@@ -25,8 +25,6 @@ module Data.Aeson.Encode.Builder
25 , unquoted
25 , unquoted
31 , zonedTime
29 , zonedTime
@@ -41,12 +39,14 @@ import Data.ByteString.Builder.Prim as BP
41import Data.ByteString.Builder.Scientific (scientificBuilder)
39import Data.ByteString.Builder.Scientific (scientificBuilder)
42import Data.Char (chr, ord)
40import Data.Char (chr, ord)
43import Data.Foldable (foldMap)
41import Data.Foldable (foldMap)
42+import Data.Int (Int64)
44import Data.Monoid ((<>))
43import Data.Monoid ((<>))
45import Data.Scientific (Scientific, base10Exponent, coefficient)
44import Data.Scientific (Scientific, base10Exponent, coefficient)
46−import Data.Time (UTCTime(..))
45+import Data.Time (DiffTime, UTCTime(..))
47import Data.Time.Calendar (Day(..), toGregorian)
46import Data.Time.Calendar (Day(..), toGregorian)
48import Data.Time.LocalTime
47import Data.Time.LocalTime
49import Data.Word (Word8)
48import Data.Word (Word8)
49+import Unsafe.Coerce (unsafeCoerce)
50import qualified Data.HashMap.Strict as HMS
50import qualified Data.HashMap.Strict as HMS
51import qualified Data.Text as T
51import qualified Data.Text as T
52import qualified Data.Text.Encoding as TE
52import qualified Data.Text.Encoding as TE
@@ -177,8 +177,8 @@ day dd = B.integerDec y <>
177 !(T dh dl) = twoDigits d
177 !(T dh dl) = twoDigits d
178{-# INLINE day #-}
178{-# INLINE day #-}
180−timeOfDay :: TimeOfDay -> Builder
180+timeOfDay :: TimeOfDay64 -> Builder
181−timeOfDay (TimeOfDay h m s)
181+timeOfDay (TOD h m s)
182 | micro100 < 5 = hhmmss -- omit trailing milliseconds if zero
182 | micro100 < 5 = hhmmss -- omit trailing milliseconds if zero
183 | otherwise = hhmmss <> BP.primBounded (ascii4 ('.',(a,(b,c)))) ()
183 | otherwise = hhmmss <> BP.primBounded (ascii4 ('.',(a,(b,c)))) ()
@@ -186,8 +186,7 @@ timeOfDay (TimeOfDay h m s)
186 !(T hh hl) = twoDigits h
186 !(T hh hl) = twoDigits h
187 !(T mh ml) = twoDigits m
187 !(T mh ml) = twoDigits m
188 !(T sh sl) = twoDigits (fromIntegral real)
188 !(T sh sl) = twoDigits (fromIntegral real)
190− (real,frac) = picos `quotRem` 1000000000000
189+ (real,frac) = s `quotRem` 1000000000000
191 -- Units of 100 microseconds (tenths of a millisecond), which we
190 -- Units of 100 microseconds (tenths of a millisecond), which we
192 -- round up so that milliseconds >= 0.5 render correctly.
191 -- round up so that milliseconds >= 0.5 render correctly.
@@ -209,16 +208,30 @@ timeZone (TimeZone off _ _)
209 (h,m) = abs off `quotRem` 60
208 (h,m) = abs off `quotRem` 60
210{-# INLINE timeZone #-}
209{-# INLINE timeZone #-}
212−dayTime :: Day -> TimeOfDay -> Builder
211+dayTime :: Day -> TimeOfDay64 -> Builder
213dayTime d t = day d <> B.char7 'T' <> timeOfDay t
212dayTime d t = day d <> B.char7 'T' <> timeOfDay t
214{-# INLINE dayTime #-}
213{-# INLINE dayTime #-}
216utcTime :: UTCTime -> B.Builder
215utcTime :: UTCTime -> B.Builder
217−utcTime (UTCTime d s) = dayTime d (timeToTimeOfDay s) <> B.char7 'Z'
216+utcTime (UTCTime d s) = dayTime d (diffTimeOfDay64 s) <> B.char7 'Z'
218{-# INLINE utcTime #-}
217{-# INLINE utcTime #-}
219+data TimeOfDay64 = TOD {-# UNPACK #-} !Int
221+ {-# UNPACK #-} !Int64
223+diffTimeOfDay64 :: DiffTime -> TimeOfDay64
224+diffTimeOfDay64 t = TOD (fromIntegral h) (fromIntegral m) s
225+ where (h,mp) = fromIntegral pico `quotRem` 3600000000000000
226+ (m,s) = mp `quotRem` 60000000000000
227+ pico = unsafeCoerce t :: Integer
229+toTimeOfDay64 :: TimeOfDay -> TimeOfDay64
230+toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))
220zonedTime :: ZonedTime -> Builder
232zonedTime :: ZonedTime -> Builder
221−zonedTime (ZonedTime (LocalTime d t) z) = dayTime d t <> timeZone z
233+zonedTime (ZonedTime (LocalTime d t) z) =
234+ dayTime d (toTimeOfDay64 t) <> timeZone z
222{-# INLINE zonedTime #-}
235{-# INLINE zonedTime #-}
224data T = T {-# UNPACK #-} !Char {-# UNPACK #-} !Char
237data T = T {-# UNPACK #-} !Char {-# UNPACK #-} !Char