@@ -27,6 +27,7 @@ module Data.Aeson.Encode.Builder
2727 , day
2828 , localTime
2929 , utcTime
30+ , timeOfDay
3031 , zonedTime
3132 , ascii2
3233 , ascii4
@@ -177,26 +178,31 @@ day dd = B.integerDec y <>
177178 !(T dh dl) = twoDigits d
178179{-# INLINE day #-}
179180
180−timeOfDay :: TimeOfDay64 -> Builder
181−timeOfDay (TOD h m s)
182− | micro100 < 5 = hhmmss -- omit trailing milliseconds if zero
183− | otherwise = hhmmss <> BP.primBounded (ascii4 ('.',(a,(b,c)))) ()
181+timeOfDay :: TimeOfDay -> Builder
182+timeOfDay t = timeOfDay64 (toTimeOfDay64 t)
183+{-# INLINE timeOfDay #-}
184+
185+timeOfDay64 :: TimeOfDay64 -> Builder
186+timeOfDay64 (TOD h m s0)
187+ | frac < mu = hhmmss -- omit trailing milliseconds if zero
188+ | otherwise = hhmmss <> BP.primBounded (ascii4 ('.',(a,(b,c)))) ()
184189 where
185190 hhmmss = BP.primBounded (ascii8 (hh,(hl,(':',(mh,(ml,(':',(sh,sl)))))))) ()
186191 !(T hh hl) = twoDigits h
187192 !(T mh ml) = twoDigits m
188193 !(T sh sl) = twoDigits (fromIntegral real)
189− (real,frac) = s `quotRem` 1000000000000
190− -- Units of 100 microseconds (tenths of a millisecond), which we
191− -- round up so that milliseconds >= 0.5 render correctly.
192− micro100
193− | d `rem` 10 < 5 = d
194− | otherwise = d + 10
195− where d = fromIntegral (frac `quot` 100000000)
194+ (real,frac) = s `quotRem` pico
195+ -- Round up picoseconds so that milliseconds >= 0.5 render correctly.
196+ s | s0 `rem` mu < nu = s0
197+ | otherwise = s0 + mu
198+ tenths = fromIntegral (frac `quot` mu)
199+ pico = 1000000000000 -- 1 second in picoseconds
200+ mu = 1000000000 -- 100 microseconds
201+ nu = 500000000
196202 !(T a b) = twoDigits ab
197− (ab,cc) = micro100 `quotRem` 100
198− !c = digit (cc `quot` 10)
199−{-# INLINE timeOfDay #-}
203+ (ab,cc) = tenths `quotRem` 10
204+ !c = digit cc
205+{-# INLINE timeOfDay64 #-}
200206
201207timeZone :: TimeZone -> Builder
202208timeZone (TimeZone off _ _)
@@ -209,7 +215,7 @@ timeZone (TimeZone off _ _)
209215{-# INLINE timeZone #-}
210216
211217dayTime :: Day -> TimeOfDay64 -> Builder
212−dayTime d t = day d <> B.char7 'T' <> timeOfDay t
218+dayTime d t = day d <> B.char7 'T' <> timeOfDay64 t
213219{-# INLINE dayTime #-}
214220
215221utcTime :: UTCTime -> B.Builder