Atoll distinguishes elapsed spans, absolute instants, civil values, and zoned views. All core temporal values use a microsecond storage base so they cross the SQL temporal boundary without unit conversion.
| Type | Meaning |
|---|---|
Duration |
Signed elapsed time |
DateTime |
UTC instant |
Date |
Civil date |
Time |
Time of day |
TimeZone |
IANA zone identifier |
ZonedDateTime |
Instant viewed in a time zone |
Durations
Construct a duration with an explicit unit:
timeout := Duration.of_seconds(30)
retry_window := Duration.of_minutes(5)
combined := timeout.plus(retry_window)Constructors cover nanoseconds, microseconds, milliseconds, seconds, minutes,
hours, and days. Nanosecond input is truncated to the microsecond storage
resolution. total_nanos() scales that stored value back up; it cannot restore
discarded sub-microsecond precision.
| Operation | Purpose |
|---|---|
total_micros, total_millis, total_seconds |
Read a whole-unit total |
total_minutes, total_hours |
Read larger whole-unit totals |
plus, minus, times, negated |
Arithmetic |
is_zero, is_negative, less_than, equals |
Comparison |
Total-unit accessors truncate toward zero when the stored span is not an exact multiple of the requested unit.
Instants
DateTime is a UTC instant measured from the Unix epoch:
started := DateTime.now()
deadline := started.plus(Duration.of_seconds(30))
elapsed := DateTime.now().diff(started)Use from_epoch_nanos, from_epoch_micros, from_epoch_millis, or
from_epoch_seconds at protocol boundaries. Matching epoch_* accessors
convert back. Nanosecond construction truncates to microseconds, while
millisecond and second accessors truncate lower precision.
year, month, day, hour, minute, and second read UTC calendar
components. date() and time() produce the corresponding civil values.
is_before, is_after, and equals compare instants.
DateTime.now() reads the host wall clock and therefore suspends. It is not a
monotonic elapsed-time source; clock adjustments can affect differences between
separate calls.
Civil values
Date stores a calendar day. Date.today() uses the current UTC date.
from_epoch_days and epoch_days convert to and from days since
1970-01-01. Day arithmetic is explicit:
today := Date.today()
next_week := today.plus_days(7)
year := next_week.year()Time.of_hms(hour, minute, second) creates a time of day.
micros_of_day, hour, minute, and second expose its components. A
Time has no date or time-zone context.
The current constructors do not return validation errors for out-of-range
calendar components. Validate untrusted hour, minute, and second input before
calling Time.of_hms.
Time zones
TimeZone.utc() requires no lookup. TimeZone.of(name) resolves an IANA zone
name through the host and returns None when the name is unknown:
zone := TimeZone.of("Asia/Kuala_Lumpur")
match zone {
Some(value) => {
local := DateTime.now().in_zone(value)
println("${local.hour()}:${local.minute()}")
}
None => report_unknown_zone()
}DateTime.in_zone(zone) creates a ZonedDateTime for the supplied instant.
Its calendar accessors report local components. offset() returns the UTC
offset, to_utc() recovers the original instant, and date()/time() return
local civil values.
Offsets and daylight-saving status depend on both zone and instant:
instant := DateTime.from_epoch_seconds(epoch)
offset := zone.offset_at(instant)
summer_time := zone.is_dst(instant)Zone lookup and DST-aware offset queries use host time-zone data and may
suspend. Store absolute events as DateTime; apply a TimeZone for display or
calendar decisions.
Current limits
Duration suffix literals described in the older async document are not used in
this chapter because the current lexer does not define them as a stable literal
family; use Duration.of_* constructors.
The installed temporal surface does not yet provide parsing, formatting, month/year arithmetic, day-of-week values, date ranges, or constructors that resolve a local civil time into an instant. Keep such policy in an application or host integration until those APIs become part of the prelude.