3.7 KiB
Time and Timing (Zig 0.16.0)
Primary release-note source: https://ziglang.org/download/0.16.0/release-notes.html
Zig 0.16 moves time APIs that depend on the runtime behind std.Io. Use std.Io.Timestamp, std.Io.Duration, and std.Io.Clock.
Migration Summary
Choose an explicit clock when migrating old time APIs. Use
std.Io.Timestamp.now(io, .real) for wall time and .boot or .awake for
elapsed-time measurements; Timestamp is not a one-for-one timer replacement.
{D}duration formatting -> formatstd.Io.Durationwith{f}
std.time still provides constants and calendar helpers such as ns_per_ms, ns_per_s, and std.time.epoch.
Clocks
std.Io.Clock values:
.real: wall-clock Unix/POSIX time, affected by clock changes..awake: monotonic-style clock intended to exclude suspend time where possible..boot: monotonic-style clock intended to include suspend time where possible..cpu_process: CPU time used by current process..cpu_thread: CPU time used by current thread.
Current Timestamp
const wall = std.Io.Timestamp.now(io, .real);
const boot = std.Io.Timestamp.now(io, .boot);
const awake = std.Io.Timestamp.now(io, .awake);
Clock-specific wrapper:
const start = std.Io.Clock.Timestamp.now(io, .boot);
Duration
const d1 = std.Io.Duration.fromMilliseconds(16);
const d2 = std.Io.Duration.fromSeconds(1);
const ns = d1.toNanoseconds();
_ = .{ d2, ns };
Formatting:
try writer.print("{f}", .{std.Io.Duration.fromMilliseconds(250)});
Do not use the removed {D} format specifier.
Elapsed Time
const start = std.Io.Timestamp.now(io, .boot);
// work
const end = std.Io.Timestamp.now(io, .boot);
const elapsed = start.durationTo(end);
Or with clock-tagged timestamps:
const start = std.Io.Clock.Timestamp.now(io, .boot);
// work
const elapsed = start.untilNow(io);
Sleeping
Use clock-aware durations/timestamps so sleeping cooperates with the selected
std.Io backend and propagates cancelation.
try std.Io.Clock.Duration{
.raw = std.Io.Duration.fromMilliseconds(10),
.clock = .boot,
}.sleep(io);
Resolution
Clock resolution may fail or return zero for unsupported clocks.
const clock: std.Io.Clock = .boot;
const resolution = try clock.resolution(io);
if (resolution.nanoseconds == 0) {
return error.ClockUnavailable;
}
Epoch and Calendar Helpers
Use std.time.epoch for calendar conversion. Timestamps can be converted to seconds:
const now = std.Io.Timestamp.now(io, .real);
const seconds: u64 = @intCast(now.toSeconds());
const epoch_seconds = std.time.epoch.EpochSeconds{ .secs = seconds };
This conversion is only valid for non-negative Unix timestamps and truncates sub-second precision. Guard pre-epoch values or retain a signed representation.
Application Guidance
- Put common wall-clock timestamp reads behind a shared application helper when consistent clock selection matters.
- Store/pass
std.Ioon timer systems that sample time repeatedly. - Avoid direct
std.time.microTimestamp-style callsites in new code; route through the shared helper. - Use
.bootor.awakefor elapsed-time measurement; use.realfor timestamps intended to correspond to wall-clock time.
Review Checklist
- Is the code using
std.Io.Timestamp.now(io, clock)rather than oldstd.time.timestamphelpers? - Is the clock choice documented by usage (
.realfor wall time, monotonic clocks for elapsed time)? - Is duration formatting using
{f}withstd.Io.Duration? - Does the API receive or store
iorather than constructing a fallback locally? - Does sleeping use a clock-aware
std.IoAPI and handleerror.Canceled?