@@ -45,6 +45,7 @@ import qualified Data.Aeson.KeyMap as KM
45
45
import Data.Char (toUpper , GeneralCategory (Control ,Surrogate ), generalCategory )
46
46
import Data.Hashable (hash )
47
47
import Data.HashMap.Strict (HashMap )
48
+ import Data.Kind (Type )
48
49
import Data.List (isSuffixOf )
49
50
import Data.Maybe (fromMaybe )
50
51
import Data.Scientific (Scientific , scientific )
@@ -53,7 +54,9 @@ import Data.Text (Text)
53
54
import Data.Time (UTCTime , ZonedTime )
54
55
import Data.Time.Format.Compat (parseTimeM , defaultTimeLocale )
55
56
import GHC.Generics (Generic )
57
+ #if __GLASGOW_HASKELL__ >= 806
56
58
import GHC.Generics.Generically (Generically (.. ))
59
+ #endif
57
60
import Instances ()
58
61
import Numeric.Natural (Natural )
59
62
import Test.Tasty (TestTree , testGroup )
@@ -78,8 +81,9 @@ roundTripCamel2 :: String -> Assertion
78
81
roundTripCamel2 name = assertEqual " " name (camelFrom ' _' $ camelTo2 ' _' name)
79
82
80
83
camelFrom :: Char -> String -> String
81
- camelFrom c s = let (p: ps) = split c s
82
- in concat $ p : map capitalize ps
84
+ camelFrom c s = case split c s of
85
+ p: ps -> concat $ p : map capitalize ps
86
+ _ -> s -- shouldn't happen?
83
87
where
84
88
split c' s' = map L. unpack $ L. split c' $ L. pack s'
85
89
capitalize t = toUpper (head t) : tail t
@@ -115,38 +119,33 @@ goodProducer = assertEqual "partial encoding should not explode on undefined"
115
119
arch32bit = (maxBound :: Int ) == 2147483647
116
120
117
121
-- Test decoding various UTC time formats
118
- --
119
- -- Note: the incomplete pattern matches for UTCTimes are completely
120
- -- intentional. The test expects these parses to succeed. If the
121
- -- pattern matches fails, there's a bug in either the test or in aeson
122
- -- and needs to be investigated.
123
122
utcTimeGood :: Assertion
124
123
utcTimeGood = do
125
- let ts1 = " 2015-01-01T12:13:00.00Z" :: LT. Text
126
- let ts2 = " 2015-01-01T12:13:00Z" :: LT. Text
124
+ let ts1 = " 2015-01-01T12:13:00.00Z"
125
+ let ts2 = " 2015-01-01T12:13:00Z"
127
126
-- 'T' between date and time is not required, can be space
128
- let ts3 = " 2015-01-03 12:13:00.00Z" :: LT. Text
129
- let ts4 = " 2015-01-03 12:13:00.125Z" :: LT. Text
130
- let ( Just ( t1 :: UTCTime )) = parseWithAeson ts1
131
- let ( Just ( t2 :: UTCTime )) = parseWithAeson ts2
132
- let ( Just ( t3 :: UTCTime )) = parseWithAeson ts3
133
- let ( Just ( t4 :: UTCTime )) = parseWithAeson ts4
127
+ let ts3 = " 2015-01-03 12:13:00.00Z"
128
+ let ts4 = " 2015-01-03 12:13:00.125Z"
129
+ t1 <- parseWithAeson ts1
130
+ t2 <- parseWithAeson ts2
131
+ t3 <- parseWithAeson ts3
132
+ t4 <- parseWithAeson ts4
134
133
assertEqual " utctime" (parseWithRead " %FT%T%QZ" ts1) t1
135
134
assertEqual " utctime" (parseWithRead " %FT%T%QZ" ts2) t2
136
135
assertEqual " utctime" (parseWithRead " %F %T%QZ" ts3) t3
137
136
assertEqual " utctime" (parseWithRead " %F %T%QZ" ts4) t4
138
137
-- Time zones. Both +HHMM and +HH:MM are allowed for timezone
139
138
-- offset, and MM may be omitted.
140
- let ts5 = " 2015-01-01T12:30:00.00+00" :: LT. Text
141
- let ts6 = " 2015-01-01T12:30:00.00+01:15" :: LT. Text
142
- let ts7 = " 2015-01-01T12:30:00.00-02" :: LT. Text
143
- let ts8 = " 2015-01-01T22:00:00.00-03" :: LT. Text
144
- let ts9 = " 2015-01-01T22:00:00.00-04:30" :: LT. Text
145
- let ( Just ( t5 :: UTCTime )) = parseWithAeson ts5
146
- let ( Just ( t6 :: UTCTime )) = parseWithAeson ts6
147
- let ( Just ( t7 :: UTCTime )) = parseWithAeson ts7
148
- let ( Just ( t8 :: UTCTime )) = parseWithAeson ts8
149
- let ( Just ( t9 :: UTCTime )) = parseWithAeson ts9
139
+ let ts5 = " 2015-01-01T12:30:00.00+00"
140
+ let ts6 = " 2015-01-01T12:30:00.00+01:15"
141
+ let ts7 = " 2015-01-01T12:30:00.00-02"
142
+ let ts8 = " 2015-01-01T22:00:00.00-03"
143
+ let ts9 = " 2015-01-01T22:00:00.00-04:30"
144
+ t5 <- parseWithAeson ts5
145
+ t6 <- parseWithAeson ts6
146
+ t7 <- parseWithAeson ts7
147
+ t8 <- parseWithAeson ts8
148
+ t9 <- parseWithAeson ts9
150
149
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-01-01T12:30:00.00Z" ) t5
151
150
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-01-01T11:15:00.00Z" ) t6
152
151
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-01-01T14:30:00Z" ) t7
@@ -155,30 +154,31 @@ utcTimeGood = do
155
154
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-01-02T02:30:00Z" ) t9
156
155
157
156
-- Seconds in Time can be omitted
158
- let ts10 = " 2015-01-03T12:13Z" :: LT. Text
159
- let ts11 = " 2015-01-03 12:13Z" :: LT. Text
160
- let ts12 = " 2015-01-01T12:30-02" :: LT. Text
161
- let ( Just ( t10 :: UTCTime )) = parseWithAeson ts10
162
- let ( Just ( t11 :: UTCTime )) = parseWithAeson ts11
163
- let ( Just ( t12 :: UTCTime )) = parseWithAeson ts12
157
+ let ts10 = " 2015-01-03T12:13Z"
158
+ let ts11 = " 2015-01-03 12:13Z"
159
+ let ts12 = " 2015-01-01T12:30-02"
160
+ t10 <- parseWithAeson ts10
161
+ t11 <- parseWithAeson ts11
162
+ t12 <- parseWithAeson ts12
164
163
assertEqual " utctime" (parseWithRead " %FT%H:%MZ" ts10) t10
165
164
assertEqual " utctime" (parseWithRead " %F %H:%MZ" ts11) t11
166
165
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-01-01T14:30:00Z" ) t12
167
166
168
167
-- leap seconds are included correctly
169
- let ts13 = " 2015-08-23T23:59:60.128+00" :: LT. Text
170
- let ( Just ( t13 :: UTCTime )) = parseWithAeson ts13
168
+ let ts13 = " 2015-08-23T23:59:60.128+00"
169
+ t13 <- parseWithAeson ts13
171
170
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-08-23T23:59:60.128Z" ) t13
172
- let ts14 = " 2015-08-23T23:59:60.999999999999+00" :: LT. Text
173
- let ( Just ( t14 :: UTCTime )) = parseWithAeson ts14
171
+ let ts14 = " 2015-08-23T23:59:60.999999999999+00"
172
+ t14 <- parseWithAeson ts14
174
173
assertEqual " utctime" (parseWithRead " %FT%T%QZ" " 2015-08-23T23:59:60.999999999999Z" ) t14
175
174
176
175
where
177
176
parseWithRead :: String -> LT. Text -> UTCTime
178
177
parseWithRead f s =
179
178
fromMaybe (error " parseTime input malformed" ) . parseTimeM True defaultTimeLocale f . LT. unpack $ s
180
- parseWithAeson :: LT. Text -> Maybe UTCTime
181
- parseWithAeson s = decode . LT. encodeUtf8 $ LT. concat [" \" " , s, " \" " ]
179
+
180
+ parseWithAeson :: LT. Text -> IO UTCTime
181
+ parseWithAeson s = either fail return . eitherDecode . LT. encodeUtf8 $ LT. concat [" \" " , s, " \" " ]
182
182
183
183
-- Test that a few non-timezone qualified timestamp formats get
184
184
-- rejected if decoding to UTCTime.
@@ -659,7 +659,7 @@ bigNaturalKeyDecoding =
659
659
((eitherDecode :: L. ByteString -> Either String (HashMap Natural Value )) " { \" 1e2000\" : null }" )
660
660
661
661
-- A regression test for: https://github.com/bos/aeson/issues/757
662
- type family Fam757 :: * -> *
662
+ type family Fam757 :: Type -> Type
663
663
type instance Fam757 = Maybe
664
664
newtype Newtype757 a = MkNewtype757 (Fam757 a )
665
665
deriveToJSON1 defaultOptions ''Newtype757
0 commit comments