{-# LANGUAGE Safe #-}

-- | POSIX time, if you need to deal with timestamps and the like.
-- Most people won't need this module.
--
-- You can use 'POSIXTime' to obtain integer/word timestamps. For example:
--
-- > import Data.Time
-- > import Data.Time.Clock.POSIX
-- > import Data.Int
-- >
-- > nanosSinceEpoch :: UTCTime -> Int64
-- > nanosSinceEpoch =
-- >     floor . (1e9 *) . nominalDiffTimeToSeconds . utcTimeToPOSIXSeconds
-- >
-- > main :: IO ()
-- > main = do
-- >     u <- getCurrentTime
-- >     print $ nanosSinceEpoch u
module Data.Time.Clock.POSIX
    ( posixDayLength
    , POSIXTime
    , posixSecondsToUTCTime
    , utcTimeToPOSIXSeconds
    , getPOSIXTime
    , getCurrentTime
    , systemToPOSIXTime
    ) where

import Data.Fixed
import Data.Time.Calendar.Days
import Data.Time.Clock.Internal.POSIXTime
import Data.Time.Clock.Internal.UTCTime
import Data.Time.Clock.System

posixSecondsToUTCTime :: POSIXTime -> UTCTime
posixSecondsToUTCTime :: POSIXTime -> UTCTime
posixSecondsToUTCTime POSIXTime
i = let
    (Integer
d, POSIXTime
t) = forall a b. (Real a, Integral b) => a -> a -> (b, a)
divMod' POSIXTime
i POSIXTime
posixDayLength
    in Day -> DiffTime -> UTCTime
UTCTime (Integer -> Day -> Day
addDays Integer
d Day
systemEpochDay) (forall a b. (Real a, Fractional b) => a -> b
realToFrac POSIXTime
t)

utcTimeToPOSIXSeconds :: UTCTime -> POSIXTime
utcTimeToPOSIXSeconds :: UTCTime -> POSIXTime
utcTimeToPOSIXSeconds (UTCTime Day
d DiffTime
t) =
    (forall a. Num a => Integer -> a
fromInteger (Day -> Day -> Integer
diffDays Day
d Day
systemEpochDay) forall a. Num a => a -> a -> a
* POSIXTime
posixDayLength) forall a. Num a => a -> a -> a
+ forall a. Ord a => a -> a -> a
min POSIXTime
posixDayLength (forall a b. (Real a, Fractional b) => a -> b
realToFrac DiffTime
t)

systemToPOSIXTime :: SystemTime -> POSIXTime
systemToPOSIXTime :: SystemTime -> POSIXTime
systemToPOSIXTime (MkSystemTime Int64
s Word32
ns) = (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
s) forall a. Num a => a -> a -> a
+ (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
ns) forall a. Num a => a -> a -> a
* POSIXTime
1E-9

-- | Get the current POSIX time from the system clock.
getPOSIXTime :: IO POSIXTime
getPOSIXTime :: IO POSIXTime
getPOSIXTime = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SystemTime -> POSIXTime
systemToPOSIXTime IO SystemTime
getSystemTime

-- | Get the current 'UTCTime' from the system clock.
getCurrentTime :: IO UTCTime
getCurrentTime :: IO UTCTime
getCurrentTime = SystemTime -> UTCTime
systemToUTCTime forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` IO SystemTime
getSystemTime