Skip to content

Commit f8b5413

Browse files
authored
Merge pull request #1046 from haskell/issue-272-tz-offsets
Resolve #272. Allow 23:59 as maximum/minimum tz offset
2 parents 9a48ced + 3774a8d commit f8b5413

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

text-iso8601/src/Data/Time/FromText.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ parseTimeOfDay = parseTimeOfDay_ kontEOF $ \_ _ _ c _ -> unexpectedChar c "end-o
131131
--
132132
-- The accepted formats are @Z@, @+HH@, @+HHMM@, or @+HH:MM@. (@+@ can be @-@).
133133
--
134+
-- Accepts @-23:59..23:59@ range, i.e. @HH < 24@ and @MM < 59@.
135+
-- (This is consistent with grammar, and with what Python, Clojure, joda-time do).
136+
--
134137
parseTimeZone :: Text -> Either String Local.TimeZone
135138
parseTimeZone = parseTimeZone_ Right
136139

@@ -485,11 +488,9 @@ parseTimeZone__ x kont c t0 = case c of
485488

486489
withResult :: (Int -> Int) -> Int -> Int -> (Local.TimeZone -> Either String b) -> Either String b
487490
withResult posNeg hh mm kontR =
488-
let off = posNeg (hh * 60 + mm)
489-
in if off < (-720) || off > 840 || mm > 59
490-
then Left $ "Invalid TimeZone:" ++ show (hh, mm)
491-
else kontR (Local.minutesToTimeZone off)
492-
491+
if hh < 24 && mm < 60
492+
then kontR (Local.minutesToTimeZone (posNeg (hh * 60 + mm)))
493+
else Left $ "Invalid TimeZone:" ++ show (hh, mm)
493494

494495
{-# INLINE parseLocalTime_ #-}
495496
parseLocalTime_

text-iso8601/tests/text-iso8601-tests.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ main = defaultMain $ testGroup "text-iso8601"
5757
-- ISO8601 allows various offsets, while RFC3339 only +-HH:MM
5858
, accepts T.parseUTCTime "1990-12-31T15:59:60-0800" -- no colon
5959
, accepts T.parseUTCTime "1990-12-31T15:59:60-08" -- just hour
60+
61+
-- accepts +23:59
62+
, accepts T.parseUTCTime "1937-01-01T12:00:00+23:59"
63+
, accepts T.parseUTCTime "1937-01-01T12:00:00-23:59"
6064
]
6165

6266
, testGroup "rejected"
@@ -70,6 +74,10 @@ main = defaultMain $ testGroup "text-iso8601"
7074
-- RFC3339 says we MAY limit, i.e. requiring they should be uppercase.
7175
, rejects T.parseUTCTime "2023-06-09T02:35:33z"
7276
, rejects T.parseUTCTime "2023-06-09t02:35:33Z"
77+
78+
-- accepts +23:59, but not 24 or 60
79+
, rejects T.parseUTCTime "1937-01-01T12:00:00+24:59"
80+
, rejects T.parseUTCTime "1937-01-01T12:00:00-23:60"
7381
]
7482
]
7583

@@ -91,13 +99,13 @@ roundtrip eq build parse = testProperty (show (typeRep (Proxy :: Proxy a))) $ \x
9199
property (liftEq eq y (Right x))
92100

93101
rejects :: forall a. (Typeable a, Show a) => (Text -> Either String a) -> String -> TestTree
94-
rejects parse inp = testCase (show (typeRep (Proxy :: Proxy a)) ++ " accepts " ++ show inp) $ do
102+
rejects parse inp = testCase (show (typeRep (Proxy :: Proxy a)) ++ " rejects " ++ show inp) $ do
95103
case parse (T.pack inp) of
96104
Left _ -> return ()
97105
Right a -> assertFailure $ "Unexpectedly accepted: " ++ show a
98106

99107
accepts :: forall a. (Typeable a, Show a) => (Text -> Either String a) -> String -> TestTree
100-
accepts parse inp = testCase (show (typeRep (Proxy :: Proxy a)) ++ " rejects " ++ show inp) $ do
108+
accepts parse inp = testCase (show (typeRep (Proxy :: Proxy a)) ++ " accepts " ++ show inp) $ do
101109
case parse (T.pack inp) of
102110
Left err -> assertFailure $ "Unexpectedly rejected: " ++ err
103111
Right _ -> return ()

0 commit comments

Comments
 (0)