11-- |
22-- Module : Streamly.Internal.Data.Time.Units
33-- Copyright : (c) 2019 Composewell Technologies
4- --
5- -- License : BSD3
4+ -- License : BSD-3-Clause
6576-- Stability : pre-release
87-- Portability : GHC
98--
9+ -- Fast time manipulation.
10+ --
11+ -- = Representing Time
12+ --
13+ -- Numbers along with an associated unit (e.g. 'MilliSecond64') are used to
14+ -- represent durations and points in time. Durations are relative but points
15+ -- are absolute and defined with respect to some fixed or well known point in
16+ -- time e.g. the Unix epoch (01-Jan-1970). Absolute and relative times are
17+ -- numbers that can be represented and manipulated like 'Num'.
18+ --
19+ -- = Fixed Precision 64-bit Units
20+ --
21+ -- * 'NanoSecond64': 292 years at nanosecond precision.
22+ -- * 'MicroSecond64': 292K years at nanosecond precision.
23+ -- * 'MilliSecond64': 292M years at nanosecond precision.
24+ --
25+ -- These units are 'Integral' 'Num' types. We can use 'fromIntegral' to convert
26+ -- any integral type to/from these types.
27+ --
28+ -- = TimeSpec
29+ --
30+ -- * 'TimeSpec': 292G years at nanosecond precision
31+ --
32+ -- = RelTime64
33+ --
34+ -- Relative time, not relative to any specific epoch. Represented using
35+ -- 'NanoSecond64'. 'fromRelTime64' and 'toRelTime64' can be used to convert a
36+ -- time unit to/from RelTime. Note that a larger unit e.g. 'MicroSecond64' may
37+ -- get truncated if it is larger than 292 years. RelTime64 is also generated by
38+ -- diffing two AbsTime.
39+ --
40+ -- RelTime is a 'Num', we can do number arithmetic on RelTime, and use
41+ -- 'fromInteger' to convert an 'Integer' nanoseconds to 'RelTime'.
42+ --
43+ -- = AbsTime
44+ --
45+ -- Time measured relative to the POSIX epoch i.e. 01-Jan-1970. Represented
46+ -- using 'TimeSpec'. 'fromAbsTime' and 'toAbsTime' can be used to convert a
47+ -- time unit to/from AbsTime.
48+ --
49+ -- AbsTime is not a 'Num'. We can use 'diffAbsTime' to diff abstimes to get
50+ -- a 'RelTime'. We can add RelTime to AbsTime to get another AbsTime.
51+ --
52+ -- = TimeSpec vs 64-bit Units
53+ --
54+ -- TimeSpec can represent up to 292 billion years of time at nanosecond
55+ -- precision while 64-bit units can represent only 292 years at the same
56+ -- precision. However, 64-bit units are much faster to manipulate. In high
57+ -- performance code it is recommended to use the 64-bit units if possible.
58+ --
59+ -- = Working with the "time" package
60+ --
61+ -- AbsTime is essentially the same as 'SystemTime' from the time package. We
62+ -- can use 'SystemTime' to interconvert between time package and this module.
63+ --
64+ -- = Alternative Representations
65+ --
66+ -- Double or Fixed would be a much better representation so that we do not lose
67+ -- information between conversions. However, for faster arithmetic operations
68+ -- we use an 'Int64' here. When we need convservation of values we can use a
69+ -- different system of units with a Fixed precision.
70+ --
71+ -- = TODO
72+ --
73+ -- Split the Timespec/TimeUnit in a separate module?
74+ -- Keep *64/TimeUnit64 in this module, remove the 64 suffix because these are
75+ -- common units.
76+ -- Rename TimeUnit to IsTimeSpec, TimeUnit64 to IsTimeUnit.
77+ --
1078-- Time (default double precision). Fast Time (64-bit), Wide Time (TimeSpec).
1179-- Timezone, UTC/Local/System/User-defined.
1280--
1381-- Fast (UTC Time), Wide (Local Time) etc.
1482--
1583-- Units? Can be module specific or wrappers around them.
1684-- e.g. NanoSecond (Fast (UTC Time)) or NanoSecond Time.
85+ --
1786
1887module Streamly.Internal.Data.Time.Units
1988 (
@@ -91,11 +160,6 @@ tenPower9 = 1000000000
91160-- NanoSecond Int64
92161-- ...
93162
94- -- Double or Fixed would be a much better representation so that we do not lose
95- -- information between conversions. However, for faster arithmetic operations
96- -- we use an 'Int64' here. When we need convservation of values we can use a
97- -- different system of units with a Fixed precision.
98-
99163-------------------------------------------------------------------------------
100164-- Integral Units
101165-------------------------------------------------------------------------------
@@ -160,19 +224,21 @@ newtype MilliSecond64 = MilliSecond64 Int64
160224-- performance boost. If not then we can just use Integer nanoseconds and get
161225-- rid of TimeUnitWide.
162226--
227+ {-
163228-- | A type class for converting between time units using 'Integer' as the
164229-- intermediate and the widest representation with a nanosecond resolution.
165230-- This system of units can represent arbitrarily large times but provides
166231-- least efficient arithmetic operations due to 'Integer' arithmetic.
167232--
168233-- NOTE: Converting to and from units may truncate the value depending on the
169234-- original value and the size and resolution of the destination unit.
170- {-
171235class TimeUnitWide a where
172236 toTimeInteger :: a -> Integer
173237 fromTimeInteger :: Integer -> a
174238-}
175239
240+ -- XXX Rename to IsTimeUnit?
241+ --
176242-- | A type class for converting between units of time using 'TimeSpec' as the
177243-- intermediate representation. This system of units can represent up to ~292
178244-- billion years at nanosecond resolution with reasonably efficient arithmetic
@@ -262,18 +328,27 @@ instance TimeUnit64 MilliSecond64 where
262328-- Absolute time
263329-------------------------------------------------------------------------------
264330
331+ -- Have a Fixed64 type with an Int64 as underlying type
332+ -- XXX Use AbsTime64 for faster arithmetic on AbsTimes?
333+ --
334+ -- data Epoch = Posix | UTC | Rel
335+ --
336+ -- XXX data Time epoch = Time TimeSpec
337+ --
265338-- | Absolute times are relative to a predefined epoch in time. 'AbsTime'
266339-- represents times using 'TimeSpec' which can represent times up to ~292
267340-- billion years at a nanosecond resolution.
268341newtype AbsTime = AbsTime TimeSpec
269342 deriving (Eq , Ord , Show )
270343
271- -- | Convert a 'TimeUnit' to an absolute time.
344+ -- | Convert a 'TimeUnit' representing relative time from the Unix epoch to an
345+ -- absolute time.
272346{-# INLINE_NORMAL toAbsTime #-}
273347toAbsTime :: TimeUnit a => a -> AbsTime
274348toAbsTime = AbsTime . toTimeSpec
275349
276- -- | Convert absolute time to a 'TimeUnit'.
350+ -- | Convert absolute time to a relative 'TimeUnit' representing time relative
351+ -- to the Unix epoch.
277352{-# INLINE_NORMAL fromAbsTime #-}
278353fromAbsTime :: TimeUnit a => AbsTime -> a
279354fromAbsTime (AbsTime t) = fromTimeSpec t
@@ -294,8 +369,10 @@ fromAbsTime (AbsTime t) = fromTimeSpec t
294369-- usually shorter and for our purposes an Int64 nanoseconds can hold close to
295370-- thousand year duration. It is also faster to manipulate. We do not check for
296371-- overflows during manipulations so use it only when you know the time cannot
297- -- be too big. If you need a bigger RelTime representation then use RelTimeBig .
372+ -- be too big. If you need a bigger RelTime representation then use RelTime .
298373
374+ -- This is the same as the DiffTime in time package.
375+ --
299376-- | Relative times are relative to some arbitrary point of time. Unlike
300377-- 'AbsTime' they are not relative to a predefined epoch.
301378newtype RelTime64 = RelTime64 NanoSecond64
0 commit comments