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