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 :: [Char] -> [Char]
fixupTzIn [Char]
s = forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
s ((forall a. [a] -> [a] -> [a]
++ [Char]
"+00:00") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse) forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix [Char]
"Z"      (forall a. [a] -> [a]
reverse [Char]
s)

-- |Given a string, remove a trailing @+00:00@ (which @FormatTime@) and replace it with @Z@ (which is ISO8601 standard)
fixupTzOut :: String -> String
fixupTzOut :: [Char] -> [Char]
fixupTzOut [Char]
s = forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
s ((forall a. [a] -> [a] -> [a]
++ [Char]
"Z")      forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse) forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix [Char]
"00:00+" (forall a. [a] -> [a]
reverse [Char]
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 :: [Char] -> [Char]
fixupMs (Char
':':Char
s10:Char
s1:Char
tzChar:[Char]
rest) | Char
tzChar forall a. Eq a => a -> a -> Bool
== Char
'Z' Bool -> Bool -> Bool
|| Char
tzChar forall a. Eq a => a -> a -> Bool
== Char
'+' Bool -> Bool -> Bool
|| Char
tzChar forall a. Eq a => a -> a -> Bool
== Char
'-' =
  Char
':'forall a. a -> [a] -> [a]
:Char
s10forall a. a -> [a] -> [a]
:Char
s1forall a. a -> [a] -> [a]
:Char
'.'forall a. a -> [a] -> [a]
:Char
'0'forall a. a -> [a] -> [a]
:Char
'0'forall a. a -> [a] -> [a]
:Char
'0'forall a. a -> [a] -> [a]
:Char
tzCharforall a. a -> [a] -> [a]
:[Char]
rest
fixupMs (Char
':':Char
s10:Char
s1:Char
'.':[Char]
digitsAndRest) =
  let ([Char]
digits, [Char]
rest) = forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit [Char]
digitsAndRest
      newDigits :: [Char]
newDigits = forall a. Int -> [a] -> [a]
take Int
3 ([Char]
digits forall a. [a] -> [a] -> [a]
++ forall a. (a -> a) -> a
fix (Char
'0'forall a. a -> [a] -> [a]
:))
  in Char
':'forall a. a -> [a] -> [a]
:Char
s10forall a. a -> [a] -> [a]
:Char
s1forall a. a -> [a] -> [a]
:Char
'.'forall a. a -> [a] -> [a]
:([Char]
newDigits forall a. [a] -> [a] -> [a]
++ [Char]
rest)
fixupMs (Char
c:[Char]
cs) = Char
c forall a. a -> [a] -> [a]
: [Char] -> [Char]
fixupMs [Char]
cs
fixupMs []     = []