12. Time Functions
The Time library provides typed UTC timestamps and durations, stored as signed
64-bit counts of 100-nanosecond ticks. There are 10000000 ticks per second.
A UTC value counts ticks since 1970-01-01T00:00:00Z, without time-zone or
leap-second state; a duration counts elapsed ticks. These are distinct types
from integers and from each other. No implicit conversion turns a number into a duration.
See DUST for language rules, the core arithmetic reference for shared operators, and the Function Index for all callable entries.
Table of Contents
12.1. Range and resolution ↑
One tick is 100 ns, or 0.0000001 s. The signed 64-bit range provides roughly
29,227.7 Gregorian years on either side of the Unix epoch, approximately
27,258 BCE through 31,197 CE. Exact endpoint spellings use astronomical year
numbering, including year zero:
| Payload | Canonical UTC |
|---|---|
-9223372036854775808 ticks |
-27258-04-19T21:11:54.5224192Z |
9223372036854775807 ticks |
31197-09-14T02:48:05.4775807Z |
The range covers recorded history, back to the
first writing in Uruk around
3400 BCE: clay tablets logging deliveries, rations, and labor, the first event logs.
It also leaves room for the prototype's fictional touchstones: Dune's
Butlerian Jihad
and the Horus Heresy, whose
official timeline includes events in 005.M31 through 014.M31, around
30,005–30,014 CE. The Dune Encyclopedia dates its Jihad as 200–108 B.G.; a
conversion to a specific Gregorian year is not part of this API.
The resolution remains fine enough to describe fast motion. Using the
prototype's approximate Parker Solar Probe speed of 191.2 km/s, a 100 ns tick
corresponds to 191200 × 0.0000001 = 0.01912 m, about 19 mm.
NASA reports its record flyby speed as about 430,000 mph,
which gives the same approximately 19 mm scale per tick.
Windows FILETIME
also uses 100 ns units, with a different epoch. A representation's resolution
does not guarantee that a clock or scheduler measures time that accurately.
Canonical timestamps and durations use at most seven fractional second digits. Text accepts up to nine fractional second digits and is rounded to the nearest tick, with halfway cases rounded away from zero. A nonzero timestamp or duration that would round to zero is represented by one tick in magnitude.
(time/utc -9223372036854775808) (time/utc 9223372036854775807) (time/utc 30005-01-01T00:00:00Z)
#utc -27258-04-19T21:11:54.5224192Z #utc 31197-09-14T02:48:05.4775807Z #utc 30005-01-01T00:00:00Z
(time/duration -9223372036854775808) (time/duration 9223372036854775807) (time/units ns (time/duration 1))
#dur -P10675199DT2H48M5.4775808S #dur P10675199DT2H48M5.4775807S 100
#utc 2024-02-29T12:34:56.123456700Z #utc 2024-02-29T12:34:56.12345670Z
#utc 2024-02-29T12:34:56.1234567Z #utc 2024-02-29T12:34:56.1234567Z
#utc 2024-02-29T12:34:56.1234567Z #utc 2024-02-29T12:34:56.1234567Z
#dur PT0.000000100S #dur PT0.00000010S
#dur PT0.0000001S #dur PT0.0000001S
#dur PT0.0000001S #dur PT0.0000001S
#utc 1970-01-01T00:00:00.000000001Z
#utc 1970-01-01T00:00:00.0000001Z
#utc 1970-01-01T00:00:00.0000001Z
12.2. Types and conversion ↑
(time/utc value) → UTC
An integer supplies a raw count of 100 ns ticks since the Unix epoch. A string
supplies a UTC timestamp ending in Z. A float supplies a Julian day, following SQLite's
Julian-day convention: day 0.0 is -4713-11-24T12:00:00Z, 2440587.5 is the Unix epoch,
and 2451545.0 is 2000-01-01T12:00:00Z.
Integer and float arguments deliberately have different units. Use an integer for exact tick counts; Julian-day floats have ordinary floating-point precision limits. Julian days are rounded to the nearest tick, with exact halfway cases rounded away from the Unix epoch. Invalid or out-of-range timestamp input is an error.
(time/utc 0) (time/utc -1) (time/utc 2024-02-29T12:34:56.1234567Z)
#utc 1970-01-01T00:00:00Z #utc 1969-12-31T23:59:59.9999999Z #utc 2024-02-29T12:34:56.1234567Z
(time/utc 0.0) (time/utc 2440587.5) (time/utc 2451545.0)
#utc -4713-11-24T12:00:00Z #utc 1970-01-01T00:00:00Z #utc 2000-01-01T12:00:00Z
12.2.2. time/duration ↑
Function(time/duration value) → duration
(time/duration amount unit) → duration
With one argument, a number supplies a raw 100 ns tick count and a string
supplies an ISO duration. A float is rounded to the nearest tick, with halfway
cases rounded away from zero and a minimum of one tick in magnitude for
nonzero values: (time/duration 1.5) is two ticks.
With two arguments, amount is an integer or float and unit is one of
ns, us, µs, ms, s, m, h, d, w, tick, or ticks.
Both tick spellings mean 100 ns. Days and weeks mean fixed elapsed intervals
of 24 hours and seven days. The result is always a typed duration.
Numeric amounts are rounded to the nearest tick, with halfway cases rounded
away from zero. A nonzero amount that rounds to zero is raised to one tick
in magnitude. For example, (time/duration 1 ns) is one tick,
(time/duration 101 ns) is one tick, and (time/duration -1 ns) is minus
one tick. (time/duration 1.5 ticks) is two ticks and
(time/duration 1.5 h) returns #dur PT1H30M.
Years and months are calendar offsets, not fixed duration
units; use time/shift for them.
(time/duration 0) (time/duration -1) (time/duration PT1H30M)
#dur PT0S #dur -PT0.0000001S #dur PT1H30M
(time/duration 100 ns) (time/duration 1 us) (time/duration 1 µs) (time/duration 1 ms) (time/duration 1 s) (time/duration 1 m) (time/duration 1 h) (time/duration 1 d) (time/duration 1 w) (time/duration 1 tick) (time/duration 1 ticks) (time/duration 1.5 h)
#dur PT0.0000001S #dur PT0.000001S #dur PT0.000001S #dur PT0.001S #dur PT1S #dur PT1M #dur PT1H #dur P1D #dur P7D #dur PT0.0000001S #dur PT0.0000001S #dur PT1H30M
(time/duration 1.5) (time/duration -1.5) (time/duration 1.4)
#dur PT0.0000002S #dur -PT0.0000002S #dur PT0.0000001S
12.2.3. time/units ↑
Function(time/units unit value) → number
Expresses a UTC timestamp or duration in the requested unit. The unit argument comes first. For UTC, the result measures time since the Unix epoch; for a duration, it measures the elapsed interval. The underlying value remains a signed count of 100 ns ticks.
| Unit | Meaning | Result kind |
|---|---|---|
tick, ticks |
100 ns ticks | Integer |
ns |
Nanoseconds | Integer |
us, µs |
Microseconds | Float |
ms |
Milliseconds | Float |
s |
Seconds | Float |
m |
Minutes | Float |
h |
Hours | Float |
d |
24-hour days | Float |
w |
Seven-day weeks | Float |
Float results retain fractional units. For example,
(time/units s #dur PT1.5S) returns 1.5, while
(time/units ns (time/duration 1)) returns integer 100.
Float conversions can lose precision for large values.
Exact tick counts retain the full signed 64-bit range:
(time/units ticks (time/utc 1)) (time/units ticks (time/duration 1 ticks)) (time/units ticks (time/duration -9223372036854775808))
1 1 -9223372036854775808
Nanosecond results are also integers:
(time/units ns #utc 1970-01-01T00:00:00Z) (time/units ns #dur PT1.5S) (time/units ns #utc 1969-12-31T23:59:59.9999999Z)
0 1500000000 -100
Larger units retain fractional duration values:
(time/units us (time/duration 5)) (time/units us (time/duration -5)) (time/units µs (time/duration 5)) (time/units µs (time/duration -5)) (time/units ms (time/duration 2500)) (time/units ms (time/duration -2500)) (time/units s (time/duration 1250000)) (time/units s (time/duration -1250000)) (time/units m (time/duration 75000000)) (time/units m (time/duration -75000000)) (time/units h (time/duration 4500000000)) (time/units h (time/duration -4500000000)) (time/units d (time/duration 108000000000)) (time/units d (time/duration -108000000000)) (time/units w (time/duration 756000000000)) (time/units w (time/duration -756000000000))
0.5 -0.5 0.5 -0.5 0.25 -0.25 0.125 -0.125 0.125 -0.125 0.125 -0.125 0.125 -0.125 0.125 -0.125
UTC conversions measure fractional units from the Unix epoch:
(time/units us (time/utc 5)) (time/units us (time/utc -5)) (time/units µs (time/utc 5)) (time/units µs (time/utc -5)) (time/units ms (time/utc 2500)) (time/units ms (time/utc -2500)) (time/units s (time/utc 1250000)) (time/units s (time/utc -1250000)) (time/units m (time/utc 75000000)) (time/units m (time/utc -75000000)) (time/units h (time/utc 4500000000)) (time/units h (time/utc -4500000000)) (time/units d (time/utc 108000000000)) (time/units d (time/utc -108000000000)) (time/units w (time/utc 756000000000)) (time/units w (time/utc -756000000000))
0.5 -0.5 0.5 -0.5 0.25 -0.25 0.125 -0.125 0.125 -0.125 0.125 -0.125 0.125 -0.125 0.125 -0.125
Conversion to a finer unit can exceed the signed 64-bit range. In particular, expressing ticks as nanoseconds requires multiplication by 100, so a valid timestamp or duration can overflow that conversion. Overflow is checked.
See the time/units conformance cases.
(time/utc? value) → boolean
Returns whether the value has the UTC kind. Durations and integers return false.
(time/utc? #utc 1970-01-01T00:00Z) (time/utc? #dur PT0S) (time/utc? 0)
(time/utc? #utc 1970-01-01T00:00:00Z) (time/utc? #dur PT0S) (time/utc? 0)
true false false
12.2.5. time/duration? ↑
Function(time/duration? value) → boolean
Returns whether the value has the duration kind. UTC timestamps and integers
return false.
(time/duration? #dur PT0S) (time/duration? #utc 1970-01-01T00:00Z) (time/duration? 0)
(time/duration? #dur PT0S) (time/duration? #utc 1970-01-01T00:00:00Z) (time/duration? 0)
true false false
12.2.6. time/format ↑
Function(time/format value) → string
Formats a UTC timestamp or duration as its canonical ISO string, without a
DUST tag prefix. The full 100 ns tick precision is retained. For readable display text,
use the String library's strings/humanize function.
(time/format #utc 1970-01-01T00:00:00Z) (time/format #utc 1969-12-31T23:59:59.9999999Z) (time/format #dur PT1.5S)
1970-01-01T00:00:00Z 1969-12-31T23:59:59.9999999Z PT1.5S
12.3. Temporal arithmetic ↑
The Core library's shared operators accept these explicit temporal combinations. Each result retains its indicated kind. Arithmetic uses exact signed 64-bit ticks and reports overflow rather than wrapping.
| Operation | Result |
|---|---|
| UTC + duration; duration + UTC | UTC |
| Duration + duration | Duration |
| UTC - duration | UTC |
| UTC - UTC; duration - duration | Duration |
| Duration * integer; integer * duration | Duration |
| Duration / integer | Duration, ticks truncated toward zero |
| Duration / duration | Float ratio |
Operations with several operands fold from left to right, so the kind of each intermediate result determines the next operation. Unary addition preserves UTC and duration values. Unary subtraction negates a duration; a timestamp cannot be negated. Unary multiplication preserves a duration, while a duration has no unary reciprocal.
(+ #utc 1970-01-01T00:00:00Z #dur PT1S) (+ #dur PT1S #utc 1970-01-01T00:00:00Z) (+ #dur PT1S #dur PT2S) (+ #utc 1970-01-01T00:00:00Z) (+ #dur PT1S)
#utc 1970-01-01T00:00:01Z #utc 1970-01-01T00:00:01Z #dur PT3S #utc 1970-01-01T00:00:00Z #dur PT1S
(- #utc 1970-01-01T00:00:01Z #utc 1970-01-01T00:00:00Z) (- #utc 1970-01-01T00:00:01Z #dur PT2S) (- #dur PT3S #dur PT1S) (- #dur PT1S)
#dur PT1S #utc 1969-12-31T23:59:59Z #dur PT2S #dur -PT1S
(* #dur PT1.5S 2) (* 2 #dur PT1.5S) (* #dur PT1S) (* 2 #dur PT3S 2)
#dur PT3S #dur PT3S #dur PT1S #dur PT12S
(/ #dur PT3S 2) (/ #dur PT0.0000001S -2) (/ #dur -PT0.0000003S 2) (/ #dur PT3S #dur PT2S)
#dur PT1.5S #dur PT0S #dur -PT0.0000001S 1.5
math/abs accepts durations. math/min, math/max, and math/clamp accept
matching UTC or duration kinds and preserve the selected value's kind.
They compare all ticks exactly.
(math/abs #dur -PT1S) (math/abs #dur PT0S) (math/abs #dur PT1.5S)
#dur PT1S #dur PT0S #dur PT1.5S
(math/min #dur PT2S #dur PT1S) (math/min #utc 1970-01-02T00:00Z #utc 1970-01-01T00:00Z) (math/min #dur -PT1S #dur PT0S)
(math/min #dur PT2S #dur PT1S) (math/min #utc 1970-01-02T00:00:00Z #utc 1970-01-01T00:00:00Z) (math/min #dur -PT1S #dur PT0S)
#dur PT1S #utc 1970-01-01T00:00:00Z #dur -PT1S
(math/max #dur PT2S #dur PT1S) (math/max #utc 1970-01-02T00:00Z #utc 1970-01-01T00:00Z) (math/max #dur -PT1S #dur PT0S)
(math/max #dur PT2S #dur PT1S) (math/max #utc 1970-01-02T00:00:00Z #utc 1970-01-01T00:00:00Z) (math/max #dur -PT1S #dur PT0S)
#dur PT2S #utc 1970-01-02T00:00:00Z #dur PT0S
(math/clamp #dur PT3S #dur PT1S #dur PT2S) (math/clamp #utc 1970-01-01T00:00Z #utc 1970-01-02T00:00Z #utc 1970-01-03T00:00Z) (math/clamp #dur PT1.5S #dur PT1S #dur PT2S)
(math/clamp #dur PT3S #dur PT1S #dur PT2S) (math/clamp #utc 1970-01-01T00:00:00Z #utc 1970-01-02T00:00:00Z #utc 1970-01-03T00:00:00Z) (math/clamp #dur PT1.5S #dur PT1S #dur PT2S)
#dur PT2S #utc 1970-01-02T00:00:00Z #dur PT1.5S
12.3.1. Rejected combinations and bounds ↑
UTC plus UTC, duration minus UTC, and numeric additions to durations are type errors. Durations multiply only by integers, and division requires an integer or a duration as the divisor. There is no implicit conversion from seconds or another numeric unit; construct a duration explicitly. Zero divisors are errors.
(+ #utc 1970-01-01T00:00Z #utc 1970-01-01T00:00Z)
(+ #utc 1970-01-01T00:00:00Z #utc 1970-01-01T00:00:00Z)
#err <mismatch type>
(- #dur PT1S #utc 1970-01-01T00:00Z)
(- #dur PT1S #utc 1970-01-01T00:00:00Z)
#err <mismatch type>
(math/min #dur PT1S #utc 1970-01-01T00:00Z)
(math/min #dur PT1S #utc 1970-01-01T00:00:00Z)
#err <mismatch type>
(+ #dur PT922337203685.4775807S #dur PT0.0000001S)
(+ #dur P10675199DT2H48M5.4775807S #dur PT0.0000001S)
#err <integer overflow>
(/ #dur -PT922337203685.4775808S -1)
(/ #dur -P10675199DT2H48M5.4775808S -1)
#err <integer overflow>
(math/abs #dur -PT922337203685.4775808S)
(math/abs #dur -P10675199DT2H48M5.4775808S)
#err <integer overflow>
12.4. Calendar operations ↑
Calendar fields and boundaries use UTC. Week boundaries begin on Monday.
12.4.1. time/parts ↑
Function(time/parts timestamp) → map
Returns integer fields year, month, day, hour, minute, second,
nanosecond, and weekday. Months and days start at one. ISO weekdays run from
one for Monday through seven for Sunday. The nanosecond field is the fractional
part of the second, from zero through 999999900 in multiples of 100.
(time/parts #utc 2024-02-29T12:34:56.1234567Z) (time/parts #utc 1970-01-01T00:00:00Z) (time/parts #utc 1969-12-31T23:59:59.9999999Z)
{day 29 hour 12 minute 34 month 2 nanosecond 123456700 second 56 weekday 4 year 2024} {day 1 hour 0 minute 0 month 1 nanosecond 0 second 0 weekday 4 year 1970} {day 31 hour 23 minute 59 month 12 nanosecond 999999900 second 59 weekday 3 year 1969}
12.4.2. time/start-of ↑
Function(time/start-of timestamp unit) → UTC
Returns the start of the containing UTC calendar unit. The unit is one of
year, month, week, day, hour, minute, or second.
This floors to the earlier boundary, including for times before the Unix epoch.
A week's Monday can fall in the preceding month or year.
(time/start-of #utc 2026-05-06T12:34:56.123Z year) (time/start-of #utc 2026-05-06T12:34:56.123Z month) (time/start-of #utc 2026-01-01T12:34:56Z week) (time/start-of #utc 2026-05-06T12:34:56.123Z day) (time/start-of #utc 2026-05-06T12:34:56.123Z hour) (time/start-of #utc 2026-05-06T12:34:56.123Z minute) (time/start-of #utc 1969-12-31T23:59:59.999Z second)
#utc 2026-01-01T00:00:00Z #utc 2026-05-01T00:00:00Z #utc 2025-12-29T00:00:00Z #utc 2026-05-06T00:00:00Z #utc 2026-05-06T12:00:00Z #utc 2026-05-06T12:34:00Z #utc 1969-12-31T23:59:59Z
(time/start-of #utc 1970-01-01T00:00Z fortnight)
(time/start-of #utc 1970-01-01T00:00:00Z fortnight)
#err <invalid value>
12.4.3. time/shift ↑
Function(time/shift timestamp changes) → UTC
Shifts by a map containing integer years, months, and days offsets.
Omitted offsets are zero; negative offsets move backward. Unknown fields and
non-integer offsets are errors.
The year and month offsets are combined into one month shift. The original day
is then clamped to the last valid day of the resulting month, and the day offset
is applied afterward. Time of day and the 100 ns fraction are retained. For example,
January 31 plus one month becomes February 28 or 29. February 29, 2024 plus one
year becomes February 28, 2025. This uses the earlier valid date when the target
month is shorter; SQLite's default ceiling rule
instead resolves that leap-day example to March 1. Combining years 1 and
months -1 shifts February 29, 2024 to January 29, 2025, with only one clamp.
(time/shift #utc 2024-01-31T12:34:56.123Z {months 1}) (time/shift #utc 2023-01-31T12:00Z {months 1}) (time/shift #utc 2024-01-31T12:00Z {days 1 months 1}) (time/shift #utc 2024-02-29T12:00Z {months -1 years 1}) (time/shift #utc 2024-03-31T12:00Z {months -1}) (time/shift #utc 2024-02-29T12:00Z {years 1})
(time/shift #utc 2024-01-31T12:34:56.123Z {months 1}) (time/shift #utc 2023-01-31T12:00:00Z {months 1}) (time/shift #utc 2024-01-31T12:00:00Z {days 1 months 1}) (time/shift #utc 2024-02-29T12:00:00Z {months -1 years 1}) (time/shift #utc 2024-03-31T12:00:00Z {months -1}) (time/shift #utc 2024-02-29T12:00:00Z {years 1})
#utc 2024-02-29T12:34:56.123Z #utc 2023-02-28T12:00:00Z #utc 2024-03-01T12:00:00Z #utc 2025-01-29T12:00:00Z #utc 2024-02-29T12:00:00Z #utc 2025-02-28T12:00:00Z
(time/shift #utc 1970-01-01T00:00Z {hours 1})
(time/shift #utc 1970-01-01T00:00:00Z {hours 1})
#err <invalid value>
(time/shift #utc 1970-01-01T00:00Z {months 1.5})
(time/shift #utc 1970-01-01T00:00:00Z {months 1.5})
#err <mismatch type>
12.5. Duration quantization ↑
Both arguments must be durations, and the quantum must be strictly positive. A rounded result outside signed 64-bit ticks is an overflow error.
12.5.1. time/truncate ↑
Function(time/truncate duration quantum) → duration
Returns the multiple of quantum reached by truncating toward zero.
For example, 1.9s becomes 1s and -1.9s becomes -1s at a one-second quantum.
(time/truncate #dur PT1.9S #dur PT1S) (time/truncate #dur -PT1.9S #dur PT1S) (time/truncate #dur PT0.5S #dur PT1S)
#dur PT1S #dur -PT1S #dur PT0S
12.5.2. time/round ↑
Function(time/round duration quantum) → duration
Returns the nearest multiple of quantum, with halfway cases rounded away
from zero. At a one-second quantum, 1.5s becomes 2s and -1.5s becomes -2s.
(time/round #dur PT1.5S #dur PT1S) (time/round #dur -PT1.5S #dur PT1S) (time/round #dur PT1.4S #dur PT1S)
#dur PT2S #dur -PT2S #dur PT1S
(time/round (time/duration 9223372036854775807) (time/duration 4))
#err <integer overflow>
(time/now) → UTC
Returns the current wall-clock time as a typed UTC value with 100 ns tick storage. Takes no arguments. The wall clock can change independently of evaluation; this function does not provide a monotonic elapsed-time clock.
To humanize a timestamp relative to the clock, pass the returned UTC explicitly:
(strings/humanize #utc 2026-10-29T12:00Z {mode relative now (time/now)})
Use the String library's strings/humanize function for readable
durations or absolute and relative timestamps. Relative formatting requires an
explicit UTC reference time and never reads the clock implicitly.