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 -> [Char]
(Int -> ZonedTimeOfDay -> ShowS)
-> (ZonedTimeOfDay -> [Char])
-> ([ZonedTimeOfDay] -> ShowS)
-> Show ZonedTimeOfDay
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ZonedTimeOfDay -> ShowS
showsPrec :: Int -> ZonedTimeOfDay -> ShowS
$cshow :: ZonedTimeOfDay -> [Char]
show :: ZonedTimeOfDay -> [Char]
$cshowList :: [ZonedTimeOfDay] -> ShowS
showList :: [ZonedTimeOfDay] -> ShowS
Show, ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
(ZonedTimeOfDay -> ZonedTimeOfDay -> Bool)
-> (ZonedTimeOfDay -> ZonedTimeOfDay -> Bool) -> Eq ZonedTimeOfDay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
== :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
$c/= :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
/= :: ZonedTimeOfDay -> ZonedTimeOfDay -> Bool
Eq)

utc :: Local.TimeZone
utc :: TimeZone
utc = Int -> Bool -> [Char] -> TimeZone
Local.TimeZone Int
0 Bool
False [Char]
""

zonedTimeOfDay :: Text -> Aeson.Parser ZonedTimeOfDay
zonedTimeOfDay :: Text -> Parser ZonedTimeOfDay
zonedTimeOfDay Text
t =
  Parser ZonedTimeOfDay -> Text -> Either [Char] ZonedTimeOfDay
forall a. Parser a -> Text -> Either [Char] a
A.parseOnly (Parser ZonedTimeOfDay
p Parser ZonedTimeOfDay -> Parser Text () -> Parser ZonedTimeOfDay
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
endOfInput) Text
t
    Either [Char] ZonedTimeOfDay
-> ([Char] -> Parser ZonedTimeOfDay) -> Parser ZonedTimeOfDay
forall (m :: * -> *) e a.
Applicative m =>
Either e a -> (e -> m a) -> m a
`onLeft` \[Char]
err -> [Char] -> Parser ZonedTimeOfDay
forall a. [Char] -> Parser a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser ZonedTimeOfDay)
-> [Char] -> Parser ZonedTimeOfDay
forall a b. (a -> b) -> a -> b
$ [Char]
"could not parse timetz: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
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 a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
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
_ = [Char] -> Parser ZonedTimeOfDay
forall a. [Char] -> Parser a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"Expecting a string for timetz"