ZDate
The instant type. Identity is epoch nanoseconds (bigint); everything else is a view.
Construction
import {zdate, ZDate} from '@sajajs/zdate'
zdate(source?, viewOptions?) // factory
new ZDate(source?, viewOptions?) // constructor, same behaviorThe factory also carries the statics: zdate.min, zdate.max, zdate.defaults.
A ZDate consists of two ZView projections: .utc and .local. The utc projection is always UTC; the local projection is in the requested or default zone. Both projections share the same epoch, locale, and calendar.
The Source Resolves the Epoch
source accepts a string (any supported format), an epoch bigint, a Date, calendar fields, a snapshot, a ZDate, or nothing (now).
The source's only job is to resolve the epoch. View options never participate in that resolution:
zdate('2024-01-15T12:00:00Z')
zdate('2024-01-15T12:00:00Z', {zone: 'Asia/Tokyo'})
// same instant — the zone changed the view, not the resolutionOne exception: natural dates are relative, so they are anchored to the current time with the given view options before being applied.
An RFC 9557 suffix zone is the case where this rule earns its keep: the suffix participates in resolution — it names the rules that turn the wall time into an epoch — and that is all it does. It does not become the local view unless adopted with 'source'. Examples live in Creating Instants; the rationale lives in Time Zones and DST.
View Options
viewOptions sets zone, locale, and calendar for the views. Anything omitted falls back to the process defaults.
Passing ViewOptions as the first argument means "now, with these views" — an ergonomic shorthand in which the second argument is ignored:
zdate({zone: 'Asia/Tokyo'}) // identical to zdate(undefined, {zone: 'Asia/Tokyo'})Adopting the Source's Views
Some sources carry view data of their own: an RFC 9557 string has a suffix zone and calendar, a snapshot has all three fields, a ZDate has its views, calendar fields name their calendar and zone. 'source' adopts that data instead of the defaults — for all three fields at once, or per field:
zdate(input, 'source') // zone, locale, and calendar from the source
zdate(input, {zone: 'source'}) // just the zone; locale and calendar use defaultsIf 'source' is requested and the source has no data for that field, the default is used.
Properties
| Member | Returns | Description |
|---|---|---|
epoch | bigint | Epoch nanoseconds — the identity |
utc | ZView | The UTC projection |
local | ZView | The zoned projection |
parsedSuffix | ParsedSuffix | undefined | RFC 9557 suffix data captured at parse |
parsedSuffix is parse-origin metadata, not value metadata. It exists only on the instance that parsed the string; derived instances — the results of with(), by(), and to() — intentionally do not inherit it.
Another way of thinking about this is, parsedSuffix is only populated when the source timestamp is RFC 9557 — a method like to() does not create its new instance from an RFC 9557 timestamp, so the result has no parsedSuffix.
If you need the suffix beyond the instance that parsed it, read parsedSuffix and keep it — no derived instance will carry it for you.
Statics
| Member | Description |
|---|---|
ZDate.defaults | Process-wide ZDefaults: setZone(), setLocale(), setCalendar() |
ZDate.min(...dates) | Earliest of the given dates |
ZDate.max(...dates) | Latest of the given dates |
Verbs
with(options)
Same instant, different view options. Returns a new ZDate.
d.with({zone: 'Asia/Tokyo'})
d.with({calendar: 'hebrew', locale: 'he-IL'})format(format, options?)
Render a view as text. Named formats ('rfc9557', 'rfc3339', 'rfc9110', …) or specifier patterns. Options select the UTC view or a per-call calendar. See Formatting.
compare(other, unit?)
Order two instants: negative, zero, or positive. An optional unit compares at a granularity ('day', 'minute', …).
by(input)
Move by an amount. Accepts a duration string, a ZDuration, or delta fields. Calendar-aware in the view's calendar.
d.by('2 days')
d.by({months: 1, hours: -3})to(input)
Move to a destination. Three shapes:
d.to('start of month') // boundary — named destination
d.to({nearest: 'minute', interval: 30}) // interval — snapped destination
d.to({month: 2, hour: 22}) // fields — explicit destinationdiff(other?, unit?)
The distance to another instant as a ZDuration. With no argument, measures to now.
Protocol
valueOf() returns the epoch bigint, so <, >, and sorting work directly. toJSON() and toString() emit RFC 9557.
