A date, checked against the calendar.
The reference.
Every public type, function and constant, grouped by package. Generated from pkg.generated.mbti and the source's own documentation comments.
@moondate
Types
Date
structA day on the proleptic Gregorian calendar.
Proleptic means the Gregorian rules are applied before 1582 as well, which is what every interchange format in reach assumes and what makes arithmetic over the whole range uniform.
- year : Int32
- month : Int32
- day : Int32
Days since 1970-01-01, negative before it.
Howard Hinnant's days_from_civil: shift the year to start in March so the leap day falls at the end, then the month lengths follow a pattern with no table.
One date less another, as a span of whole days.
The ISO 8601 week date: the year the week belongs to, the week number, and the day of the week with Monday as 1.
The year is not always the calendar year. A week belongs to the year that holds its Thursday, so the first of January can fall in the last week of the year before — which is exactly the case a hand-rolled week number gets wrong.
The day of the week with Monday as 1 and Sunday as 7.
[Date::weekday] counts from Sunday as 0, which is what cron and C's tm_wday use; ISO counts from Monday as 1. Both are here because both are asked for, and picking one silently is how an off-by-one gets into a schedule.
The date n days after 1970-01-01, the inverse of [Date::days].
The date named by an ISO week date.
The date with that ordinal.
Days since 0001-01-01, that day being 1.
The proleptic Gregorian ordinal, which is what makes two dates subtractable without going through an epoch.
The date n days later, or earlier when n is negative.
The date n months later, clamped to the end of the month it lands in.
The thirty-first of January plus one month is the twenty-eighth or twenty-ninth of February, because there is no thirty-first. Every calendar library makes this choice and they all make the same one.
The same date with some parts replaced.
The day of the week, Sunday being 0.
1970-01-01 was a Thursday, which is where the 4 comes from.
The day of the year, the first of January being 1.
Three-way ordering from Compare: less, equal or greater.
Structural equality from Eq.
The negation of equal, from Eq.
self >= other, from Compare.
self > other, from Compare.
self <= other, from Compare.
self < other, from Compare.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Moment
enumA point in time, in one of the four shapes a format names.
TOML 1.0.0 has exactly these four and gives them these meanings; RFC 3339 defines only Zoned. The distinction is not decoration: Plain is a wall clock, which is what an alarm or an opening time is, and turning it into an instant needs a zone nobody has supplied.
- Zoned(date~ : Date, time~ : Time, zone~ : Zone)
- Plain(date~ : Date, time~ : Time)
- Day(date~ : Date)
- Clock(time~ : Time)
A moment as an ASN.1 GeneralizedTime, which is the form DER uses from 2050 on and the one that needs no windowing rule to read back.
The same instant read in another zone.
None for the three shapes that are not instants: moving a wall clock to another zone would be inventing the zone it was written in.
A date and a time as one wall-clock moment.
zone makes it an instant instead; leaving it off keeps it a wall clock, which is what an opening time or an alarm is.
The moment in C's ctime form: Sun Nov 6 08:49:37 1994.
The day is space-padded rather than zero-padded, which is the one thing that distinguishes this form from every other.
The date out of a moment.
None for a bare time, which has no date to give.
One moment less another, for the two shapes that can be subtracted.
None when they are not comparable: an instant and a wall clock differ by an amount that depends on a zone nobody supplied, and a bare time and a bare date are not the same kind of thing.
Seconds since 1970-01-01T00:00:00Z, for a moment that names one.
None for the three shapes that do not: a wall clock, a bare date and a bare time are not instants until someone supplies the zone they are read in.
A moment as an HTTP date (RFC 9110 §5.6.7): Sun, 06 Nov 1994 08:49:37 GMT.
This is the one form a Date header may take. The two obsolete forms are read by [http] and never written, which is what §5.6.7 asks for.
The instant, as whole seconds past 1970 and the nanoseconds after them.
The two are apart because a count of nanoseconds runs out in 2262, and because a zone whose offset is not a whole second puts the nanoseconds of the instant at odds with the nanoseconds on the clock: 15:23:30.123456789-00:00:00.000000100 is 100 nanoseconds earlier than its clock says.
The ISO week date of the moment's date.
The moment as ISO 8601 text, which is what [Show] writes.
sep is the character between the date and the time, T by default; any character works, and a space is what a log line wants.
fraction is the number of fractional-second digits, 0 to 9, truncated. Left out, it writes as many as the value needs and none for a whole second, which is Temporal's auto.
offset writes the zone the moment carries, Z for UTC and ±HH:MM for an offset; false leaves the zone off, which is Temporal's offset: "never".
zone_name follows the offset with the name the zone is filed under, in brackets: 2026-11-01T01:30:00-04:00[America/New_York], which is Temporal's timeZoneName: "critical" and the only way the text keeps the name as well as the instant.
The moment seconds after 1970-01-01T00:00:00Z, the inverse of [Moment::timestamp].
Reading the clock is not this package's job — it has no I/O — so a caller that wants "now" passes what its own clock said.
Days since 0001-01-01 of the moment's date.
The moment span later.
A bare date moves by whole days and a bare time wraps within the day, because that is all each of them can mean.
The same moment with some parts replaced.
The time out of a moment.
Midnight for a bare date, which is the time it names.
Seconds since the epoch as a Double, fraction included.
The nine fields of a broken-down time, in the usual order: year, month, day, hour, minute, second, weekday counted from Monday as 0, day of the year, and whether daylight saving applies — always -1 here, because that needs a zone database this package does not carry.
The Date.prototype.toISOString shape: always the UTC instant, always three fractional digits, always a trailing Z.
A moment with no zone has no instant of its own, so its wall clock is taken as UTC — the same convention [Moment::strftime] uses for a bare time.
The Date.prototype.toUTCString shape: Tue, 22 Sep 2026 05:30:05 GMT.
This is the HTTP date form [Moment::http_text] already writes, on the UTC instant, which is exactly what ECMAScript's toUTCString produces.
How far the moment's clock is from UTC.
The day of the week of the moment's date, Sunday being 0.
The zone a moment carries, or None when it carries none.
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Span
structA length of time, to the nanosecond, with no calendar attached.
A span is not a number of months: a month is not a fixed length, so adding one is a calendar operation (Date::plus_months) rather than arithmetic.
- nanos : Int64
A span made of the usual parts: days, hours, minutes, seconds and fractions.
The span with its sign dropped.
Two spans added.
The span negated.
A span of n of these.
The whole days in a span, and the seconds and nanoseconds left over — the three fields a duration is usually stored in.
The span as whole seconds, rounded towards zero.
One span less another.
The span as seconds, fraction included.
Three-way ordering from Compare: less, equal or greater.
Structural equality from Eq.
The negation of equal, from Eq.
self >= other, from Compare.
self > other, from Compare.
self <= other, from Compare.
self < other, from Compare.
The debug representation, from Debug.
Time
structA time on a twenty-four hour clock, to the nanosecond.
A second of 60 is allowed: RFC 3339 §5.6 permits it for a leap second, and a timestamp that records one is a real timestamp that a reader should not throw away.
- hour : Int32
- minute : Int32
- second : Int32
- nano : Int32
A time, checked against the clock.
Nanoseconds since midnight.
The same time with some parts replaced.
Three-way ordering from Compare: less, equal or greater.
Structural equality from Eq.
The negation of equal, from Eq.
self >= other, from Compare.
self > other, from Compare.
self <= other, from Compare.
self < other, from Compare.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Zone
enumHow far the clock is from UTC.
Utc and Offset(0) are both midnight-at-Greenwich, but they are not the same thing to write down: RFC 3339 §4.3 gives -00:00 to a timestamp whose offset is unknown, and Z to one that is genuinely UTC.
Offset counts minutes; Named counts seconds and carries the name the zone is filed under, so VV and a Go layout's MST have something to write.
- Utc
- Offset(Int32)
- Named(ZoneName)
- Precise(Int64)
The abbreviation written for the zone: EST, GMT, +0530.
A named zone read from text that carried no abbreviation falls back to the numeric spelling, which is what a fixed offset writes anyway.
How far east of UTC the zone is, in minutes, rounded towards zero.
A named zone whose local mean time is not a whole number of minutes loses the remainder here, which is what the %z forms write and what every other implementation writes for those years.
The name the zone is filed under: EST5EDT for a POSIX rule, the path in the database for a named zone.
A fixed offset has no name of its own, so it is spelled the way a POSIX rule spells one — UTC, UTC-05:00 — which is what VV writes for it.
How far east of UTC the zone is, in nanoseconds.
The finest of the three readers, and the one the others are built on: an instant is a count of nanoseconds, so this is what epoch subtracts.
How far east of UTC the zone is, in seconds, rounded towards zero.
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
ZoneName
structA zone named by a database, read at one instant.
The offset and the abbreviation are the ones in force at the instant the moment carries, which is what makes a Zoned a value: it can be compared, written and moved to another zone with no database in reach. Crossing a transition is a question for the rules, so a moment that has to survive one goes back through @zone.Tz::moment.
The offset is in seconds east of UTC, because a zone's local mean time before standard time was adopted is not a whole number of minutes: New York ran 4:56:02 behind Greenwich. Offsets in whole minutes are what [Zone::Offset] carries, and [Zone::seconds] puts both on the same footing.
- name : String
- offset : Int32
- abbrev : String
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Errors
Refused
suberrorWhy a zone, a rule or a wall clock was refused.
A zone database is a binary format with a version byte, a set of rules whose text is a small language of its own, and a question — which instant does this clock name — that has no answer for one hour a year in most of the world. Each of those fails in its own way, and the message says which.
- Range(field~ : String, got~ : Int32, low~ : Int32, high~ : Int32)
- Malformed(String)
- Truncated(String)
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Functions
An ASN.1 UTCTime or GeneralizedTime (ITU-T X.680 §47), as DER writes them.
This is how a certificate spells its validity. DER requires the Z and whole seconds; UTCTime's two-digit year is read as RFC 5280 §4.1.2.5.1 says — 49 and under are 2000s, 50 and over are 1900s, which is not the same rule HTTP uses.
An HTTP date read (RFC 9110 §5.6.7).
The preferred IMF-fixdate, and the two obsolete forms a recipient must still accept: RFC 850's Sunday, 06-Nov-94 08:49:37 GMT and asctime's Sun Nov 6 08:49:37 1994. A two-digit year is read as RFC 6265 §5.1.1 says: 69 and under are 2000s, 70 and over are 1900s.
Whether year has a twenty-ninth of February.
Every fourth year, except every hundredth, except every four-hundredth — the rule that makes the calendar year 365.2425 days long.
How many days month has in year.
A moment read from ISO 8601 text, which is what [parse] does.
A moment read from text whose zone is named by a place.
[@moondate.parse] keeps a place name when the offset is written beside it and refuses it when it is not: the place alone does not say which side of a transition the clock was on. This is the entry point that knows — it reads the place from the database and answers with fold for the hour that has none.
let moment = @tzdata.parse("2026-11-01T01:30:00[America/New_York]") moment.strftime("%H:%M %Z") // 01:30 EDT
A text that names an offset rather than a place is answered by [@moondate.parse] alone, so this costs a database lookup and nothing else.
Constants
Midnight, and the last representable moment of a day.
The earliest and latest dates this calendar writes with a four-digit year.
They are 1-01-01 and 9999-12-31, which is as far as a four-digit year writes; the arithmetic here works outside that range, so these are a convention for writing rather than a limit on computing.
The years this calendar spans.
Nanoseconds in a second, a minute, an hour and a day.
The smallest difference two moments can have.
A nanosecond rather than a microsecond: the clock here is finer, which is what a protocol timestamp and a benchmark both want.
@cron
Types
Cron
structA parsed expression: which values of each field it fires on.
Each field is a bit set, so asking whether a moment matches is six bit tests rather than a search. star_day and star_week are kept because the two fields interact — see [Cron::matches].
- seconds : Int64
- minutes : Int64
- hours : Int32
- days : Int32
- months : Int32
- weekdays : Int32
- star_day : Bool
- star_week : Bool
Whether m is a moment this expression fires on.
The day-of-month and day-of-week fields are or-ed when both are restricted, which is Vixie cron's rule and surprises everyone once: 0 0 13 * 5 is the thirteenth *or* any Friday, not Friday the thirteenth. When one of them is * they are and-ed, which is why 0 0 13 * * is only the thirteenth.
The first moment strictly after m that this expression fires on.
None when it never does. An expression can name a day that does not exist — 0 0 30 2 * is the thirtieth of February — so the search is bounded at four years, which is past any leap-year cycle a real schedule turns on.
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Errors
Refused
suberrorWhy a zone, a rule or a wall clock was refused.
A zone database is a binary format with a version byte, a set of rules whose text is a small language of its own, and a question — which instant does this clock name — that has no answer for one hour a year in most of the world. Each of those fails in its own way, and the message says which.
- Fields(got~ : Int32)
- Range(field~ : String, got~ : Int32, low~ : Int32, high~ : Int32)
- Malformed(String)
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Functions
A moment read from text whose zone is named by a place.
[@moondate.parse] keeps a place name when the offset is written beside it and refuses it when it is not: the place alone does not say which side of a transition the clock was on. This is the entry point that knows — it reads the place from the database and answers with fold for the hour that has none.
let moment = @tzdata.parse("2026-11-01T01:30:00[America/New_York]") moment.strftime("%H:%M %Z") // 01:30 EDT
A text that names an offset rather than a place is answered by [@moondate.parse] alone, so this costs a database lookup and nothing else.
@zone
Types
ClockRule
structWhen a change happens: which day, and how long after local midnight.
The seconds can pass a day — Ireland's rules once changed the clocks at twenty-five hundred hours — because a rule is read as "so many hours after the start of that day", not as a time of day.
- onset : Onset
- seconds : Int32
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Fold
enumWhich side of a fold a wall clock lands on.
Most zones move their clocks twice a year, so one hour of the year happens twice and another never happens at all. Asking a zone for an instant from a wall clock therefore has three defensible answers and one that refuses.
Compatible is what Python's fold=0 and Temporal's disambiguation: "compatible" both do: the first of two repeated hours, the second of two skipped ones. Earlier and Later pick by instant. Python's fold=1 is Later for a repeated clock and Earlier for a skipped one.
- Compatible
- Earlier
- Later
- Reject
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Local
enumThe instants a wall clock names in a zone.
Zero, one or two, and the difference is not an edge case: a timestamp written by a program in a zone that observes daylight saving is ambiguous for one hour every autumn and impossible for one hour every spring, and both have to be handled rather than papered over.
- Exact(instant~ : Int64)
- Ambiguous(earlier~ : Int64, later~ : Int64)
- Skipped(earlier~ : Int64, later~ : Int64)
The instant a wall clock names, under a policy for the two hours a year that have no single answer.
Whether the wall clock names exactly one instant.
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
OffsetPolicy
enumHow a field edit keeps the offset that was in force before the edit.
Prefer is the default: the instant the old offset named is kept when that offset is still the one the zone has at the new reading, and when it is not, [Fold] decides. Ignore goes straight to the zone's rules. Use keeps the old offset whatever the zone says, so a change that fell in between moves the reading — the instant does not move, but the date and time and the offset in force do. Reject is the offset that refuses: a reading the old offset no longer covers is an error, even when the zone would have answered it, which is the one case the disambiguation is not the one to decide.
- Prefer
- Ignore
- Use
- Reject
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Onset
enumThe day a daylight-saving rule changes the clocks on, as POSIX TZ strings write it.
- MonthWeekDay(month~ : Int32, week~ : Int32, weekday~ : Int32)
- Julian(n~ : Int32)
- Days(n~ : Int32)
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Reading
structWhat a zone reads at one instant: the offset in force, whether daylight saving was on, and the abbreviation written for it.
epoch is when the reading began, not the instant it was asked about, so a table of readings doubles as the list of changes.
- epoch : Int64
- offset : Int32
- is_dst : Bool
- abbrev : String
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Rule
structA POSIX TZ string: the standard offset, and either no daylight saving or the two changes that bracket it.
RFC 8536 §3.3 puts one of these in every TZif footer, which is how a file that stops in 2037 still answers for 2100. The grammar is POSIX's TZ, extended there to allow a quoted name like <+0545> and seconds in the offsets.
- std_offset : Int32
- std_abbrev : String
- dst_offset : Int32?
- dst_abbrev : String
- dst_start : ClockRule?
- dst_end : ClockRule?
What the rule reads at an instant.
The two changes are placed year by year rather than tabulated: a rule is a pattern, and asking it about a date a century out costs a handful of date computations, which is how a TZif footer answers past the end of its table.
A POSIX TZ string read.
EST5EDT,M3.2.0,M11.1.0 is New York; UTC0 is UTC; <+0545>-5:45 is a fixed offset with a name that needs the angle brackets because of the sign. The offset in the string is what to *add* to local time to get UTC, so its sign is the opposite of the one a timestamp writes, which is the one trap in the whole format.
The string a rule is written as, in the form [Rule::parse] reads.
Structural equality from Eq.
The negation of equal, from Eq.
The debug representation, from Debug.
Tz
struct- name : String
- readings : Array[Reading]
- rule : Rule?
The abbreviation the zone writes at an instant.
What the zone reads at an instant.
The readings that begin between two instants, from included and to not.
The instant a wall clock names, under a policy for the two hours a year that have no single answer.
Whether daylight saving was on at an instant.
The instant epoch read in this zone.
This is the direction that needs no policy: an instant is one instant, and the zone only says what the clock read at it.
The name the zone is filed under.
A zone built from readings that were computed elsewhere.
The first reading is the one in force from the beginning of time; the rest each begin at their own epoch. A zone database that is not a TZif file — a table of its own, a test fixture — comes in through here.
How far east of UTC the zone is at an instant, in seconds.
A TZif file read (RFC 9636).
Versions 1 to 4 are read. A version 2 file carries the same zone twice — once in 32-bit transition times, once in 64-bit — and the second copy is the one used, because it is the one that keeps the years past 2038.
Leap-second records are checked for shape and then left alone: a zone answers for civil time, and this library already lets a Time hold the sixtieth second of a minute, so a leap second needs no table here.
The instants a wall clock names in this zone.
The readings the zone has been through, oldest first.
The rule that carries on past the last reading, when the zone has one.
A wall clock pinned to this zone.
A moment that already names an instant is moved to this zone instead, which is what @moondate.Moment::astimezone does with a fixed offset and this does with a whole database.
ZonedDateTime
structA date and a time that already names an instant, carried in a zone.
The instant is the point on the line — epoch seconds and nano nanoseconds past 1970 — and the zone is what the clocks read at it. The two together are the value Temporal calls a ZonedDateTime: move it to another zone and the instant does not move, only the reading does; add a duration and the instant moves by it, whatever a day happens to be here.
What [@moondate.Moment] carries is a Zone — a name with the offset in force at that instant beside it. That is a value that can be written and compared with no database in reach, but it cannot cross a change, because a change is a question for the rules. This type is for that: it keeps a Tz, the readings and the rule that carries on past them, so a step that lands on the other side of a change reads the new offset back from the rules rather than carrying a stale one forward.
let zone = @tzdata.load("America/New_York") let zoned = ZonedDateTime::of(2026, 3, 8, hour=2, minute=30, zone~) // 02:30 never happens, so the compatible answer is the later instant zoned.isoformat() // 2026-03-08T03:30:00-04:00[America/New_York]
The zone it is built in is what it is filed under. A wall clock that is Ambiguous or Skipped is answered by [Fold]; under Reject it raises rather than guessing. A field that is out of range is refused as [Refused::BadDate], the calendar and the clock's own refusal carried here.
- epoch : Int64
- nano : Int32
- tz : Tz
The abbreviation the zone writes at the instant: EST, EDT, UTC.
The date the clocks read at the instant, in the zone.
The day the clocks read at the instant, in the zone.
Seconds since 1970-01-01T00:00:00Z, the point on the line.
An instant in a zone, the direction that needs no policy.
An instant is one instant, and the zone only says what the clocks read at it. This is what an arithmetic step lands on, and what a value is moved to with [into].
The hour the clocks read at the instant, in the zone, 0 to 23.
The same instant carried in another zone.
The instant does not move; only the reading does. This is what @moondate.Moment::astimezone is, with a whole database in place of a fixed offset.
Whether daylight saving was on at the instant.
The instant as the ISO 8601 text it reads in the zone: the date and time the clocks show, the offset in force beside it, and the name in brackets.
2026-09-22T14:30:00+08:00[Asia/Shanghai]
fraction is the number of fractional-second digits, 0 to 9; left out, as many as the value needs. zone_name leaves the name off when false.
The minute the clocks read at the instant, in the zone, 0 to 59.
The Moment the zone writes for the instant: a Zoned that carries the name and the offset in force, so it can be written back with no database in reach.
This is the round trip that makes [of] and the writers agree: read the value back as a moment, and the offset beside it is the one in force.
The month the clocks read at the instant, in the zone, 1 to 12.
The nanoseconds of the instant, 0 to 999_999_999.
A date and a time in a zone.
The two hours a year that have no single answer are decided by [Fold]: for a wall clock read twice, Compatible (the default) takes the earlier instant and Later the later; for one that never reads, Compatible takes the later instant and Earlier the earlier. Reject raises for either. A field that is not a date and time the calendar has is refused as [Refused::BadDate].
A moment the caller already has, placed in a zone.
A moment that names an instant is put in the zone; one that does not — a Plain wall clock — is answered by [Fold], and Reject raises for the hours that have none.
How far east of UTC the zone is at the instant, in seconds.
How far east of UTC the zone is at the instant, in whole minutes.
A local mean time that is not a whole number of minutes loses the remainder, which is what an offset written ±HH:MM says.
The instant span later, in the same zone.
The span is added to the point on the line, not to the reading: a day added here is the instant a day later, and if a change falls in between, the reading moves across it. That is what a duration means for an instant, and the one thing that keeps a span added the same however it is split.
The instant days later, in the same zone.
The instant months later, in the same zone.
A month is a calendar step, so the reading is moved rather than the instant: the same day of the month, clamped to one that exists, is read in the month months later, and the offset that was in force is kept if it still is. Across a change the result is not the old instant plus a fixed number of days, because that is not what a month is.
What the zone read at the instant: the offset, the abbreviation, and whether daylight saving was on.
The second the clocks read at the instant, in the zone, 0 to 59.
A leap second is kept as the sixtieth second of its minute, the way the clock here does; it is not projected to the next minute.
The time the clocks read at the instant, in the zone.
The instant as a sentence: 2026-09-22T14:30:00+08:00 Asia/Shanghai.
The instant with the day changed, the rest of the reading kept. A day the month does not have is refused as [Refused::BadDate].
The instant with the hour changed, the rest of the reading kept.
The instant with the minute changed, the rest of the reading kept.
The instant with the month changed, the rest of the reading kept. A month that leaves no such day — the thirty-first into February — is refused as [Refused::BadDate].
The instant with the nanoseconds changed, the rest of the reading kept.
The offset is in seconds, so the seconds the instant names are not moved: only the fraction is replaced, and the reading is read back from the zone.
The instant with the second changed, the rest of the reading kept.
The instant with the year changed, the rest of the reading kept.
The year the clocks read at the instant, in the zone.
The zone the instant is carried in.
The name the zone is filed under.
Writes the text form to a logger, from Show.
Errors
Refused
suberrorWhy a zone, a rule or a wall clock was refused.
A zone database is a binary format with a version byte, a set of rules whose text is a small language of its own, and a question — which instant does this clock name — that has no answer for one hour a year in most of the world. Each of those fails in its own way, and the message says which.
- Malformed(kind~ : String, at~ : Int32)
- Truncated(want~ : Int32, got~ : Int32)
- Unsupported(version~ : Char)
- Unknown(name~ : String)
- Missing(text~ : String)
- BadDate(@moondate.Refused)
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
@tzdata
Errors
Refused
suberrorWhy a zone, a rule or a wall clock was refused.
A zone database is a binary format with a version byte, a set of rules whose text is a small language of its own, and a question — which instant does this clock name — that has no answer for one hour a year in most of the world. Each of those fails in its own way, and the message says which.
- BadText(@moondate.Refused)
- BadZone(@zone.Refused)
Writes the text form to a logger, from Show.
The text form, as a String, from Show.
Functions
The zone filed under name, or None when the database has no such name.
The aliases the database keeps, each with the zone it names: (alias, zone).
A link is a name a country used to be filed under, or the name of a city that shares a zone with another: Asia/Calcutta is Asia/Kolkata, and a caller that stored the old name should go on getting the right answer.
The zone filed under name, which may be an alias.
The zone is compiled from the release's source the first time it is asked for, which is a table of a few hundred readings per zone; a program that needs a dozen zones pays for a dozen.
A moment read from text whose zone is named by a place.
[@moondate.parse] keeps a place name when the offset is written beside it and refuses it when it is not: the place alone does not say which side of a transition the clock was on. This is the entry point that knows — it reads the place from the database and answers with fold for the hour that has none.
let moment = @tzdata.parse("2026-11-01T01:30:00[America/New_York]") moment.strftime("%H:%M %Z") // 01:30 EDT
A text that names an offset rather than a place is answered by [@moondate.parse] alone, so this costs a database lookup and nothing else.
Every name the database knows, the aliases included, in order.
Constants
The IANA release this package carries.
The SHA-256 of the source text below, so a release can be recognised without reading the whole of it.
@zoneinfo
Errors
Refused
suberrorWhy a zone, a rule or a wall clock was refused.
A zone database is a binary format with a version byte, a set of rules whose text is a small language of its own, and a question — which instant does this clock name — that has no answer for one hour a year in most of the world. Each of those fails in its own way, and the message says which.
- Missing(path~ : String)
- Unreadable(path~ : String, said~ : String)
- BadZone(@zone.Refused)
- Unset
Structural equality from Eq.
The negation of equal, from Eq.
Writes the text form to a logger, from Show.
The debug representation, from Debug.
The text form, as a String, from Show.
Functions
The directory the zones are filed in.
TZDIR when the environment names one, and /usr/share/zoneinfo otherwise, which is where the IANA release is installed on every system that has one. A machine that keeps them elsewhere — a container with a copy in the image, a program that carries its own — says so with TZDIR.
The zone filed under name in [directory], which is what a zone name means to the system: Asia/Shanghai, America/New_York, Etc/UTC.
A zone read from the TZif file at path.
let tz = @zoneinfo.open("/etc/localtime") tz.abbrev(1790058605) // EDT, on a machine set to New York
name is what the zone is filed under, and the path is what it is filed under by default: a TZif file carries no name of its own, so the only name there is is the one it was found by. [named] passes the zone's name instead.
The zone this machine is set to.
What TZ says, and /etc/localtime when it says nothing — the two answers every other library's localtime gives, in that order:
TZunset: the file at/etc/localtime, which is how a system states its
zone to everything that asks.
TZempty: UTC, which POSIX says outright rather than by omission.TZa name, with or without the leading:glibc allows: the file of that
name in [directory].
TZa path, starting at/: that file, wherever it is.TZanything else: a POSIX TZ rule, which is howCST-8and
EST5EDT,M3.2.0,M11.1.0 are written and how a container states a zone without carrying a database.
A machine that names nothing is Unset rather than UTC. Guessing UTC is how a program silently writes timestamps eight hours out; a caller that wants UTC can say so, and a machine whose TZ is empty has said it.