    {-# LANGUAGE Safe #-}

    {-# OPTIONS -fno-warn-orphans #-}

    module Data.Time.LocalTime.Internal.LocalTime where

    import Control.DeepSeq
    import Data.Data
    import Data.Time.Calendar.Days
    import Data.Time.Calendar.Gregorian
    import Data.Time.Clock.Internal.NominalDiffTime
    import Data.Time.Clock.Internal.UTCDiff
    import Data.Time.Clock.Internal.UTCTime
    import Data.Time.Clock.Internal.UniversalTime
    import Data.Time.LocalTime.Internal.CalendarDiffTime
    import Data.Time.LocalTime.Internal.TimeOfDay
    import Data.Time.LocalTime.Internal.TimeZone
    import GHC.Generics
    import Language.Haskell.TH.Syntax qualified as TH

    -- | A simple day and time aggregate, where the day is of the specified parameter,
    -- and the time is a TimeOfDay.
    -- Conversion of this (as local civil time) to UTC depends on the time zone.
    -- Conversion of this (as local mean time) to UT1 depends on the longitude.
    data LocalTime = LocalTime
        { LocalTime -> Day
    localDay :: Day
        , LocalTime -> TimeOfDay
    localTimeOfDay :: TimeOfDay
        }
        deriving (LocalTime -> LocalTime -> Bool
    (LocalTime -> LocalTime -> Bool)
    -> (LocalTime -> LocalTime -> Bool) -> Eq LocalTime
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LocalTime -> LocalTime -> Bool
    == :: LocalTime -> LocalTime -> Bool
    $c/= :: LocalTime -> LocalTime -> Bool
    /= :: LocalTime -> LocalTime -> Bool
    Eq, Eq LocalTime
    Eq LocalTime =>
    (LocalTime -> LocalTime -> Ordering)
    -> (LocalTime -> LocalTime -> Bool)
    -> (LocalTime -> LocalTime -> Bool)
    -> (LocalTime -> LocalTime -> Bool)
    -> (LocalTime -> LocalTime -> Bool)
    -> (LocalTime -> LocalTime -> LocalTime)
    -> (LocalTime -> LocalTime -> LocalTime)
    -> Ord LocalTime
    LocalTime -> LocalTime -> Bool
    LocalTime -> LocalTime -> Ordering
    LocalTime -> LocalTime -> LocalTime
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: LocalTime -> LocalTime -> Ordering
    compare :: LocalTime -> LocalTime -> Ordering
    $c< :: LocalTime -> LocalTime -> Bool
    < :: LocalTime -> LocalTime -> Bool
    $c<= :: LocalTime -> LocalTime -> Bool
    <= :: LocalTime -> LocalTime -> Bool
    $c> :: LocalTime -> LocalTime -> Bool
    > :: LocalTime -> LocalTime -> Bool
    $c>= :: LocalTime -> LocalTime -> Bool
    >= :: LocalTime -> LocalTime -> Bool
    $cmax :: LocalTime -> LocalTime -> LocalTime
    max :: LocalTime -> LocalTime -> LocalTime
    $cmin :: LocalTime -> LocalTime -> LocalTime
    min :: LocalTime -> LocalTime -> LocalTime
    Ord, Typeable, Typeable LocalTime
    Typeable LocalTime =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> LocalTime -> c LocalTime)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c LocalTime)
    -> (LocalTime -> Constr)
    -> (LocalTime -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c LocalTime))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c LocalTime))
    -> ((forall b. Data b => b -> b) -> LocalTime -> LocalTime)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> LocalTime -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> LocalTime -> r)
    -> (forall u. (forall d. Data d => d -> u) -> LocalTime -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> LocalTime -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime)
    -> Data LocalTime
    LocalTime -> Constr
    LocalTime -> DataType
    (forall b. Data b => b -> b) -> LocalTime -> LocalTime
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> LocalTime -> u
    forall u. (forall d. Data d => d -> u) -> LocalTime -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c LocalTime
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> LocalTime -> c LocalTime
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c LocalTime)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c LocalTime)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> LocalTime -> c LocalTime
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> LocalTime -> c LocalTime
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c LocalTime
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c LocalTime
    $ctoConstr :: LocalTime -> Constr
    toConstr :: LocalTime -> Constr
    $cdataTypeOf :: LocalTime -> DataType
    dataTypeOf :: LocalTime -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c LocalTime)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c LocalTime)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c LocalTime)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c LocalTime)
    $cgmapT :: (forall b. Data b => b -> b) -> LocalTime -> LocalTime
    gmapT :: (forall b. Data b => b -> b) -> LocalTime -> LocalTime
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> LocalTime -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> LocalTime -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> LocalTime -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> LocalTime -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> LocalTime -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LocalTime -> m LocalTime
    Data, (forall x. LocalTime -> Rep LocalTime x)
    -> (forall x. Rep LocalTime x -> LocalTime) -> Generic LocalTime
    forall x. Rep LocalTime x -> LocalTime
    forall x. LocalTime -> Rep LocalTime x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. LocalTime -> Rep LocalTime x
    from :: forall x. LocalTime -> Rep LocalTime x
    $cto :: forall x. Rep LocalTime x -> LocalTime
    to :: forall x. Rep LocalTime x -> LocalTime
    Generic, (forall (m :: * -> *). Quote m => LocalTime -> m Exp)
    -> (forall (m :: * -> *). Quote m => LocalTime -> Code m LocalTime)
    -> Lift LocalTime
    forall t.
    (forall (m :: * -> *). Quote m => t -> m Exp)
    -> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
    forall (m :: * -> *). Quote m => LocalTime -> m Exp
    forall (m :: * -> *). Quote m => LocalTime -> Code m LocalTime
    $clift :: forall (m :: * -> *). Quote m => LocalTime -> m Exp
    lift :: forall (m :: * -> *). Quote m => LocalTime -> m Exp
    $cliftTyped :: forall (m :: * -> *). Quote m => LocalTime -> Code m LocalTime
    liftTyped :: forall (m :: * -> *). Quote m => LocalTime -> Code m LocalTime
    TH.Lift)

    instance NFData LocalTime where
        rnf :: LocalTime -> ()
    rnf (LocalTime Day
    d TimeOfDay
    t) = Day -> ()
    forall a. NFData a => a -> ()
    rnf Day
    d () -> () -> ()
    forall a b. a -> b -> b
    `seq` TimeOfDay -> ()
    forall a. NFData a => a -> ()
    rnf TimeOfDay
    t () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    instance Show LocalTime where
        show :: LocalTime -> String
    show (LocalTime Day
    d TimeOfDay
    t) = (Day -> String
    showGregorian Day
    d) String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ (TimeOfDay -> String
    forall a. Show a => a -> String
    show TimeOfDay
    t)

    -- | addLocalTime a b = a + b
    addLocalTime :: NominalDiffTime -> LocalTime -> LocalTime
    addLocalTime :: NominalDiffTime -> LocalTime -> LocalTime
    addLocalTime NominalDiffTime
    x = TimeZone -> UTCTime -> LocalTime
    utcToLocalTime TimeZone
    utc (UTCTime -> LocalTime)
    -> (LocalTime -> UTCTime) -> LocalTime -> LocalTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . NominalDiffTime -> UTCTime -> UTCTime
    addUTCTime NominalDiffTime
    x (UTCTime -> UTCTime)
    -> (LocalTime -> UTCTime) -> LocalTime -> UTCTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TimeZone -> LocalTime -> UTCTime
    localTimeToUTC TimeZone
    utc

    -- | diffLocalTime a b = a - b
    diffLocalTime :: LocalTime -> LocalTime -> NominalDiffTime
    diffLocalTime :: LocalTime -> LocalTime -> NominalDiffTime
    diffLocalTime LocalTime
    a LocalTime
    b = UTCTime -> UTCTime -> NominalDiffTime
    diffUTCTime (TimeZone -> LocalTime -> UTCTime
    localTimeToUTC TimeZone
    utc LocalTime
    a) (TimeZone -> LocalTime -> UTCTime
    localTimeToUTC TimeZone
    utc LocalTime
    b)

    -- | Get the local time of a UTC time in a time zone.
    utcToLocalTime :: TimeZone -> UTCTime -> LocalTime
    utcToLocalTime :: TimeZone -> UTCTime -> LocalTime
    utcToLocalTime TimeZone
    tz (UTCTime Day
    day DiffTime
    dt) = Day -> TimeOfDay -> LocalTime
    LocalTime (Integer -> Day -> Day
    addDays Integer
    i Day
    day) TimeOfDay
    tod
      where
        (Integer
    i, TimeOfDay
    tod) = TimeZone -> TimeOfDay -> (Integer, TimeOfDay)
    utcToLocalTimeOfDay TimeZone
    tz (DiffTime -> TimeOfDay
    timeToTimeOfDay DiffTime
    dt)

    -- | Get the UTC time of a local time in a time zone.
    localTimeToUTC :: TimeZone -> LocalTime -> UTCTime
    localTimeToUTC :: TimeZone -> LocalTime -> UTCTime
    localTimeToUTC TimeZone
    tz (LocalTime Day
    day TimeOfDay
    tod) = Day -> DiffTime -> UTCTime
    UTCTime (Integer -> Day -> Day
    addDays Integer
    i Day
    day) (TimeOfDay -> DiffTime
    timeOfDayToTime TimeOfDay
    todUTC)
      where
        (Integer
    i, TimeOfDay
    todUTC) = TimeZone -> TimeOfDay -> (Integer, TimeOfDay)
    localToUTCTimeOfDay TimeZone
    tz TimeOfDay
    tod

    -- | Get the local time of a UT1 time on a particular meridian (in degrees, positive is East).
    ut1ToLocalTime :: Rational -> UniversalTime -> LocalTime
    ut1ToLocalTime :: Rational -> UniversalTime -> LocalTime
    ut1ToLocalTime Rational
    long (ModJulianDate Rational
    date) =
        Day -> TimeOfDay -> LocalTime
    LocalTime (Integer -> Day
    ModifiedJulianDay Integer
    localMJD) (Rational -> TimeOfDay
    dayFractionToTimeOfDay Rational
    localToDOffset)
      where
        localTime :: Rational
    localTime = Rational
    date Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Rational
    long Rational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    / Rational
    360 :: Rational
        localMJD :: Integer
    localMJD = Rational -> Integer
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    floor Rational
    localTime
        localToDOffset :: Rational
    localToDOffset = Rational
    localTime Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    - (Integer -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    localMJD)

    -- | Get the UT1 time of a local time on a particular meridian (in degrees, positive is East).
    localTimeToUT1 :: Rational -> LocalTime -> UniversalTime
    localTimeToUT1 :: Rational -> LocalTime -> UniversalTime
    localTimeToUT1 Rational
    long (LocalTime (ModifiedJulianDay Integer
    localMJD) TimeOfDay
    tod) =
        Rational -> UniversalTime
    ModJulianDate ((Integer -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    localMJD) Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + (TimeOfDay -> Rational
    timeOfDayToDayFraction TimeOfDay
    tod) Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    - (Rational
    long Rational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    / Rational
    360))

    -- orphan instance
    instance Show UniversalTime where
        show :: UniversalTime -> String
    show UniversalTime
    t = LocalTime -> String
    forall a. Show a => a -> String
    show (Rational -> UniversalTime -> LocalTime
    ut1ToLocalTime Rational
    0 UniversalTime
    t)

    addLocalDurationClip :: CalendarDiffTime -> LocalTime -> LocalTime
    addLocalDurationClip :: CalendarDiffTime -> LocalTime -> LocalTime
    addLocalDurationClip (CalendarDiffTime Integer
    m NominalDiffTime
    d) (LocalTime Day
    day TimeOfDay
    t) =
        NominalDiffTime -> LocalTime -> LocalTime
    addLocalTime NominalDiffTime
    d (LocalTime -> LocalTime) -> LocalTime -> LocalTime
    forall a b. (a -> b) -> a -> b
    $ Day -> TimeOfDay -> LocalTime
    LocalTime (Integer -> Day -> Day
    addGregorianMonthsClip Integer
    m Day
    day) TimeOfDay
    t

    addLocalDurationRollOver :: CalendarDiffTime -> LocalTime -> LocalTime
    addLocalDurationRollOver :: CalendarDiffTime -> LocalTime -> LocalTime
    addLocalDurationRollOver (CalendarDiffTime Integer
    m NominalDiffTime
    d) (LocalTime Day
    day TimeOfDay
    t) =
        NominalDiffTime -> LocalTime -> LocalTime
    addLocalTime NominalDiffTime
    d (LocalTime -> LocalTime) -> LocalTime -> LocalTime
    forall a b. (a -> b) -> a -> b
    $ Day -> TimeOfDay -> LocalTime
    LocalTime (Integer -> Day -> Day
    addGregorianMonthsRollOver Integer
    m Day
    day) TimeOfDay
    t

    diffLocalDurationClip :: LocalTime -> LocalTime -> CalendarDiffTime
    diffLocalDurationClip :: LocalTime -> LocalTime -> CalendarDiffTime
    diffLocalDurationClip (LocalTime Day
    day1 TimeOfDay
    t1) (LocalTime Day
    day2 TimeOfDay
    t2) =
        let
            CalendarDiffTime Integer
    m NominalDiffTime
    t = CalendarDiffDays -> CalendarDiffTime
    calendarTimeDays (CalendarDiffDays -> CalendarDiffTime)
    -> CalendarDiffDays -> CalendarDiffTime
    forall a b. (a -> b) -> a -> b
    $ Day -> Day -> CalendarDiffDays
    diffGregorianDurationClip Day
    day1 Day
    day2
        in
            Integer -> NominalDiffTime -> CalendarDiffTime
    CalendarDiffTime Integer
    m (NominalDiffTime -> CalendarDiffTime)
    -> NominalDiffTime -> CalendarDiffTime
    forall a b. (a -> b) -> a -> b
    $ NominalDiffTime
    t NominalDiffTime -> NominalDiffTime -> NominalDiffTime
    forall a. Num a => a -> a -> a
    + TimeOfDay -> TimeOfDay -> NominalDiffTime
    diffTimeOfDay TimeOfDay
    t1 TimeOfDay
    t2

    diffLocalDurationRollOver :: LocalTime -> LocalTime -> CalendarDiffTime
    diffLocalDurationRollOver :: LocalTime -> LocalTime -> CalendarDiffTime
    diffLocalDurationRollOver (LocalTime Day
    day1 TimeOfDay
    t1) (LocalTime Day
    day2 TimeOfDay
    t2) =
        let
            CalendarDiffTime Integer
    m NominalDiffTime
    t = CalendarDiffDays -> CalendarDiffTime
    calendarTimeDays (CalendarDiffDays -> CalendarDiffTime)
    -> CalendarDiffDays -> CalendarDiffTime
    forall a b. (a -> b) -> a -> b
    $ Day -> Day -> CalendarDiffDays
    diffGregorianDurationRollOver Day
    day1 Day
    day2
        in
            Integer -> NominalDiffTime -> CalendarDiffTime
    CalendarDiffTime Integer
    m (NominalDiffTime -> CalendarDiffTime)
    -> NominalDiffTime -> CalendarDiffTime
    forall a b. (a -> b) -> a -> b
    $ NominalDiffTime
    t NominalDiffTime -> NominalDiffTime -> NominalDiffTime
    forall a. Num a => a -> a -> a
    + TimeOfDay -> TimeOfDay -> NominalDiffTime
    diffTimeOfDay TimeOfDay
    t1 TimeOfDay
    t2