format everything with hindent
[packages/time.git] / lib / Data / Time / Clock / Internal / SystemTime.hs
1 {-# OPTIONS -fno-warn-trustworthy-safe #-}
2 {-# LANGUAGE Trustworthy #-}
3
4 module Data.Time.Clock.Internal.SystemTime
5 ( SystemTime(..)
6 , getSystemTime
7 , getTime_resolution
8 , getTAISystemTime
9 ) where
10
11 import Control.DeepSeq
12 import Data.Int (Int64)
13 import Data.Time.Clock.Internal.DiffTime
14 import Data.Word
15 #include "HsTimeConfig.h"
16
17 #ifdef mingw32_HOST_OS
18 import qualified System.Win32.Time as Win32
19 #elif defined(HAVE_CLOCK_GETTIME)
20 import Data.Time.Clock.Internal.CTimespec
21 import Foreign.C.Types (CLong(..), CTime(..))
22 #else
23 import Data.Time.Clock.Internal.CTimeval
24 import Foreign.C.Types (CLong(..))
25 #endif
26 --------------------------------------------------------------------------------
27 -- | 'SystemTime' is time returned by system clock functions.
28 -- Its semantics depends on the clock function, but the epoch is typically the beginning of 1970.
29 -- Note that 'systemNanoseconds' of 1E9 to 2E9-1 can be used to represent leap seconds.
30 data SystemTime = MkSystemTime
31 { systemSeconds :: {-# UNPACK #-}!Int64
32 , systemNanoseconds :: {-# UNPACK #-}!Word32
33 } deriving (Eq, Ord, Show)
34
35 instance NFData SystemTime where
36 rnf a = a `seq` ()
37
38 -- | Get the system time, epoch start of 1970 UTC, leap-seconds ignored.
39 -- 'getSystemTime' is typically much faster than 'getCurrentTime'.
40 getSystemTime :: IO SystemTime
41 -- | The resolution of 'getSystemTime', 'getCurrentTime', 'getPOSIXTime'
42 getTime_resolution :: DiffTime
43 -- | If supported, get TAI time, epoch start of 1970 TAI, with resolution.
44 -- This is supported only on UNIX systems, and only those with CLOCK_TAI available at run-time.
45 getTAISystemTime :: Maybe (DiffTime, IO SystemTime)
46 #ifdef mingw32_HOST_OS
47 -- On Windows, the equlvalent of POSIX time is "file time", defined as
48 -- the number of 100-nanosecond intervals that have elapsed since
49 -- 12:00 A.M. January 1, 1601 (UTC). We can convert this into a POSIX
50 -- time by adjusting the offset to be relative to the POSIX epoch.
51 getSystemTime = do
52 Win32.FILETIME ft <- Win32.getSystemTimeAsFileTime
53 let (s, us) = (ft - win32_epoch_adjust) `divMod` 10000000
54 return (MkSystemTime (fromIntegral s) (fromIntegral us * 100))
55 where
56 win32_epoch_adjust :: Word64
57 win32_epoch_adjust = 116444736000000000
58
59 getTime_resolution = 100E-9 -- 100ns
60
61 getTAISystemTime = Nothing
62 #elif defined(HAVE_CLOCK_GETTIME)
63 -- Use hi-res clock_gettime
64 timespecToSystemTime :: CTimespec -> SystemTime
65 timespecToSystemTime (MkCTimespec (CTime s) (CLong ns)) = (MkSystemTime (fromIntegral s) (fromIntegral ns))
66
67 timespecToDiffTime :: CTimespec -> DiffTime
68 timespecToDiffTime (MkCTimespec (CTime s) ns) = (fromIntegral s) + (fromIntegral ns) * 1E-9
69
70 clockGetSystemTime :: ClockID -> IO SystemTime
71 clockGetSystemTime clock = fmap timespecToSystemTime $ clockGetTime clock
72
73 getSystemTime = clockGetSystemTime clock_REALTIME
74
75 getTime_resolution = timespecToDiffTime realtimeRes
76
77 getTAISystemTime =
78 fmap (\resolution -> (timespecToDiffTime resolution, clockGetSystemTime clock_TAI)) $ clockResolution clock_TAI
79 #else
80 -- Use gettimeofday
81 getSystemTime = do
82 MkCTimeval (CLong s) (CLong us) <- getCTimeval
83 return (MkSystemTime (fromIntegral s) (fromIntegral us * 1000))
84
85 getTime_resolution = 1E-6 -- microsecond
86
87 getTAISystemTime = Nothing
88 #endif