module Hasura.SQL.Time
  ( ZonedTimeOfDay (..),
  )
where

import Data.Aeson.Types qualified as Aeson
import Data.Attoparsec.Text as A
import Data.Attoparsec.Time (timeOfDay, timeZone)
import Data.Time.LocalTime qualified as Local
import Hasura.Prelude

data ZonedTimeOfDay = ZonedTimeOfDay
  { ZonedTimeOfDay -> TimeOfDay
ztodTime :: Local.TimeOfDay,
    ZonedTimeOfDay -> TimeZone
ztodZone :: Local.TimeZone
  }
  deriving (Int -> ZonedTimeOfDay -> ShowS
[ZonedTimeOfDay] -> ShowS
ZonedTimeOfDay -> String
(Int -> ZonedTimeOfDay -> ShowS)
-> (ZonedTimeOfDay -> String)
-> ([ZonedTimeOfDay] -> ShowS)
-> Show ZonedTimeOfDay
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ZonedTimeOfDay] -> ShowS
$cshowList :: [ZonedTimeOfDay] -> ShowS
show :: ZonedTimeOfDay -> String
$cshow :: ZonedTimeOfDay -> String
showsPrec :: Int -> ZonedTimeOfDay -> ShowS
$cshowsPrec :: Int -> ZonedTimeOfDay -> ShowS
Show, ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
(ZonedTimeOfDay -> ZonedTimeOfDay -> Bool)
-> (ZonedTimeOfDay -> ZonedTimeOfDay -> Bool) -> Eq ZonedTimeOfDay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
$c/= :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
== :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
$c== :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
Eq)

utc :: Local.TimeZone
utc :: TimeZone
utc = Int -> Bool -> String -> TimeZone
Local.TimeZone Int
0 Bool
False String
""

zonedTimeOfDay :: Text -> Aeson.Parser ZonedTimeOfDay
zonedTimeOfDay :: Text -> Parser ZonedTimeOfDay
zonedTimeOfDay Text
t =
  Parser ZonedTimeOfDay -> Text -> Either String ZonedTimeOfDay
forall a. Parser a -> Text -> Either String a
A.parseOnly (Parser ZonedTimeOfDay
p Parser ZonedTimeOfDay -> Parser Text () -> Parser ZonedTimeOfDay
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
endOfInput) Text
t
    Either String ZonedTimeOfDay
-> (String -> Parser ZonedTimeOfDay) -> Parser ZonedTimeOfDay
forall (m :: * -> *) e a.
Applicative m =>
Either e a -> (e -> m a) -> m a
`onLeft` \String
err -> String -> Parser ZonedTimeOfDay
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser ZonedTimeOfDay)
-> String -> Parser ZonedTimeOfDay
forall a b. (a -> b) -> a -> b
$ String
"could not parse timetz: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
err
  where
    p :: Parser ZonedTimeOfDay
p = TimeOfDay -> TimeZone -> ZonedTimeOfDay
ZonedTimeOfDay (TimeOfDay -> TimeZone -> ZonedTimeOfDay)
-> Parser Text TimeOfDay
-> Parser Text (TimeZone -> ZonedTimeOfDay)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text TimeOfDay
timeOfDay Parser Text (TimeZone -> ZonedTimeOfDay)
-> Parser Text TimeZone -> Parser ZonedTimeOfDay
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (TimeZone -> Maybe TimeZone -> TimeZone
forall a. a -> Maybe a -> a
fromMaybe TimeZone
utc (Maybe TimeZone -> TimeZone)
-> Parser Text (Maybe TimeZone) -> Parser Text TimeZone
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text (Maybe TimeZone)
timeZone)

instance Aeson.FromJSON ZonedTimeOfDay where
  parseJSON :: Value -> Parser ZonedTimeOfDay
parseJSON (Aeson.String Text
t) = Text -> Parser ZonedTimeOfDay
zonedTimeOfDay Text
t
  parseJSON Value
_ = String -> Parser ZonedTimeOfDay
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Expecting a string for timetz"