Closed mdorman closed 10 years ago
I don't think it's correct to drop the milliseconds. What do you mean by “a superfluous '.' before the time zone 'Z'”? Could you show me the JSON before you store it into CouchDB and right after it's read back in?
I think I found a problem in Aeson. The take 23
is wrong if the year won't fit into 4 digits, such that the last digit(s) of the milliseconds are dropped: (ZonedTime
doesn't use take 23
.)
instance ToJSON UTCTime where
toJSON t = String (pack (take 23 str ++ "Z"))
where str = formatTime defaultTimeLocale "%FT%T.%q" t
{-# INLINE toJSON #-}
Your dropping of the milliseconds ‘fixed’ it by giving it more wiggle room. (It'll still fail if the year takes more than 8 digits…) I'll figure out a fix that's acceptable for both thyme and aeson.
For now, you may want to restrict your years to the range (0, 9999). Something like:
> quickCheck $ \ ut -> let t = ut & _utctDayTime . microseconds %~ (\ us -> us `div` 1000 * 1000) & _utctDay . gregorian . _ymdYear %~ (`mod` 1000) in fromJSON (toJSON t) == Data.Aeson.Success t
+++ OK, passed 100 tests.
Let me know if this fixes your issue, and whether you'd prefer I make a new release soon.
Doing some round-trip testing through CouchDB using the Arbitrary instances, I was ending up with strings with a superfluous '.' before the time zone 'Z', which was causing them to fail to be read back in.
These tests have been rock-solid using ZonedTime, but I recently made the decision to start storing UTCTime, and suddenly failures started springing up---so I know my round-trip strategy should work.
I removed the storing of millis entirely, and things went back to working.