    -- |
    -- Module      : Data.Hourglass.Internal.Unix
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Time lowlevel helpers for the unix operating system
    --
    -- depend on localtime_r and gmtime_r.
    -- Some obscure unix system might not support them.
    --
    module Data.Hourglass.Internal.Unix
        ( dateTimeFromUnixEpochP
        , dateTimeFromUnixEpoch
        , systemGetTimezone
        , systemGetElapsed
        , systemGetElapsedP
        ) where

    import Data.Hourglass.Types
    import Data.Time.Calendar.MonthDay
    import Data.Time.Calendar.OrdinalDate
    import Data.Time.LocalTime hiding (TimeOfDay(..))
    import qualified Data.Time.LocalTime as DTLocalTime
    import Data.Time.Clock.System

    -- | convert a unix epoch precise to DateTime
    dateTimeFromUnixEpochP :: ElapsedP -> DateTime
    dateTimeFromUnixEpochP :: ElapsedP -> DateTime
    dateTimeFromUnixEpochP (ElapsedP (Elapsed Seconds
    sec) (NanoSeconds Int64
    ns)) =
        Date -> TimeOfDay -> DateTime
    DateTime Date
    date TimeOfDay
    time
      where systime :: SystemTime
    systime = Int64 -> Word32 -> SystemTime
    MkSystemTime (Seconds -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Seconds
    sec) (Int64 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    ns)
            utctime :: UTCTime
    utctime = SystemTime -> UTCTime
    systemToUTCTime SystemTime
    systime
            LocalTime Day
    day TimeOfDay
    timeofday = TimeZone -> UTCTime -> LocalTime
    utcToLocalTime TimeZone
    utc UTCTime
    utctime
            (Year
    year, DayOfYear
    dayofyear) = Day -> (Year, DayOfYear)
    toOrdinalDate Day
    day
            (DayOfYear
    monthofyear, DayOfYear
    dayofmonth) = Bool -> DayOfYear -> (DayOfYear, DayOfYear)
    dayOfYearToMonthAndDay (Year -> Bool
    isLeapYear Year
    year) DayOfYear
    dayofyear
            date :: Date
    date = Date
                { dateYear :: DayOfYear
    dateYear  = Year -> DayOfYear
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Year
    year
                , dateMonth :: Month
    dateMonth = DayOfYear -> Month
    forall a. Enum a => DayOfYear -> a
    toEnum (DayOfYear
    monthofyear DayOfYear -> DayOfYear -> DayOfYear
    forall a. Num a => a -> a -> a
    - DayOfYear
    1)
                , dateDay :: DayOfYear
    dateDay   = DayOfYear
    dayofmonth
                }
            time :: TimeOfDay
    time = TimeOfDay
                { todHour :: Hours
    todHour = DayOfYear -> Hours
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (DayOfYear -> Hours) -> DayOfYear -> Hours
    forall a b. (a -> b) -> a -> b
    $ TimeOfDay -> DayOfYear
    DTLocalTime.todHour TimeOfDay
    timeofday
                , todMin :: Minutes
    todMin  = DayOfYear -> Minutes
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (DayOfYear -> Minutes) -> DayOfYear -> Minutes
    forall a b. (a -> b) -> a -> b
    $ TimeOfDay -> DayOfYear
    DTLocalTime.todMin TimeOfDay
    timeofday
                , todSec :: Seconds
    todSec  = Pico -> Seconds
    forall b. Integral b => Pico -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    floor (Pico -> Seconds) -> Pico -> Seconds
    forall a b. (a -> b) -> a -> b
    $ TimeOfDay -> Pico
    DTLocalTime.todSec TimeOfDay
    timeofday
                , todNSec :: NanoSeconds
    todNSec = Int64 -> NanoSeconds
    NanoSeconds Int64
    ns
                }

    -- | convert a unix epoch to DateTime
    dateTimeFromUnixEpoch :: Elapsed -> DateTime
    dateTimeFromUnixEpoch :: Elapsed -> DateTime
    dateTimeFromUnixEpoch Elapsed
    e = ElapsedP -> DateTime
    dateTimeFromUnixEpochP (ElapsedP -> DateTime) -> ElapsedP -> DateTime
    forall a b. (a -> b) -> a -> b
    $ Elapsed -> NanoSeconds -> ElapsedP
    ElapsedP Elapsed
    e NanoSeconds
    0

    -- | return the timezone offset in minutes
    systemGetTimezone :: IO TimezoneOffset
    systemGetTimezone :: IO TimezoneOffset
    systemGetTimezone = do
        TimeZone DayOfYear
    tzm Bool
    _ String
    _ <- IO TimeZone
    getCurrentTimeZone
        TimezoneOffset -> IO TimezoneOffset
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TimezoneOffset -> IO TimezoneOffset)
    -> TimezoneOffset -> IO TimezoneOffset
    forall a b. (a -> b) -> a -> b
    $ DayOfYear -> TimezoneOffset
    TimezoneOffset DayOfYear
    tzm

    ----------------------------------------------------------------------------------------
    -- | return the current elapsedP
    systemGetElapsedP :: IO ElapsedP
    systemGetElapsedP :: IO ElapsedP
    systemGetElapsedP = do
        MkSystemTime Int64
    sec Word32
    nsec <- IO SystemTime
    getSystemTime
        ElapsedP -> IO ElapsedP
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ElapsedP -> IO ElapsedP) -> ElapsedP -> IO ElapsedP
    forall a b. (a -> b) -> a -> b
    $ Elapsed -> NanoSeconds -> ElapsedP
    ElapsedP (Int64 -> Elapsed
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    sec) (Word32 -> NanoSeconds
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    nsec)

    -- | return the current elapsed
    systemGetElapsed :: IO Elapsed
    systemGetElapsed :: IO Elapsed
    systemGetElapsed = do
        ElapsedP Elapsed
    e NanoSeconds
    _ <- IO ElapsedP
    systemGetElapsedP
        Elapsed -> IO Elapsed
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Elapsed
    e