on master help sign in
Parse and serialize .NET System.DateTime values correctly.
9a67be9Bryan O'Sullivan
Data/Aeson/Types.hs+13−4
@@ -1,5 +1,5 @@
1{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
1{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
2− IncoherentInstances, OverlappingInstances, Rank2Types #-}
2+ IncoherentInstances, OverlappingInstances, OverloadedStrings, Rank2Types #-}
3
3
4-- |
4-- |
5-- Module: Data.Aeson.Types
5-- Module: Data.Aeson.Types
@@ -639,21 +639,30 @@ instance FromJSON Value where
639 {-# INLINE parseJSON #-}
639 {-# INLINE parseJSON #-}
640
640
641-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
641-- | 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.
643newtype DotNetTime = DotNetTime {
648newtype DotNetTime = DotNetTime {
644 fromDotNetTime :: UTCTime
649 fromDotNetTime :: UTCTime
645 } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
650 } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
646
651
647instance ToJSON DotNetTime where
652instance ToJSON DotNetTime where
648 toJSON (DotNetTime t) =
653 toJSON (DotNetTime t) =
654+ String (pack (secs ++ msecs ++ ")/"))
649− String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
655+ where secs = formatTime defaultTimeLocale "/Date(%s" t
656+ msecs = take 3 $ formatTime defaultTimeLocale "%q" t
650 {-# INLINE toJSON #-}
657 {-# INLINE toJSON #-}
651
658
652instance FromJSON DotNetTime where
659instance FromJSON DotNetTime where
653 parseJSON (String t) =
660 parseJSON (String t) =
654− case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
661+ case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
655 Just d -> pure (DotNetTime d)
662 Just d -> pure (DotNetTime d)
656 _ -> fail "could not parse .NET time"
663 _ -> fail "could not parse .NET time"
664+ where (s,m) = T.splitAt (T.length t - 5) t
665+ t' = T.concat [s,".",m]
657 parseJSON v = typeMismatch "DotNetTime" v
666 parseJSON v = typeMismatch "DotNetTime" v
658 {-# INLINE parseJSON #-}
667 {-# INLINE parseJSON #-}
659
668