module Data.Time.TZTime
(
Internal.TZTime
, Internal.tzTimeLocalTime
, Internal.tzTimeTZInfo
, Internal.tzTimeOffset
, getCurrentTZTime
, Internal.fromUTC
, Internal.fromPOSIXTime
, Internal.fromZonedTime
, Internal.fromLocalTime
, Internal.fromLocalTimeStrict
, Internal.fromLocalTimeThrow
, Internal.unsafeFromLocalTime
, Internal.TZError(..)
, Internal.toUTC
, Internal.toPOSIXTime
, Internal.toZonedTime
, Internal.inTZ
, atEarliestOffset
, atLatestOffset
, atStartOfDay
, addTime
, hours
, minutes
, seconds
, modifyLocal
, modifyLocalStrict
, modifyLocalThrow
, addCalendarClip
, addCalendarRollOver
, calendarDays
, calendarWeeks
, calendarMonths
, calendarYears
, atYear
, atMonthOfYear
, atDayOfMonth
, atDay
, atHour
, atMinute
, atSecond
, atTimeOfDay
, atMidnight
, atFirstDayOfWeekOnAfter
, diffTZTime
) where
import Control.Exception.Safe (MonadThrow, throwM)
import Control.Monad.Except (MonadError)
import Data.Fixed (Pico)
import Data.Time
(CalendarDiffDays(..), Day, DayOfWeek(..), LocalTime(..), NominalDiffTime, TimeOfDay(..),
addUTCTime, diffUTCTime, getCurrentTime, midnight, secondsToNominalDiffTime)
import Data.Time qualified as Time
import Data.Time.Calendar.Compat
(DayOfMonth, MonthOfYear, Year, firstDayOfWeekOnAfter, pattern YearMonthDay)
import Data.Time.TZInfo
import Data.Time.TZTime.Internal as Internal
getCurrentTZTime :: IO TZTime
getCurrentTZTime :: IO TZTime
getCurrentTZTime = do
TZInfo
tzi <- IO TZInfo
getCurrentTZInfo
UTCTime
utcNow <- IO UTCTime
getCurrentTime
pure $ TZInfo -> UTCTime -> TZTime
fromUTC TZInfo
tzi UTCTime
utcNow
atEarliestOffset :: TZTime -> TZTime
atEarliestOffset :: TZTime -> TZTime
atEarliestOffset TZTime
tzt =
case TZInfo -> LocalTime -> Either TZError TZTime
forall (m :: * -> *).
MonadError TZError m =>
TZInfo -> LocalTime -> m TZTime
fromLocalTimeStrict (TZTime -> TZInfo
tzTimeTZInfo TZTime
tzt) (TZTime -> LocalTime
tzTimeLocalTime TZTime
tzt) of
Left (TZOverlap LocalTime
_ TZTime
earliest TZTime
_) -> TZTime
earliest
Either TZError TZTime
_ -> TZTime
tzt
atLatestOffset :: TZTime -> TZTime
atLatestOffset :: TZTime -> TZTime
atLatestOffset TZTime
tzt =
case TZInfo -> LocalTime -> Either TZError TZTime
forall (m :: * -> *).
MonadError TZError m =>
TZInfo -> LocalTime -> m TZTime
fromLocalTimeStrict (TZTime -> TZInfo
tzTimeTZInfo TZTime
tzt) (TZTime -> LocalTime
tzTimeLocalTime TZTime
tzt) of
Left (TZOverlap LocalTime
_ TZTime
_ TZTime
latest) -> TZTime
latest
Either TZError TZTime
_ -> TZTime
tzt
atStartOfDay :: TZTime -> TZTime
atStartOfDay :: TZTime -> TZTime
atStartOfDay TZTime
tzt =
case (LocalTime -> LocalTime) -> TZTime -> Either TZError TZTime
forall (m :: * -> *).
MonadError TZError m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
Internal.modifyLocalTimeLine LocalTime -> LocalTime
atMidnight TZTime
tzt of
Right TZTime
result -> TZTime
result
Left (TZGap LocalTime
_ TZTime
_ TZTime
after) -> TZTime
after
Left (TZOverlap LocalTime
_ TZTime
atEarliestOffset TZTime
_) -> TZTime
atEarliestOffset
addTime :: NominalDiffTime -> TZTime -> TZTime
addTime :: NominalDiffTime -> TZTime -> TZTime
addTime = (UTCTime -> UTCTime) -> TZTime -> TZTime
Internal.modifyUniversalTimeLine ((UTCTime -> UTCTime) -> TZTime -> TZTime)
-> (NominalDiffTime -> UTCTime -> UTCTime)
-> NominalDiffTime
-> TZTime
-> TZTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NominalDiffTime -> UTCTime -> UTCTime
addUTCTime
hours :: Pico -> NominalDiffTime
hours :: Pico -> NominalDiffTime
hours Pico
h = Pico -> NominalDiffTime
minutes (Pico
h Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
* Pico
60)
minutes :: Pico -> NominalDiffTime
minutes :: Pico -> NominalDiffTime
minutes Pico
m = Pico -> NominalDiffTime
seconds (Pico
m Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
* Pico
60)
seconds :: Pico -> NominalDiffTime
seconds :: Pico -> NominalDiffTime
seconds = Pico -> NominalDiffTime
secondsToNominalDiffTime
modifyLocal :: (LocalTime -> LocalTime) -> TZTime -> TZTime
modifyLocal :: (LocalTime -> LocalTime) -> TZTime -> TZTime
modifyLocal LocalTime -> LocalTime
f TZTime
tzt =
case (LocalTime -> LocalTime) -> TZTime -> Either TZError TZTime
forall (m :: * -> *).
MonadError TZError m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalStrict LocalTime -> LocalTime
f TZTime
tzt of
Right TZTime
result -> TZTime
result
Left (TZGap LocalTime
_ TZTime
_ TZTime
after) -> TZTime
after
Left (TZOverlap LocalTime
_ TZTime
atEarliestOffset TZTime
atLatestOffset)
| TZTime -> TimeZone
tzTimeOffset TZTime
atLatestOffset TimeZone -> TimeZone -> Bool
forall a. Eq a => a -> a -> Bool
== TZTime -> TimeZone
tzTimeOffset TZTime
tzt -> TZTime
atLatestOffset
| Bool
otherwise -> TZTime
atEarliestOffset
modifyLocalStrict :: MonadError TZError m => (LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalStrict :: forall (m :: * -> *).
MonadError TZError m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalStrict = (LocalTime -> LocalTime) -> TZTime -> m TZTime
forall (m :: * -> *).
MonadError TZError m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
Internal.modifyLocalTimeLine
modifyLocalThrow :: MonadThrow m => (LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalThrow :: forall (m :: * -> *).
MonadThrow m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalThrow LocalTime -> LocalTime
f =
(TZError -> m TZTime)
-> (TZTime -> m TZTime) -> Either TZError TZTime -> m TZTime
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either TZError -> m TZTime
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM TZTime -> m TZTime
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either TZError TZTime -> m TZTime)
-> (TZTime -> Either TZError TZTime) -> TZTime -> m TZTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LocalTime -> LocalTime) -> TZTime -> Either TZError TZTime
forall (m :: * -> *).
MonadError TZError m =>
(LocalTime -> LocalTime) -> TZTime -> m TZTime
modifyLocalStrict LocalTime -> LocalTime
f
addCalendarClip :: CalendarDiffDays -> LocalTime -> LocalTime
addCalendarClip :: CalendarDiffDays -> LocalTime -> LocalTime
addCalendarClip CalendarDiffDays
cdd LocalTime
lt = LocalTime
lt
{ localDay :: Day
localDay = CalendarDiffDays -> Day -> Day
Time.addGregorianDurationClip CalendarDiffDays
cdd (Day -> Day) -> Day -> Day
forall a b. (a -> b) -> a -> b
$ LocalTime -> Day
localDay LocalTime
lt
}
addCalendarRollOver :: CalendarDiffDays -> LocalTime -> LocalTime
addCalendarRollOver :: CalendarDiffDays -> LocalTime -> LocalTime
addCalendarRollOver CalendarDiffDays
cdd LocalTime
lt = LocalTime
lt
{ localDay :: Day
localDay = CalendarDiffDays -> Day -> Day
Time.addGregorianDurationRollOver CalendarDiffDays
cdd (Day -> Day) -> Day -> Day
forall a b. (a -> b) -> a -> b
$ LocalTime -> Day
localDay LocalTime
lt
}
calendarDays :: Integer -> CalendarDiffDays
calendarDays :: Integer -> CalendarDiffDays
calendarDays Integer
n = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
0 Integer
n
calendarWeeks :: Integer -> CalendarDiffDays
calendarWeeks :: Integer -> CalendarDiffDays
calendarWeeks Integer
n = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
0 (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
7)
calendarMonths :: Integer -> CalendarDiffDays
calendarMonths :: Integer -> CalendarDiffDays
calendarMonths Integer
n = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
n Integer
0
calendarYears :: Integer -> CalendarDiffDays
calendarYears :: Integer -> CalendarDiffDays
calendarYears Integer
n = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
12) Integer
0
atYear :: Year -> LocalTime -> LocalTime
atYear :: Integer -> LocalTime -> LocalTime
atYear Integer
y LocalTime
lt =
let YearMonthDay Integer
_ MonthOfYear
moy MonthOfYear
dom = LocalTime -> Day
localDay LocalTime
lt
in LocalTime
lt { localDay :: Day
localDay = Integer -> MonthOfYear -> MonthOfYear -> Day
YearMonthDay Integer
y MonthOfYear
moy MonthOfYear
dom }
atMonthOfYear :: MonthOfYear -> LocalTime -> LocalTime
atMonthOfYear :: MonthOfYear -> LocalTime -> LocalTime
atMonthOfYear MonthOfYear
moy LocalTime
lt =
let YearMonthDay Integer
y MonthOfYear
_ MonthOfYear
dom = LocalTime -> Day
localDay LocalTime
lt
in LocalTime
lt { localDay :: Day
localDay = Integer -> MonthOfYear -> MonthOfYear -> Day
YearMonthDay Integer
y MonthOfYear
moy MonthOfYear
dom }
atDayOfMonth :: DayOfMonth -> LocalTime -> LocalTime
atDayOfMonth :: MonthOfYear -> LocalTime -> LocalTime
atDayOfMonth MonthOfYear
dom LocalTime
lt =
let YearMonthDay Integer
y MonthOfYear
m MonthOfYear
_ = LocalTime -> Day
localDay LocalTime
lt
in LocalTime
lt { localDay :: Day
localDay = Integer -> MonthOfYear -> MonthOfYear -> Day
YearMonthDay Integer
y MonthOfYear
m MonthOfYear
dom }
atDay :: Day -> LocalTime -> LocalTime
atDay :: Day -> LocalTime -> LocalTime
atDay Day
day LocalTime
lt = LocalTime
lt { localDay :: Day
localDay = Day
day }
atHour :: Int -> LocalTime -> LocalTime
atHour :: MonthOfYear -> LocalTime -> LocalTime
atHour MonthOfYear
h LocalTime
lt = LocalTime
lt
{ localTimeOfDay :: TimeOfDay
localTimeOfDay = (LocalTime -> TimeOfDay
localTimeOfDay LocalTime
lt) { todHour :: MonthOfYear
todHour = MonthOfYear
h }
}
atMinute :: Int -> LocalTime -> LocalTime
atMinute :: MonthOfYear -> LocalTime -> LocalTime
atMinute MonthOfYear
m LocalTime
lt = LocalTime
lt
{ localTimeOfDay :: TimeOfDay
localTimeOfDay = (LocalTime -> TimeOfDay
localTimeOfDay LocalTime
lt) { todMin :: MonthOfYear
todMin = MonthOfYear
m }
}
atSecond :: Pico -> LocalTime -> LocalTime
atSecond :: Pico -> LocalTime -> LocalTime
atSecond Pico
s LocalTime
lt = LocalTime
lt
{ localTimeOfDay :: TimeOfDay
localTimeOfDay = (LocalTime -> TimeOfDay
localTimeOfDay LocalTime
lt) { todSec :: Pico
todSec = Pico
s }
}
atTimeOfDay :: TimeOfDay -> LocalTime -> LocalTime
atTimeOfDay :: TimeOfDay -> LocalTime -> LocalTime
atTimeOfDay TimeOfDay
tod LocalTime
lt = LocalTime
lt { localTimeOfDay :: TimeOfDay
localTimeOfDay = TimeOfDay
tod }
atMidnight :: LocalTime -> LocalTime
atMidnight :: LocalTime -> LocalTime
atMidnight = TimeOfDay -> LocalTime -> LocalTime
atTimeOfDay TimeOfDay
midnight
atFirstDayOfWeekOnAfter :: DayOfWeek -> LocalTime -> LocalTime
atFirstDayOfWeekOnAfter :: DayOfWeek -> LocalTime -> LocalTime
atFirstDayOfWeekOnAfter DayOfWeek
dow LocalTime
lt = LocalTime
lt
{ localDay :: Day
localDay = DayOfWeek -> Day -> Day
firstDayOfWeekOnAfter DayOfWeek
dow (Day -> Day) -> Day -> Day
forall a b. (a -> b) -> a -> b
$ LocalTime -> Day
localDay LocalTime
lt
}
diffTZTime :: TZTime -> TZTime -> NominalDiffTime
diffTZTime :: TZTime -> TZTime -> NominalDiffTime
diffTZTime TZTime
tzt1 TZTime
tzt2 =
UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime (TZTime -> UTCTime
toUTC TZTime
tzt1) (TZTime -> UTCTime
toUTC TZTime
tzt2)