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

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