Module time/instant
The two clocks: Instant (monotonic, for measuring elapsed time) and
SystemTime (wall clock, for timestamps that outlive the process).
They are deliberately DIFFERENT TYPES and not interconvertible. A monotonic reading has no meaning outside this process — it cannot be persisted, compared across machines, or turned into a date — while a wall-clock reading can jump backwards when the system clock is adjusted and so must never be used to measure a duration. Rust draws the same line, and mixing them is the bug the split prevents.
Example
{ Instant, SystemTime, UNIX_EPOCH } :: import "std/time/instant";
start := Instant.now();
// ... do work ...
println(start.elapsed().as_millis()); // elapsed: monotonic
t := SystemTime.now();
match(t.duration_since(UNIX_EPOCH), // timestamp: wall clock
.Ok(d) => println(d.as_secs()),
.Err(e) => println(e)
);
Stability
unstable — SystemTime arrived in v0.2.28 (#522) and has had one release,
and two shapes here still differ from Rust in ways that a caller can only
discover by reading the body. Instant.duration_since and Instant.sub
CLAMP at zero, where Rust's Instant::duration_since panics on a later
argument and splits the non-panicking cases into checked_duration_since
and saturating_duration_since; the clamp is defensible for a monotonic
clock but it silently turns a reversed-argument bug into a zero. Neither
type has the checked_add/checked_sub Rust offers, Instant has no
Hash or Default while Duration has both, and SystemTime has no
ToString/Debug — a timestamp that cannot be printed. Instant.add/
sub also multiply out to a nanosecond count, which is exactly what the
SystemTime helpers below were written to avoid; it is harmless only
because a monotonic reading is uptime rather than a date.
Freezing needs the clamp-vs-checked_* split decided and those trait gaps
filled. The two-clock division itself is settled and will not move.
Types
Snapshot from the monotonic clock. Use elapsed to measure durations.
Fields
| Name | Type | Description |
|---|---|---|
secs | i64 | Whole seconds since the Unix epoch. Negative before 1970. |
nanos | i64 | Sub-second part, always in |
Trait Implementations
impl(Instant, ...)
now : (Instant) fn() -> InstantRead the wall clock. Panics if CLOCK_REALTIME fails, for the same
reason Instant.now does: a broken clock must not silently read as the
epoch.
Returns: Instant
duration_since : (Instant) fn(self : Instant, earlier : Instant) -> Durationimpl(Instant, ...)
add : (Instant) fn(self : Instant, d : Duration) -> Instantimpl(Instant, Eq(Instant)(...))
impl(Instant, Ord(Instant)(...))
Methods
== : (Instant) fn(lhs : Instant, rhs : Instant) -> bool!= : (Instant) fn(lhs : Instant, rhs : Instant) -> bool< : (Instant) fn(lhs : Instant, rhs : Instant) -> bool<= : (Instant) fn(lhs : Instant, rhs : Instant) -> bool> : (Instant) fn(lhs : Instant, rhs : Instant) -> bool>= : (Instant) fn(lhs : Instant, rhs : Instant) -> boolRaised when a SystemTime comparison runs backwards.
Not a theoretical case: the system clock can be stepped by NTP or by hand,
so a timestamp taken later can precede one taken earlier. Rust returns a
Result from duration_since/elapsed for exactly this, and returning a
silent Duration.zero() instead — the way Instant.duration_since may,
since a monotonic clock cannot go backwards — would hide a real clock jump.
Variants
| Variant | Fields | Description |
|---|---|---|
EarlierThan | by: Duration |
|
Trait Implementations
impl(generic(T : Type), where(T <: ToString), T : (ToString))
impl(generic(T : Type), where(T <: ToString), T : (ToString), Format)
format : fn(self : Self, spec : str) -> StringRender self under spec. An unrecognised spec degrades to the plain
to_string() rendering rather than failing.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Self | |
spec | str |
Returns: String
Methods
to_string : (SystemTimeError) fn(self : SystemTimeError) -> Stringsource : (SystemTimeError) fn(self : SystemTimeError) -> Option(dyn( + ToString))The error that caused this one, or .None at the root of the chain.
Rust's Error::source. Defaulted to .None, so an error with nothing
underneath it implements the trait by saying only what it is; a wrapper
overrides it to hand back what it wrapped. Walking the chain to the root
cause is not expressible yet — the returned Dyn loses the Error
trait on an erased receiver, so a caller can print one link but cannot
follow it (#521,
issues/self-trait-in-a-return-type-loses-the-trait-on-an-erased-receiver.md).
Parameters
| Name | Type | Notes |
|---|---|---|
self | SystemTimeError |
A wall-clock timestamp, measured from UNIX_EPOCH.
Use this for anything that leaves the process — a file's mtime, a log line,
a serialized record. Use Instant to MEASURE, never this: the wall clock
can jump.
Fields
| Name | Type | Description |
|---|---|---|
secs | i64 | Whole seconds since the Unix epoch. Negative before 1970. |
nanos | i64 | Sub-second part, always in |
Trait Implementations
impl(SystemTime, ...)
now : (SystemTime) fn() -> SystemTimeRead the wall clock. Panics if CLOCK_REALTIME fails, for the same
reason Instant.now does: a broken clock must not silently read as the
epoch.
Returns: SystemTime
from_unix_secs : (SystemTime) fn(secs : i64) -> SystemTimeA timestamp from whole seconds since the epoch — what a stat field or
a serialized record carries.
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
secs | i64 | Whole seconds since the Unix epoch. Negative before 1970. |
Returns: SystemTime
from_unix_parts : (SystemTime) fn(secs : i64, nanos : i64) -> SystemTimeA timestamp from seconds plus a nanosecond part. nanos outside
[0, 1e9) is carried into secs, so a caller need not pre-normalize;
OS timestamp fields already supply a value in range.
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
secs | i64 | Whole seconds since the Unix epoch. Negative before 1970. | |
nanos | i64 | Sub-second part, always in |
Returns: SystemTime
as_unix_secs : (SystemTime) fn(self : SystemTime) -> i64Whole seconds since the epoch, truncating the sub-second part.
Parameters
| Name | Type | Notes |
|---|---|---|
self | SystemTime |
Returns: i64
duration_since : (SystemTime) fn(self : SystemTime, earlier : SystemTime) -> Result(Duration, SystemTimeError)How much later self is than earlier, or .Err when it is EARLIER —
which means the clock was adjusted between the two readings.
Parameters
| Name | Type | Notes |
|---|---|---|
self | SystemTime | |
earlier | SystemTime |
Returns: Result(Duration, SystemTimeError)
elapsed : (SystemTime) fn(self : SystemTime) -> Result(Duration, SystemTimeError)How long ago self was, or .Err if it is in the future.
Parameters
| Name | Type | Notes |
|---|---|---|
self | SystemTime |
Returns: Result(Duration, SystemTimeError)
add : (SystemTime) fn(self : SystemTime, d : Duration) -> SystemTimesub : (SystemTime) fn(self : SystemTime, d : Duration) -> SystemTimeimpl(SystemTime, Eq(SystemTime)(...))
impl(SystemTime, Ord(SystemTime)(...))
Methods
== : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> bool!= : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> bool< : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> bool<= : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> bool> : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> bool>= : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> boolcmp : (SystemTime) fn(lhs : SystemTime, rhs : SystemTime) -> OrderingConstants
1970-01-01T00:00:00Z — the anchor SystemTime is measured from.
Value: SystemTime(secs: 0, nanos: 0)