tztime-0.1.0.0: test/Test/Data/Time/TZTime/QQ.hs
-- SPDX-FileCopyrightText: 2022 Serokell <https://serokell.io/>
--
-- SPDX-License-Identifier: MPL-2.0
module Test.Data.Time.TZTime.QQ where
import Data.List (intercalate)
import Data.Time (LocalTime(..), TimeOfDay(..), TimeZone)
import Data.Time.Calendar.Compat (pattern YearMonthDay)
import Data.Time.TZInfo as TZI
import Data.Time.TZTime as TZT
import Data.Time.TZTime.Internal (TZTime(UnsafeTZTime))
import Data.Time.TZTime.QQ (tz)
import Language.Haskell.TH (runQ)
import Language.Haskell.TH.Quote (quoteExp)
import Language.Haskell.TH.TestUtils (tryTestQ, unmockedState)
import Test.Tasty.HUnit
shouldFailWith :: String -> [String] -> Assertion
shouldFailWith input expectedErrorLines = do
runQ (tryTestQ unmockedState (quoteExp tz input)) >>= \case
Left err -> err @?= expectedError
Right exp -> assertFailure $ unlines
[ "Expected QQ to fail, but it succeeded with: "
, show exp
]
where
expectedError = intercalate "\n" expectedErrorLines
unit_parses_valid_unambiguous_times :: Assertion
unit_parses_valid_unambiguous_times = do
let expected = unsafeFromLocalTime (TZI.fromLabel TZI.Europe__Rome) (LocalTime (YearMonthDay 2022 3 4) (TimeOfDay 10 15 40.123))
[tz|2022-03-04 10:15:40.123 [Europe/Rome]|] @?= expected
[tz|2022-03-04 10:15:40.123 +01:00 [Europe/Rome]|] @?= expected
unit_fails_when_time_zone_is_unknown :: Assertion
unit_fails_when_time_zone_is_unknown = do
"2022-01-01 01:02:03 [Narnia]" `shouldFailWith`
["Unknown time zone: 'Narnia'"]
unit_fails_when_time_is_valid_but_offset_is_invalid :: Assertion
unit_fails_when_time_is_valid_but_offset_is_invalid = do
"2022-03-04 10:15:40.123 +03:00 [Europe/Rome]" `shouldFailWith`
[ "Invalid offset: +03:00"
, " Did you mean any of the following?"
, " - 2022-03-04 10:15:40.123 +01:00 [Europe/Rome]"
]
unit_fails_when_time_lands_on_a_gap :: Assertion
unit_fails_when_time_lands_on_a_gap =
"2022-03-13 02:30:00 [America/Winnipeg]" `shouldFailWith`
[ "Invalid time: the clocks are set forward around this time."
, " Did you mean any of the following?"
, " - 2022-03-13 01:30:00 -06:00 [America/Winnipeg]"
, " - 2022-03-13 03:30:00 -05:00 [America/Winnipeg]"
]
unit_is_ambiguous_when_time_lands_on_an_overlap :: Assertion
unit_is_ambiguous_when_time_lands_on_an_overlap =
"2022-11-06 01:30:00 [America/Winnipeg]" `shouldFailWith`
[ "Ambiguous time: please specify an offset."
, " Did you mean any of the following?"
, " - 2022-11-06 01:30:00 -05:00 [America/Winnipeg]"
, " - 2022-11-06 01:30:00 -06:00 [America/Winnipeg]"
]
unit_is_not_ambiguous_when_time_lands_on_an_overlap_and_an_offset_is_specified :: Assertion
unit_is_not_ambiguous_when_time_lands_on_an_overlap_and_an_offset_is_specified = do
[tz|2022-11-06 01:30:00 CDT [America/Winnipeg]|] @?=
UnsafeTZTime
(LocalTime (YearMonthDay 2022 11 6) (TimeOfDay 1 30 0))
(TZI.fromLabel TZI.America__Winnipeg)
(read @TimeZone "CDT")
[tz|2022-11-06 01:30:00 CST [America/Winnipeg]|] @?=
UnsafeTZTime
(LocalTime (YearMonthDay 2022 11 6) (TimeOfDay 1 30 0))
(TZI.fromLabel TZI.America__Winnipeg)
(read @TimeZone "CST")
unit_fails_when_time_lands_on_an_overlap_and_the_offset_is_invalid :: Assertion
unit_fails_when_time_lands_on_an_overlap_and_the_offset_is_invalid = do
"2022-11-06 01:30:00 +00:00 [America/Winnipeg]" `shouldFailWith`
[ "Invalid offset: +00:00"
, " Did you mean any of the following?"
, " - 2022-11-06 01:30:00 -05:00 [America/Winnipeg]"
, " - 2022-11-06 01:30:00 -06:00 [America/Winnipeg]"
]
unit_fails_when_theres_extra_input :: Assertion
unit_fails_when_theres_extra_input = do
"2022-03-04 10:15:40.123 [Europe/Rome] more input" `shouldFailWith`
["Failed to parse: '2022-03-04 10:15:40.123 [Europe/Rome] more input'"]
unit_ignores_surrounding_whitespace :: Assertion
unit_ignores_surrounding_whitespace = do
[tz| 2022-03-04 10:15:40.123 [Europe/Rome] |] @?= [tz|2022-03-04 10:15:40.123 [Europe/Rome]|]