Skip to content

Commit 7c0dd50

Browse files
committed
Restore parsing of fractional seconds in the Created field.
The old show/read format always included fractional seconds in the `Created` field; this fixes a bug that was introduced in 9667923 This commit restored parsing fractional seconds, and modified parsing to allow either format.
1 parent 162a32f commit 7c0dd50

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

src/Database/Schema/Migrations/Filesystem.hs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ where
1111
import Prelude
1212

1313
import Control.Exception (Exception (..), catch, throw)
14-
import Control.Monad (filterM)
14+
import Control.Monad (filterM, msum)
1515
import Data.Aeson
1616
import Data.Aeson.Types (typeMismatch)
1717
import Data.ByteString.Char8 qualified as BSC
@@ -147,18 +147,28 @@ newtype UTCTimeYaml = UTCTimeYaml
147147

148148
instance FromJSON UTCTimeYaml where
149149
parseJSON =
150-
withText "UTCTime" $
151-
maybe (fail "Unable to parse UTCTime") (pure . UTCTimeYaml)
152-
. parseTimeM True defaultTimeLocale utcTimeYamlFormat
153-
. cs
150+
withText "UTCTime" $ \t ->
151+
let s = cs t
152+
in case msum [parseTimeM True defaultTimeLocale fmt s | fmt <- utcTimeParseFormats] of
153+
Nothing -> fail "Unable to parse UTCTime"
154+
Just utc -> pure $ UTCTimeYaml utc
154155

155156
instance ToJSON UTCTimeYaml where
156-
toJSON = toJSON . formatTime defaultTimeLocale utcTimeYamlFormat . unUTCTimeYaml
157-
toEncoding = toEncoding . formatTime defaultTimeLocale utcTimeYamlFormat . unUTCTimeYaml
158-
159-
-- Keeps things as the old Show/Read-based format, e.g "2009-04-15 10:02:06 UTC"
160-
utcTimeYamlFormat :: String
161-
utcTimeYamlFormat = "%F %T%Q UTC"
157+
toJSON = toJSON . formatTime defaultTimeLocale utcTimeWriteFormat . unUTCTimeYaml
158+
toEncoding = toEncoding . formatTime defaultTimeLocale utcTimeWriteFormat . unUTCTimeYaml
159+
160+
-- | Canonical output format: the old Show/Read-based format,
161+
-- e.g "2009-04-15 10:02:06.123456 UTC"
162+
utcTimeWriteFormat :: String
163+
utcTimeWriteFormat = "%F %T%Q UTC"
164+
165+
-- | Accepted input formats, tried in order. Lenient parsing accepts
166+
-- timestamps with or without fractional seconds.
167+
utcTimeParseFormats :: [String]
168+
utcTimeParseFormats =
169+
[ "%F %T%Q UTC" -- "2009-04-15 10:02:06.123456 UTC" (with fractional seconds)
170+
, "%F %T UTC" -- "2009-04-15 10:02:06 UTC" (without fractional seconds)
171+
]
162172

163173
newtype DependsYaml = DependsYaml
164174
{ unDependsYaml :: [Text]

tests/FilesystemParseSpec.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ spec = do
3434
it "fully valid" $ do
3535
migrationFromFile' "valid_full" `shouldReturn` Right validFull
3636

37+
it "fully valid with fractional seconds in timestamp" $ do
38+
migrationFromFile' "valid_full_fractional_ts"
39+
`shouldReturn` Right (validFullFractionalTs {mId = "valid_full_fractional_ts"})
40+
3741
it "comments" $ do
3842
migrationFromFile' "valid_with_comments"
3943
`shouldReturn` Right (validFull {mId = "valid_with_comments"})
@@ -154,3 +158,17 @@ ts = read tsStr
154158

155159
tsStr :: String
156160
tsStr = "2009-04-15 10:02:06 UTC"
161+
162+
validFullFractionalTs :: Migration
163+
validFullFractionalTs =
164+
Migration
165+
{ mTimestamp = Just tsFractional
166+
, mId = "valid_full_fractional_ts"
167+
, mDesc = Just "A valid full migration with fractional seconds."
168+
, mDeps = ["another_migration"]
169+
, mApply = "CREATE TABLE test ( a int );"
170+
, mRevert = Just "DROP TABLE test;"
171+
}
172+
173+
tsFractional :: UTCTime
174+
tsFractional = read "2009-04-15 10:02:06.123456 UTC"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Description: A valid full migration with fractional seconds.
2+
Created: 2009-04-15 10:02:06.123456 UTC
3+
Depends: another_migration
4+
Apply:
5+
6+
CREATE TABLE test (
7+
a int
8+
);
9+
10+
Revert: DROP TABLE test;

0 commit comments

Comments
 (0)