@core/time separates elapsed time from wall-clock time. Import it when you need to measure durations or work with UTC timestamps.
Three types of time
Duration for elapsed amountsTimeMark for measuring elapsed time and frame deltasTimestamp for real-world UTC instants
These types stay opaque. Pass them to the package functions. Do not construct them with struct syntax.
Measuring elapsed time
Use TimeMark for a monotonic measurement point. Use Duration for the elapsed amount.
import @core/time {
TimeMark,
mark_now,
duration_between,
as_seconds,
}
previous ~= mark_now()
current = mark_now()
delta = duration_between(previous, current)
previous = current
seconds = as_seconds(delta)
This shape works for frame-delta style code without requiring a scheduler or animation package.
UTC timestamps
Use Timestamp for real-world UTC instants that may be logged, stored or exchanged with external systems.
import @core/time {
Timestamp,
timestamp_from_iso_string,
timestamp_from_unix_milliseconds,
to_iso_string,
}
parse_created || -> Timestamp, Error!:
return timestamp_from_iso_string("1970-01-01T00:00:00.000Z")!
;
created = parse_created() catch:
then timestamp_from_unix_milliseconds(0.0)
;
io.line(to_iso_string(created))
timestamp_from_iso_string takes the fallible path because invalid strings can fail. Handle it with ! or catch. For the full function list, backend behaviour and deferred surfaces, see Core time advanced.
@core/time separates elapsed time from wall-clock time. It belongs to the binding-backed Core package family with no prelude alias, so it requires an explicit import.
@core/time carries Core origin with ExternalBinding backing. See Package origins and backing for origin and backing rules.
Import roots
Import individual symbols or the whole namespace:
import @core/time {
Duration,
TimeMark,
mark_now,
duration_between,
as_seconds,
}
import @core/time
previous = time.mark_now()
Opaque types
The package exposes three opaque types. Do not construct them with struct syntax or inspect their fields. Pass them to the package functions.
| Type | Purpose | |---|---| | Duration | Signed elapsed amount | | TimeMark | Monotonic clock mark for deltas and frame timing | | Timestamp | UTC wall-clock instant for logs, storage and system boundaries |
All three use the handle ABI. They carry no source-visible fields.
Monotonic clock functions
| Function | Parameters | Returns | Error | |---|---|---|---| | mark_now() | none | TimeMark | no | | elapsed_since(start) | TimeMark | Duration | no | | duration_between(start, end) | TimeMark, TimeMark | Duration | no |
mark_now() returns the current monotonic mark. elapsed_since(start) returns the duration from start to now. duration_between(start, end) returns the duration from start to end.
Wall-clock timestamp functions
| Function | Parameters | Returns | Error | |---|---|---|---| | timestamp_now() | none | Timestamp | no | | timestamp_from_unix_seconds(seconds) | Float | Timestamp | no | | timestamp_from_unix_milliseconds(milliseconds) | Float | Timestamp | no | | timestamp_from_iso_string(text) | String | Timestamp, Error! | yes |
timestamp_from_iso_string is the only fallible function. Invalid ISO strings return through Error!.
import @core/time {
Timestamp,
timestamp_from_iso_string,
timestamp_from_unix_milliseconds,
}
created = timestamp_from_iso_string("not-a-date") catch:
then timestamp_from_unix_milliseconds(0.0)
;
Duration construction and helpers
| Function | Parameters | Returns | Error | |---|---|---|---| | duration_from_seconds(seconds) | Float | Duration | no | | duration_from_milliseconds(milliseconds) | Float | Duration | no | | as_seconds(duration) | Duration | Float | no | | as_milliseconds(duration) | Duration | Float | no | | is_negative(duration) | Duration | Bool | no | | abs(duration) | Duration | Duration | no | | clamp(duration, min, max) | Duration, Duration, Duration | Duration | no |
Timestamp helpers
| Function | Parameters | Returns | Error | |---|---|---|---| | unix_seconds(timestamp) | Timestamp | Float | no | | unix_milliseconds(timestamp) | Timestamp | Float | no | | to_iso_string(timestamp) | Timestamp | String | no |
Access and return contracts
All parameters use shared access. No function requires mutable access. All return values stay fresh. timestamp_from_iso_string returns through Error! on invalid input. Every other function stays infallible.
Backend behaviour
HTML-JS lowers mark_now to globalThis.performance.now(). timestamp_now lowers to Date.now(). to_iso_string lowers to (new Date(#0)).toISOString(). Duration and timestamp construction helpers lower to inline JavaScript expressions.
HTML-Wasm lacks a Wasm lowering for these functions. See progress matrix for current target availability.
Unsupported source forms
- Direct symbol-path imports such as
import @core/time/mark_now face rejection. Use grouped or namespace imports. - Named arguments are not supported. Binding-backed calls are positional-only.
- Do not construct
Duration, TimeMark or Timestamp with struct syntax. - Do not inspect opaque type fields directly.
- The package does not expose receiver methods.
Deferred surfaces
Calendar date types, time zones, local-time conversion, locale-aware formatting, timers, sleep, intervals, animation callbacks and non-JS lowerings remain deferred. Browser animation-frame integration belongs in a future web-specific package rather than @core/time. See progress matrix for current status.
Related concepts