std.offsetdatetime
A date and time of day at an offset from UTC: 2024-02-29T15:04:05+08:00,
what a clock on the wall said where the clock was 8 hours ahead of
UTC — an instant (std.instant), and how it was read there. NodaTime’s
OffsetDateTime is the model: a std.localdatetime and a std.offset.
Two are equal where both their date-times and their offsets are, so
15:04:05+08:00 and 07:04:05Z, the same instant, are not equal; and
they have no order, as by their instants or by their date-times would
each be a surprise — compare their instants. RFC 3339 writes one,
and reads it (show, parse). Import it by a name,
import std.offsetdatetime as OffsetDateTime, as its names are
short.
import std.instant as Instantimport std.offset as Offsetimport std.offsetdatetime as OffsetDateTime
-- | the instant in Taipei, as RFC 3339 writes it-- | >>> inTaipei Instant.epoch-- | "1970-01-01T08:00:00+08:00"inTaipei : Instant.Instant -> StringinTaipei t = maybe "" (\o -> show (OffsetDateTime.at t o)) (Offset.fromHours 8)OffsetDateTime
data OffsetDateTimeA date-time and its offset: the date and time of day a clock on the wall says, and how far ahead of UTC the clock is.
make
make : LocalDateTime.LocalDateTime -> Offset.Offset -> OffsetDateTimeThe date-time at the offset.
local
local : OffsetDateTime -> LocalDateTime.LocalDateTimeIts date-time, as the clock at its offset tells it.
offset
offset : OffsetDateTime -> Offset.OffsetIts offset.
at
at : Instant.Instant -> Offset.Offset -> OffsetDateTimeThe instant as a clock at the offset tells it.
>>> List.map (\h -> maybe "" (\o -> show (local (at Instant.epoch o))) (Offset.fromHours h)) [0, 8, -5]["1970-01-01T00:00:00", "1970-01-01T08:00:00", "1969-12-31T19:00:00"]instant
instant : OffsetDateTime -> Instant.InstantThe instant it is: its date-time less its offset.
>>> maybe "" (\o -> show (instant (at (Instant.fromUnixNanoseconds 1709219045500000000) o))) (Offset.fromHoursAndMinutes (-9) 30)"2024-02-29T15:04:05.5Z"instanceEqualityOffsetDateTime
instance instanceEqualityOffsetDateTime : Equality OffsetDateTimeThe same date-time at the same offset, as NodaTime has it: the same instant at two offsets is two values.
>>> maybe False (\o -> at Instant.epoch o == at Instant.epoch o) (Offset.fromHours 8)True>>> maybe True (\o -> at Instant.epoch o == at Instant.epoch Offset.utc) (Offset.fromHours 8)FalseinstanceDebugOffsetDateTime
instance instanceDebugOffsetDateTime : Debug OffsetDateTimeAs show writes it, 2024-02-29T15:04:05+08:00, as NodaTime’s
debug form is.
>>> debug (at Instant.epoch Offset.utc)"1970-01-01T00:00:00Z"instanceShowOffsetDateTime
instance instanceShowOffsetDateTime : Show OffsetDateTimeAs RFC 3339 writes it, as Go’s RFC3339Nano does: the date-time as
std.localdatetime writes it — a fraction of a second only where
there is one — and the offset as std.offset does, Z for UTC
(2024-02-29T15:04:05.5+08:00). An offset that is not whole minutes
is written with its seconds, +05:30:15, which RFC 3339 has not, so
as to be exact; and a year out of 0000 to 9999 as std.localdate writes
it.
>>> List.map (\n -> maybe "" (\o -> show (at (Instant.fromUnixNanoseconds 1709219045500000000) o)) (Offset.fromSeconds n)) [0, 28800, -34200, 19815]["2024-02-29T15:04:05.5Z", "2024-02-29T23:04:05.5+08:00", "2024-02-29T05:34:05.5-09:30", "2024-02-29T20:34:20.5+05:30:15"]parse
parse : String -> Maybe OffsetDateTimeThe date-time RFC 3339 writes as s, as std.date’s parseRFC3339
reads it: 2006-01-02T15:04:05Z, the T and the Z in either
case, perhaps a fraction of a second of 1 to 9 digits after the
seconds, and an offset Z or +hh:mm or -hh:mm. Nothing if it
writes none, or a field is out of its range (the month 13, February
30, the hour 24, the second 60), or the offset is beyond 18 hours
(+19:00), as an offset here is.
>>> List.map (\s -> maybe "" show (parse s)) ["1985-04-12T23:20:50.52Z", "1996-12-19t16:39:57-08:00", "2024-02-29T23:59:59.000000001z", "0000-01-01T00:00:00+18:00", "9999-12-31T00:00:00.100Z"]["1985-04-12T23:20:50.52Z", "1996-12-19T16:39:57-08:00", "2024-02-29T23:59:59.000000001Z", "0000-01-01T00:00:00+18:00", "9999-12-31T00:00:00.1Z"]>>> maybe "" (\t -> show (instant t)) (parse "2023-11-15T06:13:20.123456789+08:00")"2023-11-14T22:13:20.123456789Z">>> (List.map (\s -> maybe True (\_ -> False) (parse s)) ["2006-13-02T15:04:05Z", "2023-02-29T00:00:00Z", "2006-01-02T24:00:00Z", "2006-01-02T15:04:60Z", "2006-01-02T15:04:05.Z", "2006-01-02T15:04:05.1234567890Z", "2006-01-02T15:04:05+08:60", "2006-01-02T15:04:05+19:00", "2006-01-02 15:04:05Z", "2006-01-02T15:04:05", "2006-01-02T15:04:05+0800", "-006-01-02T15:04:05Z", "2006-01-02T15:04:05ZZ"] : List Bool)[True, True, True, True, True, True, True, True, True, True, True, True, True]>>> List.all (\s -> maybe False (\t -> parse (show t) == Just t) (parse s)) ["2024-02-29T15:04:05.5+08:00", "1969-12-31T23:59:59.999999999-09:30", "0000-01-01T00:00:00Z"]True