Permalink
Browse files

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.
  • Loading branch information...
1 parent 5aae93c commit c0be8d48ab1f19159a2b832aa2f659994cf2fbb5 @bos bos committed Apr 11, 2011
Showing with 13 additions and 4 deletions.
  1. +13 −4 Data/Aeson/Types.hs
View
@@ -1,5 +1,5 @@
{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
- IncoherentInstances, OverlappingInstances, Rank2Types #-}
+ IncoherentInstances, OverlappingInstances, OverloadedStrings, Rank2Types #-}
-- |
-- Module: Data.Aeson.Types
@@ -639,21 +639,30 @@ instance FromJSON Value where
{-# INLINE parseJSON #-}
-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
--- serialization format as Microsoft .NET.
+-- serialization format as Microsoft .NET, whose @System.DateTime@
+-- type is by default serialized to JSON as in the following example:
+--
+-- > /Date(1302547608878)/
+--
+-- The number represents milliseconds since the Unix epoch.
newtype DotNetTime = DotNetTime {
fromDotNetTime :: UTCTime
} deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
instance ToJSON DotNetTime where
toJSON (DotNetTime t) =
- String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
+ String (pack (secs ++ msecs ++ ")/"))
+ where secs = formatTime defaultTimeLocale "/Date(%s" t
+ msecs = take 3 $ formatTime defaultTimeLocale "%q" t
{-# INLINE toJSON #-}
instance FromJSON DotNetTime where
parseJSON (String t) =
- case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
+ case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
Just d -> pure (DotNetTime d)
_ -> fail "could not parse .NET time"
+ where (s,m) = T.splitAt (T.length t - 5) t
+ t' = T.concat [s,".",m]
parseJSON v = typeMismatch "DotNetTime" v
{-# INLINE parseJSON #-}

0 comments on commit c0be8d4

Please sign in to comment.