    -- |
    -- Module      : Time.Compat
    -- License     : BSD-style
    -- Maintainer  : Nicolas DI PRIMA <nicolas@di-prima.fr>
    --
    -- Basic Time conversion compatibility.
    --
    -- This module aims to help conversion between the types from the package
    -- time to the package hourglass.
    --
    -- Example of use (extracted from file Example/Time/Compat.hs):
    --
    -- > import Data.Hourglass        as H
    -- > import Data.Hourglass.Compat as C
    -- > import Data.Time             as T
    -- >
    -- > transpose :: T.ZonedTime
    -- >           -> H.LocalTime H.DateTime
    -- > transpose oldTime =
    -- >     H.localTime
    -- >         offsetTime
    -- >         (H.DateTime newDate timeofday)
    -- >   where
    -- >     newDate :: H.Date
    -- >     newDate = C.dateFromTAIEpoch $ T.toModifiedJulianDay $ T.localDay $ T.zonedTimeToLocalTime oldTime
    -- >
    -- >     timeofday :: H.TimeOfDay
    -- >     timeofday = C.diffTimeToTimeOfDay $ T.timeOfDayToTime $ T.localTimeOfDay $ T.zonedTimeToLocalTime oldTime
    -- >
    -- >     offsetTime = H.TimezoneOffset $ fromIntegral $ T.timeZoneMinutes $ T.zonedTimeZone oldTime
    --
    module Time.Compat
        ( dateFromPOSIXEpoch
        , dateFromTAIEpoch
        , diffTimeToTimeOfDay
        ) where

    import Data.Hourglass

    -- | Convert an integer which represent the Number of days (To/From) POSIX Epoch
    -- to a Date (POSIX Epoch is 1970-01-01).
    dateFromPOSIXEpoch :: Integer -- ^ number of days since POSIX Epoch
                       -> Date
    dateFromPOSIXEpoch :: Integer -> Date
    dateFromPOSIXEpoch day :: Integer
    day = do
        let sec :: Elapsed
    sec = Seconds -> Elapsed
    Elapsed (Seconds -> Elapsed) -> Seconds -> Elapsed
    forall a b. (a -> b) -> a -> b
    $ Integer -> Seconds
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Integer -> Seconds) -> Integer -> Seconds
    forall a b. (a -> b) -> a -> b
    $ Integer
    day Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * 86400
        Elapsed -> Date
    forall t1 t2. (Timeable t1, Time t2) => t1 -> t2
    timeConvert Elapsed
    sec

    -- | Number of days between POSIX Epoch and TAI Epoch
    -- (between 1858-11-17 and 1970-01-01)
    daysTAItoPOSIX :: Integer
    daysTAItoPOSIX :: Integer
    daysTAItoPOSIX = 40587

    -- | Convert an integer which represents the Number of days (To/From) TAI Epoch
    -- This function allows use of the package time to easily convert the Day into
    -- the Hourglass Date representation (TAI Epoch is 1858-11-17).
    --
    -- This function allows user to easily convert a Data.Time.Calendar.Day into Date
    --
    -- > import qualified Data.Time.Calendar as T
    -- >
    -- > timeDay :: T.Day
    -- >
    -- > dateFromTAIEpoch $ T.toModifiedJulianDay timeDay
    dateFromTAIEpoch :: Integer -- ^ number of days since TAI Epoch
                     -> Date
    dateFromTAIEpoch :: Integer -> Date
    dateFromTAIEpoch dtai :: Integer
    dtai =
        Integer -> Date
    dateFromPOSIXEpoch (Integer
    dtai Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    daysTAItoPOSIX)

    -- | Convert of differential of time of a day.
    -- (it convers a Data.Time.Clock.DiffTime into a TimeOfDay)
    --
    -- Example with DiffTime type from time:
    --
    -- > import qualified Data.Time.Clock as T
    -- >
    -- > difftime :: T.DiffTime
    -- >
    -- > diffTimeToTimeOfDay difftime
    --
    -- Example with the TimeOfDay type from time:
    --
    -- > import qualified Data.Time.Clock as T
    -- >
    -- > timeofday :: T.TimeOfDay
    -- >
    -- > diffTimeToTimeOfDay $ T.timeOfDayToTime timeofday
    diffTimeToTimeOfDay :: Real t
                        => t         -- ^ number of seconds of the time of the day
                        -> TimeOfDay
    diffTimeToTimeOfDay :: t -> TimeOfDay
    diffTimeToTimeOfDay dt :: t
    dt = do
        $WTimeOfDay :: Hours -> Minutes -> Seconds -> NanoSeconds -> TimeOfDay
    TimeOfDay
            { todHour :: Hours
    todHour = Integer -> Hours
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    hours
            , todMin :: Minutes
    todMin  = Integer -> Minutes
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    minutes
            , todSec :: Seconds
    todSec  = Integer -> Seconds
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    seconds
            , todNSec :: NanoSeconds
    todNSec = Integer -> NanoSeconds
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    nsecs
            }
      where
        r :: Rational
        r :: Rational
    r = t -> Rational
    forall a. Real a => a -> Rational
    toRational t
    dt
        (secs :: Integer
    secs, nR :: Rational
    nR) = Rational -> (Integer, Rational)
    forall a b. (RealFrac a, Integral b) => a -> (b, a)
    properFraction Rational
    r :: (Integer, Rational)
        nsecs :: Integer
        nsecs :: Integer
    nsecs = Rational -> Integer
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Rational
    nR Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * 1000000000)
        (minsofday :: Integer
    minsofday, seconds :: Integer
    seconds) = Integer
    secs Integer -> Integer -> (Integer, Integer)
    forall a. Integral a => a -> a -> (a, a)
    `divMod` 60 :: (Integer, Integer)
        (hours :: Integer
    hours, minutes :: Integer
    minutes) = Integer
    minsofday Integer -> Integer -> (Integer, Integer)
    forall a. Integral a => a -> a -> (a, a)
    `divMod` 60 :: (Integer, Integer)