std.time

import std.time

time.now()            # Unix milliseconds
time.now_iso()        # "2026-07-30T09:12:44.120Z"
time.monotonic()      # milliseconds, for measuring elapsed time
time.monotonic_ns()   # the same clock in nanoseconds
time.format(ms, "%Y-%m-%d")
time.parse("2026-07-30T09:12:44Z")
time.parse_format("30/07/2026", "%d/%m/%Y")

Two clocks, and they are not interchangeable

now() is the wall clock - Unix milliseconds. Use it for timestamps: when something happened, what to store, what to show a person. It can jump backwards when the system clock is corrected or adjusted by NTP.

Both clocks are milliseconds. now() counts from the epoch; monotonic() counts from an arbitrary start, so its value means nothing alone - only the difference between two readings does. monotonic_ns() is the same steady clock in nanoseconds, for timing work shorter than a millisecond. (Before 0.58 monotonic() returned Float seconds; see Migration.)

monotonic() never goes backwards. Use it for durations:

start = time.monotonic()
do_work()
elapsed_ms = time.monotonic() - start     # an Int

Measuring with now() can produce a negative duration, which is a bug that appears rarely and confusingly. Measure with monotonic, timestamp with now.

Formatting and parsing

format(ms, pattern) and parse_format(text, pattern) use strftime-style patterns, in UTC. ms may be a Float, truncated to whole milliseconds; one that is not a finite number in range is an error rather than some other date. parse reads ISO 8601, and now_iso() produces it.

format_local(ms, pattern) formats in the machine's own time zone (TZ where set). Use it for times a person reads - a log file named for when the run started - and format for anything stored or compared.

Prefer ISO 8601 for anything stored or transmitted: it sorts lexicographically, carries its timezone, and is unambiguous - unlike 30/07/2026, which means two different dates depending on the reader.

A pattern with an unknown specifier is an ordinary error, catchable with try - worth knowing when the pattern comes from a config file or a flag rather than from source.

Determinism

Wall-clock values in program output make it untestable. Where output is asserted - tests, examples, anything compared - either avoid a timestamp or inject it, so the comparison does not depend on when it ran.

std.log deliberately adds no automatic timestamp for the same reason. Add time.now() as a field when you want one.

Calendars

This module is timestamps, formatting and monotonic timing. For calendar arithmetic - adding months, weekday names, date components, durations - use the datetime package.