{-# LANGUAGE ForeignFunctionInterface #-} #ifndef mingw32_HOST_OS #include #endif -- | module Data.Thyme.Clock.POSIX ( posixDayLength , POSIXTime , posixTime , getPOSIXTime -- * Compatibility , posixSecondsToUTCTime , utcTimeToPOSIXSeconds ) where import Prelude import Control.Lens import Data.AdditiveGroup import Data.Thyme.Internal.Micro import Data.Thyme.Clock.Internal #ifdef mingw32_HOST_OS import System.Win32.Time #else import Foreign.C.Error (throwErrnoIfMinus1_) import Foreign.C.Types import Foreign.Marshal.Alloc (allocaBytes) import Foreign.Ptr (Ptr, nullPtr) import Foreign.Storable #endif -- | The nominal (ignoring leap seconds) time difference since midnight -- 1970-01-01, the Unix epoch. Equvialent to a normalised -- @@. type POSIXTime = NominalDiffTime -- | "Control.Lens.Iso" between 'UTCTime' and 'POSIXTime'. -- -- @ -- > 'getPOSIXTime' -- 1459515013.527711s -- > 'review' 'posixTime' '<$>' 'getPOSIXTime' -- 2016-01-01 12:50:45.588729 UTC -- @ {-# INLINE posixTime #-} posixTime :: Iso' UTCTime POSIXTime posixTime = iso (\ (UTCRep t) -> t ^-^ unixEpoch) (UTCRep . (^+^) unixEpoch) where unixEpoch = review microseconds $ {-ModifiedJulianDay-}40587 * {-posixDayLength-}86400000000 -- | Return the current system POSIX time via -- @@, -- or @getSystemTimeAsFileTime@ on Windows. -- -- See also 'Data.Thyme.Clock.getCurrentTime', 'Data.Thyme.LocalTime.getZonedTime'. {-# INLINE getPOSIXTime #-} getPOSIXTime :: IO POSIXTime #ifdef mingw32_HOST_OS -- On Windows, the equlvalent of POSIX time is ‘file time’, defined as -- the number of 100-nanosecond intervals that have elapsed since -- 12:00 AM January 1, 1601 (UTC). We can convert this into a POSIX -- time by adjusting the offset to be relative to the POSIX epoch. getPOSIXTime = do FILETIME ft <- System.Win32.Time.getSystemTimeAsFileTime return . NominalDiffTime . Micro . fromIntegral $ quot ft 10 - 11644473600000000{-ftEpoch ^. microseconds-} -- ftEpoch = utcTime # UTCTime (gregorian # YearMonthDay 1601 1 1) zeroV #else getPOSIXTime = allocaBytes #{size struct timeval} $ \ ptv -> do throwErrnoIfMinus1_ "gettimeofday" $ gettimeofday ptv nullPtr CTime sec <- #{peek struct timeval, tv_sec} ptv CSUSeconds usec <- #{peek struct timeval, tv_usec} ptv return . NominalDiffTime . Micro $ 1000000 * fromIntegral sec + fromIntegral usec foreign import ccall unsafe "time.h gettimeofday" gettimeofday :: Ptr () -> Ptr () -> IO CInt #endif ------------------------------------------------------------------------ -- | Construct a 'UTCTime' from a 'POSIXTime'. -- -- @ -- 'posixSecondsToUTCTime' = 'review' 'posixTime' -- 'posixSecondsToUTCTime' t ≡ 'posixTime' 'Control.Lens.#' t -- @ {-# INLINE posixSecondsToUTCTime #-} posixSecondsToUTCTime :: POSIXTime -> UTCTime posixSecondsToUTCTime = review posixTime -- | Convert a 'UTCTime' to a 'POSIXTime'. -- -- @ -- 'utcTimeToPOSIXSeconds' = 'view' 'posixTime' -- @ {-# INLINE utcTimeToPOSIXSeconds #-} utcTimeToPOSIXSeconds :: UTCTime -> POSIXTime utcTimeToPOSIXSeconds = view posixTime