time
std/time — the clock, and what to say about it.
time.now() is a compiler builtin: it reads the runtime's clock in milliseconds. The clock is virtual on the bytecode VM and in the generated glue — when every task is waiting on a deadline it jumps to the earliest — so a program that sleeps costs no real time under test and both backends agree on the order things happened in.
secondsminuteshoursmillissinceshowclockCivilcivil_ofepoch_ofiso_dayhhmmstampweekdayis_leapdays_in_monthmonth_startmonth_end
seconds
pub fn seconds(n: int) -> int
Milliseconds in one second.
minutes
pub fn minutes(n: int) -> int
hours
pub fn hours(n: int) -> int
millis
pub fn millis(n: int) -> int
since
pub fn since(start: int) -> int
How long since a reading taken earlier.
show
pub fn show(ms: int) -> str
A duration in the largest unit that keeps it readable.
clock
pub fn clock(ms: int) -> str
hh:mm:ss from a duration, for a stopwatch or a progress line.
Civil
struct Civil
A moment, split the way a person reads one.
pub year: intpub month: int— 1 to 12.pub day: int— 1 to 31.pub hour: int— 0 to 23.pub minute: intpub second: int
civil_of
pub fn civil_of(ms: int, east_minutes: int) -> Civil
Split an epoch reading into fields.
ms is milliseconds since 1970-01-01T00:00:00Z — what window.epoch_ms() answers, and not what time.now() answers, which is a monotonic reading with no zero point a calendar could use.
let at = civil_of(1_754_697_600_000, 0)
assert(at.year == 2025 && at.month == 8 && at.day == 9, "2025-08-09")
epoch_of
pub fn epoch_of(c: Civil, east_minutes: int) -> int
Put one back together.
The inverse of [civil_of] under the same offset. Fields outside their range are carried rather than refused — month 13 is January of the next year, and day 0 is the last day of the month before — which is what makes Civil{ year: y, month: m + 1, day: 1, … } a correct way to ask for the start of the next month without knowing how long this one is.
iso_day
pub fn iso_day(ms: int, east_minutes: int) -> str
YYYY-MM-DD, which is what a filename wants.
A folder of reports named "10 Jul 2026" sorts April before January. This one sorts in the only order that is unambiguous in every locale.
assert(iso_day(1_754_697_600_000, 0) == "2025-08-09", "a day, written out")
hhmm
pub fn hhmm(ms: int, east_minutes: int) -> str
hh:mm from a moment, for a status bar with no room for a date.
Distinct from [clock] one section up, which reads a duration — the two print the same shape from different numbers, and giving them one name would make the difference invisible at the call site.
stamp
pub fn stamp(ms: int, east_minutes: int) -> str
YYYY-MM-DDThh:mm:ss, without an offset suffix.
The suffix is left off because this renders in whatever zone was asked for and appending Z to a local reading is a lie a log keeps forever. A caller who wants a true RFC 3339 timestamp passes 0 and adds the Z itself.
weekday
pub fn weekday(ms: int, east_minutes: int) -> int
The day of the week: 0 is Sunday, 6 is Saturday.
is_leap
pub fn is_leap(year: int) -> bool
Whether a year has a 29th of February.
days_in_month
pub fn days_in_month(year: int, month: int) -> int
How many days are in a month, 1 to 12.
Counted as the distance between two firsts rather than read out of a table with a leap-year branch beside it. The table and the branch can disagree; two calls to the same function cannot.
month_start
pub fn month_start(year: int, month: int, east_minutes: int) -> int
The first millisecond of a month.
month outside 1 to 12 is carried, so month_start(y, 13, e) is January of the following year — which is how [month_end] finds the boundary without asking how long the month it is ending happens to be.
month_end
pub fn month_end(year: int, month: int, east_minutes: int) -> int
The last millisecond that still belongs to a month.
Inclusive, so a query written >= month_start(…) and <= month_end(…) cannot let the midnight between two months fall into both or into neither.