{-# 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) = POSIXTime -> POSIXTime -> (Integer, POSIXTime)
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) (POSIXTime -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac POSIXTime
t)

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

systemToPOSIXTime :: SystemTime -> POSIXTime
systemToPOSIXTime :: SystemTime -> POSIXTime
systemToPOSIXTime (MkSystemTime Int64
s Word32
ns) = (Int64 -> POSIXTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
s) POSIXTime -> POSIXTime -> POSIXTime
forall a. Num a => a -> a -> a
+ (Word32 -> POSIXTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
ns) POSIXTime -> POSIXTime -> POSIXTime
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 = (SystemTime -> POSIXTime) -> IO SystemTime -> IO POSIXTime
forall a b. (a -> b) -> IO a -> IO b
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 (SystemTime -> UTCTime) -> IO SystemTime -> IO UTCTime
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` IO SystemTime
getSystemTime