{-# OPTIONS_GHC -Wno-redundant-constraints #-}

-- | Time utils.
--
-- @since 0.1
module Effectful.Time.Utils
  ( formatLocalTime,
    formatZonedTime,
    parseLocalTime,
    parseZonedTime,
  )
where

import Data.Time.Format qualified as Format
import Data.Time.LocalTime (LocalTime, ZonedTime)
import Effectful.Dispatch.Dynamic (HasCallStack)

-- | Formats the 'LocalTime' to @YYYY-MM-DD HH:MM:SS@.
--
-- @since 0.1
formatLocalTime :: LocalTime -> String
formatLocalTime :: LocalTime -> String
formatLocalTime = TimeLocale -> String -> LocalTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
Format.formatTime TimeLocale
Format.defaultTimeLocale String
localTimeFormat

-- | Formats the 'ZonedTime' to @YYYY-MM-DD HH:MM:SS Z@.
--
-- @since 0.1
formatZonedTime :: ZonedTime -> String
formatZonedTime :: ZonedTime -> String
formatZonedTime = TimeLocale -> String -> ZonedTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
Format.formatTime TimeLocale
Format.defaultTimeLocale String
zonedTimeFormat

-- | Parses the 'LocalTime' from @YYYY-MM-DD HH:MM:SS@.
--
-- @since 0.1
parseLocalTime :: (HasCallStack, MonadFail f) => String -> f LocalTime
parseLocalTime :: forall (f :: * -> *).
(HasCallStack, MonadFail f) =>
String -> f LocalTime
parseLocalTime =
  Bool -> TimeLocale -> String -> String -> f LocalTime
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
Format.parseTimeM
    Bool
True
    TimeLocale
Format.defaultTimeLocale
    String
localTimeFormat

-- | Parses the 'ZonedTime' from @YYYY-MM-DD HH:MM:SS Z@.
--
-- ==== __Known Timezones__
--
-- * UTC
-- * UT
-- * GMT
-- * EST
-- * EDT
-- * CST
-- * CDT
-- * MST
-- * MDT
-- * PST
-- * PDT
-- * +HHMM (e.g. +1300)
--
-- @since 0.1
parseZonedTime :: (HasCallStack, MonadFail f) => String -> f ZonedTime
parseZonedTime :: forall (f :: * -> *).
(HasCallStack, MonadFail f) =>
String -> f ZonedTime
parseZonedTime =
  Bool -> TimeLocale -> String -> String -> f ZonedTime
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
Format.parseTimeM
    Bool
True
    TimeLocale
Format.defaultTimeLocale
    String
zonedTimeFormat

localTimeFormat :: String
localTimeFormat :: String
localTimeFormat = String
"%0Y-%m-%d %H:%M:%S"

zonedTimeFormat :: String
zonedTimeFormat :: String
zonedTimeFormat = String
"%0Y-%m-%d %H:%M:%S %Z"