f9aca190f72a95cab4f361e9655c03acaec05654
[packages/time.git] / lib / Data / Time / Clock / System.hs
1 -- | Fast access to the system clock.
2 module Data.Time.Clock.System
3 (
4 systemEpochDay,
5 SystemTime(..),
6 truncateSystemTimeLeapSecond,
7 getSystemTime,
8 systemToUTCTime,
9 utcToSystemTime,
10 systemToTAITime,
11 ) where
12
13 import Data.Time.Clock.Internal.AbsoluteTime
14 import Data.Time.Clock.Internal.DiffTime
15 import Data.Time.Clock.Internal.SystemTime
16 import Data.Time.Clock.Internal.UTCTime
17 import Data.Time.Calendar.Days
18 import Data.Int (Int64)
19
20
21 -- | Map leap-second values to the start of the following second.
22 -- The resulting 'systemNanoseconds' will always be in the range 0 to 1E9-1.
23 truncateSystemTimeLeapSecond :: SystemTime -> SystemTime
24 truncateSystemTimeLeapSecond (MkSystemTime seconds nanoseconds) | nanoseconds >= 1000000000 = MkSystemTime (succ seconds) 0
25 truncateSystemTimeLeapSecond t = t
26
27 -- | Convert 'SystemTime' to 'UTCTime', matching zero 'SystemTime' to midnight of 'systemEpochDay' UTC.
28 systemToUTCTime :: SystemTime -> UTCTime
29 systemToUTCTime (MkSystemTime seconds nanoseconds) = let
30 days :: Int64
31 timeSeconds :: Int64
32 (days, timeSeconds) = seconds `divMod` 86400
33
34 day :: Day
35 day = addDays (fromIntegral days) systemEpochDay
36
37 timeNanoseconds :: Int64
38 timeNanoseconds = timeSeconds * 1000000000 + (fromIntegral nanoseconds)
39
40 timePicoseconds :: Int64
41 timePicoseconds = timeNanoseconds * 1000
42
43 time :: DiffTime
44 time = picosecondsToDiffTime $ fromIntegral timePicoseconds
45 in UTCTime day time
46
47 -- | Convert 'UTCTime' to 'SystemTime', matching zero 'SystemTime' to midnight of 'systemEpochDay' UTC.
48 utcToSystemTime :: UTCTime -> SystemTime
49 utcToSystemTime (UTCTime day time) = let
50 days :: Int64
51 days = fromIntegral $ diffDays day systemEpochDay
52
53 timePicoseconds :: Int64
54 timePicoseconds = fromIntegral $ diffTimeToPicoseconds time
55
56 timeNanoseconds :: Int64
57 timeNanoseconds = timePicoseconds `div` 1000
58
59 timeSeconds :: Int64
60 nanoseconds :: Int64
61 (timeSeconds,nanoseconds) = if timeNanoseconds >= 86400000000000 then (86399,timeNanoseconds - 86399000000000) else timeNanoseconds `divMod` 1000000000
62
63 seconds :: Int64
64 seconds = days * 86400 + timeSeconds
65
66 in MkSystemTime seconds $ fromIntegral nanoseconds
67
68 systemEpochAbsolute :: AbsoluteTime
69 systemEpochAbsolute = taiNominalDayStart systemEpochDay
70
71 -- | Convert 'SystemTime' to 'AbsoluteTime', matching zero 'SystemTime' to midnight of 'systemEpochDay' TAI.
72 systemToTAITime :: SystemTime -> AbsoluteTime
73 systemToTAITime (MkSystemTime s ns) = let
74 diff :: DiffTime
75 diff = (fromIntegral s) + (fromIntegral ns) * 1E-9
76 in addAbsoluteTime diff systemEpochAbsolute
77
78 -- | The day of the epoch of 'SystemTime', 1970-01-01
79 systemEpochDay :: Day
80 systemEpochDay = ModifiedJulianDay 40587