on master help sign in
Parse and serialize .NET System.DateTime values correctly.

The number in parentheses in the default JSON serialization of a a .NET DateTime is milliseconds since the Unix epoch, whereas I had been treating it as seconds.

commit9a67be9d38a033be918225c46456b5a0195b7de1 authorBryan O'Sullivan <bos@mailrank.com> dateMon 11 Apr 2011, 12:10 (16 years ago) parentd57e76a
1 file changed+13−4
Data/Aeson/Types.hs+13−4
Data/Aeson/Types.hs+13−4
@@ -1,5 +1,5 @@
11{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
2− IncoherentInstances, OverlappingInstances, Rank2Types #-}
2+ IncoherentInstances, OverlappingInstances, OverloadedStrings, Rank2Types #-}
33
44-- |
55-- Module: Data.Aeson.Types
@@ -639,21 +639,30 @@ instance FromJSON Value where
639639 {-# INLINE parseJSON #-}
640640
641641-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
642−-- serialization format as Microsoft .NET.
642+-- serialization format as Microsoft .NET, whose @System.DateTime@
643+-- type is by default serialized to JSON as in the following example:
644+--
645+-- > /Date(1302547608878)/
646+--
647+-- The number represents milliseconds since the Unix epoch.
643648newtype DotNetTime = DotNetTime {
644649 fromDotNetTime :: UTCTime
645650 } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
646651
647652instance ToJSON DotNetTime where
648653 toJSON (DotNetTime t) =
649− String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
654+ String (pack (secs ++ msecs ++ ")/"))
655+ where secs = formatTime defaultTimeLocale "/Date(%s" t
656+ msecs = take 3 $ formatTime defaultTimeLocale "%q" t
650657 {-# INLINE toJSON #-}
651658
652659instance FromJSON DotNetTime where
653660 parseJSON (String t) =
654− case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
661+ case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
655662 Just d -> pure (DotNetTime d)
656663 _ -> fail "could not parse .NET time"
664+ where (s,m) = T.splitAt (T.length t - 5) t
665+ t' = T.concat [s,".",m]
657666 parseJSON v = typeMismatch "DotNetTime" v
658667 {-# INLINE parseJSON #-}
659668