1{-# LANGUAGE QuasiQuotes #-}
7fromString . toString == id ** Todo?
9toString . fromString == almost id ** Todo?
11postgresql -> haskell -> postgresql * Done
13haskell -> postgresql -> haskell ** Todo?
15But still, what we really want to establish is that the two values
16correspond; for example, a conversion that consistently added hour
17when printed to a string and subtracted an hour when parsed from string
18would still pass these tests.
21Right now, we are checking that 1400+ timestamps in the range of 1860 to
222060 round trip from postgresql to haskell and back in 5 different timezones.
23In addition to UTC, the four timezones were selected so that 2 have a positive
24offset, and 2 have a negative offset, and that 2 have an offset of a
25whole number of hours, while the other two do not.
27It may be worth adding a few more timezones to ensure better test coverage.
29We are checking a handful of selected timestamps to ensure we hit
30various corner-cases in the code, in addition to 1400 timestamps randomly
31generated with granularity of seconds down to microseconds in powers of ten.
35module Time (testTime) where
38import Control.Monad(forM_, replicateM_)
39import Data.Time.Compat
40import Data.ByteString(ByteString)
41import Database.PostgreSQL.Simple.SqlQQ
46testTime :: TestEnv -> Assertion
47testTime env@TestEnv{..} = do
49 execute_ conn "SET timezone TO 'UTC'"
50 checkRoundTrips env "1860-01-01 00:00:00+00"
51 execute_ conn "SET timezone TO 'America/Chicago'" -- -5:00
52 checkRoundTrips env "1883-11-18 12:00:00-06"
53 execute_ conn "SET timezone TO 'Asia/Tokyo'" -- +9:00
54 checkRoundTrips env "1888-01-01 00:00:00+09"
55 execute_ conn "SET timezone TO 'Asia/Kathmandu'" -- +5:45
56 checkRoundTrips env "1919-12-31 23:48:44+05:30"
57 execute_ conn "SET timezone TO 'America/St_Johns'" -- -3:30
58 checkRoundTrips env "1935-03-30 00:00:52-03:30"
60initializeTable :: TestEnv -> IO ()
61initializeTable TestEnv{..} = withTransaction conn $ do
63 [sql| CREATE TEMPORARY TABLE testtime
64 ( x serial, y timestamptz, PRIMARY KEY(x) ) |]
66 let test :: ByteString -> IO () = \x -> do
68 INSERT INTO testtime (y) VALUES (?)
72 test "1883-11-18 11:59:59-05:50:36"
73 test "1883-11-18 12:09:23-05:50:36"
74 test "1883-11-18 12:00:00-06"
76 test "1887-12-31 23:59:59+09:18:59"
77 test "1888-01-01 00:18:58+09:18:59"
78 test "1888-01-01 00:00:00+09"
80 test "1919-12-31 23:59:59+05:41:16"
81 test "1919-12-31 23:48:44+05:30"
82 test "1985-12-31 23:59:59+05:30"
83 test "1986-01-01 00:15:00+05:45"
85 test "1935-03-29 23:59:59-03:30:52"
86 test "1935-03-30 00:00:52-03:30"
88 -- While the above special cases are probably a decent start, there
89 -- are probably more that are well worth adding to ensure better
92 let pop :: ByteString -> Double -> IO () = \x y ->
93 replicateM_ numTests $ execute conn
94 [sql| INSERT INTO testtime (y) VALUES
95 ('1860-01-01 00:00:00+00'::timestamptz
96 + ?::interval * ROUND(RANDOM() * ?)) |] (x,y)
97 pop "1 microsecond" 6.3113904e15
98 pop "10 microseconds" 6.3113904e14
99 pop "100 microseconds" 6.3113904e13
100 pop "1 millisecond" 6.3113904e12
101 pop "10 milliseconds" 6.3113904e11
102 pop "100 milliseconds" 6.3113904e10
103 pop "1 second" 6.3113904e9
105checkRoundTrips :: TestEnv -> ByteString -> IO ()
106checkRoundTrips TestEnv{..} limit = do
107 yxs :: [(UTCTime, Int)] <- query_ conn [sql| SELECT y, x FROM testtime |]
108 forM_ yxs $ \yx -> do
109 res <- query conn [sql| SELECT y=? FROM testtime WHERE x=? |] yx
110 assertBool "UTCTime did not round-trip from SQL to Haskell and back" $
113 yxs :: [(ZonedTime, Int)] <- query conn [sql|
114 SELECT y, x FROM testtime WHERE y > ?
116 forM_ yxs $ \yx -> do
117 res <- query conn [sql| SELECT y=? FROM testtime WHERE x=? |] yx
118 assertBool "ZonedTime did not round-trip from SQL to Haskell and back" $
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list