module Data.API.Utils
( mkUTC
, mkUTC'
, mkUTC_
, parseUTC'
, parseUTC_
, (?!)
, (?!?)
, MergeResult(..)
, mergeMaps
, diffMaps
, matchMaps
) where
import Data.Aeson
import Data.Map ( Map )
import qualified Data.Map as Map
import Data.Maybe
import qualified Data.Text as T
import Data.Time
#if MIN_VERSION_time(1,5,0)
#else
import System.Locale (defaultTimeLocale)
#endif
mkUTC :: UTCTime -> Value
mkUTC = String . mkUTC'
utcFormat :: String
utcFormat = "%Y-%m-%dT%H:%M:%SZ"
utcFormats :: [String]
utcFormats =
[ "%Y-%m-%dT%H:%M:%S%z"
, "%Y-%m-%dT%H:%M:%S%Z"
, "%Y-%m-%dT%H:%M%Z"
, "%Y-%m-%dT%H:%M:%S%QZ"
, utcFormat
]
mkUTC' :: UTCTime -> T.Text
mkUTC' = T.pack . mkUTC_
mkUTC_ :: UTCTime -> String
mkUTC_ utct = formatTime defaultTimeLocale utcFormat utct
parseUTC' :: T.Text -> Maybe UTCTime
parseUTC' t = parseUTC_ $ T.unpack t
parseUTC_ :: String -> Maybe UTCTime
parseUTC_ s = listToMaybe $ catMaybes $
map (\fmt->parseTime defaultTimeLocale fmt s) utcFormats
(?!) :: Maybe a -> e -> Either e a
Nothing ?! e = Left e
Just x ?! _ = Right x
(?!?) :: Either e a -> (e -> e') -> Either e' a
Left e ?!? f = Left (f e)
Right x ?!? _ = Right x
data MergeResult a b = OnlyInLeft a | InBoth a b | OnlyInRight b
deriving (Eq, Show)
mergeMaps :: Ord k => Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps m1 m2 = Map.unionWith (\(OnlyInLeft a) (OnlyInRight b) -> InBoth a b)
(fmap OnlyInLeft m1) (fmap OnlyInRight m2)
diffMaps :: (Eq a, Ord k) => Map k a -> Map k a -> Map k (MergeResult a a)
diffMaps m1 m2 = Map.filter different $ mergeMaps m1 m2
where
different (InBoth a b) = a /= b
different _ = True
matchMaps :: Ord k => Map k a -> Map k b -> Either (k, Either a b) (Map k (a, b))
matchMaps m1 m2 = Map.traverseWithKey win $ mergeMaps m1 m2
where
win _ (InBoth x y) = return (x, y)
win k (OnlyInLeft x) = Left (k, Left x)
win k (OnlyInRight x) = Left (k, Right x)