module Composite.Aeson.DateTimeFormatUtils ( fixupTzIn, fixupTzOut, fixupMs ) where import Data.Char (isDigit) import Data.Function (fix) import Data.List (stripPrefix) -- |Given a string, remove a trailing @Z@ (which is ISO8601 acceptable) and replace it with @+00:00@ (which is @ParseTime@ acceptable) fixupTzIn :: String -> String fixupTzIn s = maybe s ((++ "+00:00") . reverse) $ stripPrefix "Z" (reverse s) -- |Given a string, remove a trailing @+00:00@ (which @FormatTime@) and replace it with @Z@ (which is ISO8601 standard) fixupTzOut :: String -> String fixupTzOut s = maybe s ((++ "Z") . reverse) $ stripPrefix "00:00+" (reverse s) -- |Given a ISO8601-ish string generated by @FormatTime@ with @%Q@, generating between no decimal and 12 digits of decimal, normalize it to exactly -- three digits. -- -- E.g. from @2017-03-30T13:00:00Z@ generate @2017-03-30T13:00:00.000Z@, and from @2017-03-30T13:00:00.123456789Z@ generate @2017-03-30T12:00:00.123Z@ fixupMs :: String -> String fixupMs (':':s10:s1:tzChar:rest) | tzChar == 'Z' || tzChar == '+' || tzChar == '-' = ':':s10:s1:'.':'0':'0':'0':tzChar:rest fixupMs (':':s10:s1:'.':digitsAndRest) = let (digits, rest) = span isDigit digitsAndRest newDigits = take 3 (digits ++ fix ('0':)) in ':':s10:s1:'.':(newDigits ++ rest) fixupMs (c:cs) = c : fixupMs cs fixupMs [] = []