Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
The standard package for working with dates and times in Haskell, time, is awkward. That's a subjective judgment, but over the years there have been few areas more frustrating than trying to do pragmatic things with calendars and clocks. This module represents some opinionated approaches to working with times and dates, and a place to collect some hard-won idioms for converting between things.
Our original use was wanting to conveniently measure things happening on distributed computer systems. Since machine clock cycles are in units of nanoseconds, this has the nice property that, assuming the system clock is not corrupted, two subsequent events from the same source process are likely to have monotonically increasing timestamps. And even if the system clock goes to hell, they're still decently likely to be unique per device. Make for good keys.
So the timestamp type herein Time
is nanoseconds since the Unix epoch; which
in (signed) 64 bits means that you can represent times between early in the
morning of 21 September 1677 through just before midnight on 11 April 2262.
The primary use isn't doing calendaring, though; it's just working with
machine generated timestamps in distributed systems and for conveying start
and end times around in your program.
There are quite a few other time formats around the Haskell ecosystem. You can
use the fromTime
and intoTime
methods of the Instant
typeclass to
convert from one to another if you need to.
Time type
Number of nanoseconds since the Unix epoch.
The Show
and Externalize
instances display the
Time
as seconds with the nanosecond precision expressed as a decimal amount
after the interger, ie:
>>>
t <- getCurrentTimeNanoseconds
>>>
formatExternal t
"2014-07-31T23:09:35.274387031Z"
However this doesn't change the fact the underlying representation counts nanoseconds since epoch:
>>>
show $ unTime t
"1406848175274387031"
There is a Externalize
instance that is reasonably accommodating:
>>>
parseExternal "2014-07-31T13:05:04.942089001Z" :: Maybe Time
Just 2014-07-31T13:05:04.942089001Z
>>>
parseExternal "1406811904.942089001" :: Maybe Time
Just 2014-07-31T13:05:04.942089001Z
>>>
parseExternal "1406811904" :: Maybe Time
Just 2014-07-31T13:05:04.000000000Z
In case you're wondering, the valid range of nanoseconds that fits into the
underlying Int64
is:
>>>
formatExternal (minBound :: Time)
"1677-09-21T00:12:43.145224192Z"
>>>
formatExternal (maxBound :: Time)
"2262-04-11T23:47:16.854775807Z"
so in a quarter millenium's time, yes, you'll have the Y2262 Problem. Haskell code from today will, of course, still be running, so in the mid Twenty-Third century you will need to replace this implementation with something else.
Since: 0.3.3
Instances
FromJSON Time Source # | |
ToJSON Time Source # | |
Defined in Core.Data.Clock | |
Bounded Time Source # | |
Enum Time Source # | |
Generic Time Source # | |
Read Time Source # | |
Show Time Source # | |
Externalize Time Source # | Timestamps are formatted as per ISO 8601: 2022-06-20T14:51:23.544826062Z |
Defined in Core.Encoding.External | |
Eq Time Source # | |
Ord Time Source # | |
type Rep Time Source # | |
Defined in Core.Data.Clock |
getCurrentTimeNanoseconds :: IO Time Source #
Get the current system time, expressed as a Time
(which is to
say, number of nanoseconds since the Unix epoch).
Since: 0.3.3
Conversions
class Instant a where Source #
Convert between different representations of time. Our Time
timestamp has
nanosecond precision so converting from a type with lesser or greater
precision will require you to either pad with zeros or to round to the nearest
nanosecond (who the hell has picoseconds of anything anyway?) if writing an
instance of this type.
The most important instance is probably the UTCTime
one, as many other
Haskell libraries use this type to represent time.
Since: 0.3.3
Instances
Instant Int64 Source # | Number of nanoseconds since the epoch. |
Instant ElapsedP Source # | Convert to the elapsed time with sub-second precision type from hourglass, giving you ready access to that library's time formatting and calendar date manipulation functions. |
Instant Day Source # | This instance may be useful if you need to work with calendar dates with
functions from time. From here you would probably be interested in
Since: 0.3.5 |
Instant POSIXTime Source # | |
Instant UTCTime Source # | |
Internals
unTime :: Time -> Int64 Source #
If you need to manipulate the date or calculate elapsed time then you can
dig out the underlying Int64
here. We have not provided instances of
Num
, Real
, or Integral
for the timestamp type because adding two
timestamps doesn't really make sense. You can use intoTime
to reconstruct a
timestamp subsequently if necessary.
Since: 0.3.3