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
8+ --
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+ --
978
1079module Streamly.Internal.Data.Time.Units
1180 (
@@ -83,11 +152,6 @@ tenPower9 = 1000000000
83152-- NanoSecond Int64
84153-- ...
85154
86- -- Double or Fixed would be a much better representation so that we do not lose
87- -- information between conversions. However, for faster arithmetic operations
88- -- we use an 'Int64' here. When we need convservation of values we can use a
89- -- different system of units with a Fixed precision.
90-
91155-------------------------------------------------------------------------------
92156-- Integral Units
93157-------------------------------------------------------------------------------
@@ -152,19 +216,21 @@ newtype MilliSecond64 = MilliSecond64 Int64
152216-- performance boost. If not then we can just use Integer nanoseconds and get
153217-- rid of TimeUnitWide.
154218--
219+ {-
155220-- | A type class for converting between time units using 'Integer' as the
156221-- intermediate and the widest representation with a nanosecond resolution.
157222-- This system of units can represent arbitrarily large times but provides
158223-- least efficient arithmetic operations due to 'Integer' arithmetic.
159224--
160225-- NOTE: Converting to and from units may truncate the value depending on the
161226-- original value and the size and resolution of the destination unit.
162- {-
163227class TimeUnitWide a where
164228 toTimeInteger :: a -> Integer
165229 fromTimeInteger :: Integer -> a
166230-}
167231
232+ -- XXX Rename to IsTimeUnit?
233+ --
168234-- | A type class for converting between units of time using 'TimeSpec' as the
169235-- intermediate representation. This system of units can represent up to ~292
170236-- billion years at nanosecond resolution with reasonably efficient arithmetic
@@ -254,18 +320,27 @@ instance TimeUnit64 MilliSecond64 where
254320-- Absolute time
255321-------------------------------------------------------------------------------
256322
323+ -- Have a Fixed64 type with an Int64 as underlying type
324+ -- XXX Use AbsTime64 for faster arithmetic on AbsTimes?
325+ --
326+ -- data Epoch = Posix | UTC | Rel
327+ --
328+ -- XXX data Time epoch = Time TimeSpec
329+ --
257330-- | Absolute times are relative to a predefined epoch in time. 'AbsTime'
258331-- represents times using 'TimeSpec' which can represent times up to ~292
259332-- billion years at a nanosecond resolution.
260333newtype AbsTime = AbsTime TimeSpec
261334 deriving (Eq , Ord , Show )
262335
263- -- | Convert a 'TimeUnit' to an absolute time.
336+ -- | Convert a 'TimeUnit' representing relative time from the Unix epoch to an
337+ -- absolute time.
264338{-# INLINE_NORMAL toAbsTime #-}
265339toAbsTime :: TimeUnit a => a -> AbsTime
266340toAbsTime = AbsTime . toTimeSpec
267341
268- -- | Convert absolute time to a 'TimeUnit'.
342+ -- | Convert absolute time to a relative 'TimeUnit' representing time relative
343+ -- to the Unix epoch.
269344{-# INLINE_NORMAL fromAbsTime #-}
270345fromAbsTime :: TimeUnit a => AbsTime -> a
271346fromAbsTime (AbsTime t) = fromTimeSpec t
@@ -286,8 +361,10 @@ fromAbsTime (AbsTime t) = fromTimeSpec t
286361-- usually shorter and for our purposes an Int64 nanoseconds can hold close to
287362-- thousand year duration. It is also faster to manipulate. We do not check for
288363-- overflows during manipulations so use it only when you know the time cannot
289- -- be too big. If you need a bigger RelTime representation then use RelTimeBig .
364+ -- be too big. If you need a bigger RelTime representation then use RelTime .
290365
366+ -- This is the same as the DiffTime in time package.
367+ --
291368-- | Relative times are relative to some arbitrary point of time. Unlike
292369-- 'AbsTime' they are not relative to a predefined epoch.
293370newtype RelTime64 = RelTime64 NanoSecond64
0 commit comments