@@ -184,11 +184,7 @@ dayToBuilder (toGregorian -> (y,m,d)) = do
185timeOfDayToBuilder :: TimeOfDay -> Builder
185timeOfDayToBuilder :: TimeOfDay -> Builder
186timeOfDayToBuilder (TimeOfDay h m s) = do
186timeOfDayToBuilder (TimeOfDay h m s) = do
187− pad2 h ++ fromChar ':' ++ pad2 m ++ fromChar ':' ++ showSec s
187+ pad2 h ++ fromChar ':' ++ pad2 m ++ fromChar ':' ++ showSeconds s
189− showSec s = case toMicroseconds s of
191− (s,us) -> pad2 s ++ fromChar '.' ++ showMicroseconds us
193timeZoneToBuilder :: TimeZone -> Builder
189timeZoneToBuilder :: TimeZone -> Builder
194timeZoneToBuilder tz
190timeZoneToBuilder tz
@@ -231,34 +227,38 @@ localTimestampToBuilder = unboundedToBuilder localTimeToBuilder
231dateToBuilder :: Date -> Builder
227dateToBuilder :: Date -> Builder
232dateToBuilder = unboundedToBuilder dayToBuilder
228dateToBuilder = unboundedToBuilder dayToBuilder
234−toMicroseconds :: Pico -> (Int,Int)
230+showSeconds :: Pico -> Builder
233+ | z == 0 = pad2 x ++ fromChar '.' ++ showD6 y
234+ | otherwise = pad2 x ++ fromChar '.' ++ pad6 y ++ showD6 z
235−-- A kludge to work around the fact that Data.Fixed isn't very fast and doesn't
236+ -- A kludge to work around the fact that Data.Fixed isn't very fast and
236−-- give me access to the MkFixed constructor.
237+ -- doesn't give me access to the MkFixed constructor.
237−toMicroseconds p = let (x,y) = (unsafeCoerce p :: Integer)
238− `quotRem` 1000000000000
238+ (x_,yz) = (unsafeCoerce xyz :: Integer) `quotRem` 1000000000000
239+ x = fromIntegral x_ :: Int
239− (y',r) = y `quotRem` 1000000
240+ (fromIntegral -> y, fromIntegral -> z) = yz `quotRem` 1000000
240− y'' = case compare r 500000 of
241+
241− LT -> y'
242+pad6 :: Int -> Builder
242− EQ | even y' -> y'
243+pad6 xy = let (x,y) = xy `quotRem` 1000
243− _ -> y' + 1
244+ in pad3 x ++ pad3 y
244− in ( fromIntegral x, fromIntegral y'' )
245+
245−
246+showD6 :: Int -> Builder
246−-- Assumes the input is within the range [0..999999]
247+showD6 xy = case xy `quotRem` 1000 of
247−showMicroseconds :: Int -> Builder
248+ (x,0) -> showD3 x
248−showMicroseconds us =
249+ (x,y) -> pad3 x ++ showD3 y
249− case us `quotRem` 1000 of
250+
250− (ms, 0) -> case ms `quotRem` 100 of
251+pad3 :: Int -> Builder
251− (a, 0) -> p a
252+pad3 abc = let (ab,c) = abc `quotRem` 10
252− (a,ms) -> case ms `quotRem` 10 of
253+ (a,b) = ab `quotRem` 10
254− (b,c) -> p a ++ p b ++ p c
254+ in p a ++ p b ++ p c
255− (ms,us) -> case ms `quotRem` 100 of
255+
256− (a,ms) -> case ms `quotRem` 10 of
256+showD3 :: Int -> Builder
257− (b ,c) -> case us `quotRem` 100 of
257+showD3 abc = case abc `quotRem` 100 of
258− (d, 0) -> p a ++ p b ++ p c ++ p d
258+ (a, 0) -> p a
259− (d,us) -> case us `quotRem` 10 of
259+ (a,bc) -> case bc `quotRem` 10 of
260− (e , 0) -> p a ++ p b ++ p c ++ p d ++ p e
260+ (b,0) -> p a ++ p b
261− (e , f) -> p a ++ p b ++ p c ++ p d ++ p e ++ p f
261+ (b,c) -> p a ++ p b ++ p c
263-- | p assumes its input is in the range [0..9]
263-- | p assumes its input is in the range [0..9]
264p :: Integral n => n -> Builder
264p :: Integral n => n -> Builder
@@ -272,9 +272,9 @@ pad2 n = let (a,b) = n `quotRem` 10 in p a ++ p b
273-- | pad4 assumes its input is positive
273-- | pad4 assumes its input is positive
274pad4 :: (Integral n, Show n) => n -> Builder
274pad4 :: (Integral n, Show n) => n -> Builder
275−pad4 n | n >= 10000 = integral n
275+pad4 abcd | abcd >= 10000 = integral abcd
276− | otherwise = p a ++ p b ++ p c ++ p d
276+ | otherwise = p a ++ p b ++ p c ++ p d
277− where (ab,cd) = n `quotRem` 100
277+ where (ab,cd) = abcd `quotRem` 100
278− (a,b) = ab `quotRem` 10
278+ (a,b) = ab `quotRem` 10
279− (c,d) = cd `quotRem` 10
279+ (c,d) = cd `quotRem` 10
280{-# INLINE pad4 #-}
280{-# INLINE pad4 #-}