Skip to main content

Overview

The std.time module provides utilities for measuring time intervals, working with timestamps, and time unit conversions. It offers high-resolution monotonic timers and cross-platform time operations.

Time Constants

Nanosecond Conversions

pub const ns_per_us = 1000;              // Nanoseconds per microsecond
pub const ns_per_ms = 1000 * ns_per_us;  // Nanoseconds per millisecond
pub const ns_per_s = 1000 * ns_per_ms;   // Nanoseconds per second
pub const ns_per_min = 60 * ns_per_s;    // Nanoseconds per minute
pub const ns_per_hour = 60 * ns_per_min; // Nanoseconds per hour
pub const ns_per_day = 24 * ns_per_hour; // Nanoseconds per day
pub const ns_per_week = 7 * ns_per_day;  // Nanoseconds per week

Microsecond Conversions

pub const us_per_ms = 1000;              // Microseconds per millisecond
pub const us_per_s = 1000 * us_per_ms;   // Microseconds per second
pub const us_per_min = 60 * us_per_s;    // Microseconds per minute
pub const us_per_hour = 60 * us_per_min; // Microseconds per hour
pub const us_per_day = 24 * us_per_hour; // Microseconds per day
pub const us_per_week = 7 * us_per_day;  // Microseconds per week

Millisecond Conversions

pub const ms_per_s = 1000;               // Milliseconds per second
pub const ms_per_min = 60 * ms_per_s;    // Milliseconds per minute
pub const ms_per_hour = 60 * ms_per_min; // Milliseconds per hour
pub const ms_per_day = 24 * ms_per_hour; // Milliseconds per day
pub const ms_per_week = 7 * ms_per_day;  // Milliseconds per week

Second Conversions

pub const s_per_min = 60;                // Seconds per minute
pub const s_per_hour = s_per_min * 60;   // Seconds per hour
pub const s_per_day = s_per_hour * 24;   // Seconds per day
pub const s_per_week = s_per_day * 7;    // Seconds per week

Instant

pub const Instant = struct {
    timestamp: /* platform-specific */,
};
Represents a single point in time with respect to the currently executing program. Ticks during suspend and uses the system’s fastest, most precise timer.

Instant.now

pub fn now() error{Unsupported}!Instant;
Queries the system for the current moment of time.
return
Instant
Current time instant.
Example:
const std = @import("std");

const start = try std.time.Instant.now();

// Do some work...

const end = try std.time.Instant.now();
const elapsed = end.since(start);
std.debug.print("Elapsed: {} ns\n", .{elapsed});

Instant.order

pub fn order(self: Instant, other: Instant) std.math.Order;
Compares two instants.
return
std.math.Order
.lt, .eq, or .gt.
Example:
const now = try std.time.Instant.now();
const later = try std.time.Instant.now();

if (later.order(now) == .gt) {
    // later is after now
}

Instant.since

pub fn since(self: Instant, earlier: Instant) u64;
Returns elapsed time in nanoseconds since an earlier instant.
earlier
Instant
The earlier instant to measure from. Must be before or equal to self.
return
u64
Elapsed nanoseconds.
Example:
const start = try std.time.Instant.now();

// ... some operation ...

const end = try std.time.Instant.now();
const ns = end.since(start);
const ms = ns / std.time.ns_per_ms;
std.debug.print("Operation took {} ms\n", .{ms});

Timer

pub const Timer = struct {
    started: Instant,
    previous: Instant,
};
A monotonic, high-performance timer. Ensures monotonicity by saturating on the most previous sample. Use this when you need guaranteed monotonic elapsed time measurements.

Timer.start

pub fn start() Error!Timer;
Initializes the timer by querying for a supported clock.
return
Timer
Initialized timer.
Example:
var timer = try std.time.Timer.start();

Timer.read

pub fn read(self: *Timer) u64;
Reads the timer value in nanoseconds since start or last reset.
return
u64
Elapsed nanoseconds.
Example:
var timer = try std.time.Timer.start();

// Do some work

const elapsed = timer.read();
std.debug.print("Elapsed: {} ns\n", .{elapsed});

Timer.reset

pub fn reset(self: *Timer) void;
Resets the timer value to 0/now. Example:
var timer = try std.time.Timer.start();

// Do work A
const time_a = timer.read();

timer.reset();

// Do work B  
const time_b = timer.read();

Timer.lap

pub fn lap(self: *Timer) u64;
Returns the current value in nanoseconds, then resets the timer.
return
u64
Elapsed nanoseconds before reset.
Example:
var timer = try std.time.Timer.start();

for (iterations) |_| {
    // Do some work
    
    const lap_time = timer.lap();
    std.debug.print("Lap: {} ns\n", .{lap_time});
}

Time Conversion Examples

Nanoseconds to Other Units

const ns: u64 = 1_500_000_000; // 1.5 seconds in nanoseconds

const us = ns / std.time.ns_per_us;     // 1,500,000 microseconds
const ms = ns / std.time.ns_per_ms;     // 1,500 milliseconds
const seconds = ns / std.time.ns_per_s; // 1 second (truncated)

Other Units to Nanoseconds

const milliseconds: u64 = 500;
const ns = milliseconds * std.time.ns_per_ms; // 500,000,000 nanoseconds

const seconds: u64 = 10;
const ns_from_s = seconds * std.time.ns_per_s; // 10,000,000,000 nanoseconds

Duration Formatting

fn formatDuration(ns: u64) void {
    const hours = ns / std.time.ns_per_hour;
    const mins = (ns % std.time.ns_per_hour) / std.time.ns_per_min;
    const secs = (ns % std.time.ns_per_min) / std.time.ns_per_s;
    const ms = (ns % std.time.ns_per_s) / std.time.ns_per_ms;
    
    std.debug.print("{}h {}m {}s {}ms\n", .{hours, mins, secs, ms});
}

Timing Patterns

Benchmarking

const std = @import("std");

fn benchmark(comptime func: anytype, iterations: usize) !u64 {
    var timer = try std.time.Timer.start();
    
    var i: usize = 0;
    while (i < iterations) : (i += 1) {
        func();
    }
    
    const total = timer.read();
    return total / iterations; // Average time per iteration
}

// Usage
const avg_time = try benchmark(myFunction, 1000);
std.debug.print("Average: {} ns\n", .{avg_time});

Timeout Detection

fn doWorkWithTimeout(timeout_ms: u64) !void {
    var timer = try std.time.Timer.start();
    const timeout_ns = timeout_ms * std.time.ns_per_ms;
    
    while (true) {
        // Do some work
        
        if (timer.read() > timeout_ns) {
            return error.Timeout;
        }
        
        if (work_complete) break;
    }
}

Rate Limiting

const RateLimiter = struct {
    last_action: std.time.Instant,
    min_interval_ns: u64,
    
    pub fn canAct(self: *RateLimiter) !bool {
        const now = try std.time.Instant.now();
        const elapsed = now.since(self.last_action);
        
        if (elapsed >= self.min_interval_ns) {
            self.last_action = now;
            return true;
        }
        return false;
    }
};

Epoch Time

pub const epoch = @import("time/epoch.zig");
Utilities for working with Unix epoch timestamps and calendar dates. Common Operations:
// Get seconds since Unix epoch
const timestamp = std.time.epoch.timestamp();

// Convert to date components
const date = std.time.epoch.EpochSeconds.fromTimestamp(timestamp);
const year = date.getEpochYear();

Platform Considerations

Clock Sources

  • Linux: Uses CLOCK_BOOTTIME (includes suspend time)
  • macOS/Darwin: Uses CLOCK_UPTIME_RAW (includes suspend time)
  • Windows: Uses QueryPerformanceCounter (includes suspend time)
  • FreeBSD: Uses CLOCK_MONOTONIC_FAST
  • WASI: Uses clock_time_get(MONOTONIC)

Resolution

Resolution varies by platform but is typically:
  • Linux/macOS: ~1 nanosecond (limited by TSC/CPU frequency)
  • Windows: ~100 nanoseconds
  • WASI: Implementation-dependent

Monotonicity

While Instant and Timer strive for monotonicity, OS and hardware bugs may violate this. For critical use cases requiring strict monotonicity, Timer is preferred as it saturates on previous samples.

Best Practices

  1. Use Timer for elapsed time: Provides guaranteed monotonicity
  2. Use Instant for timestamps: Lightweight, suitable for ordering events
  3. Convert at display time: Keep times in nanoseconds internally, convert when formatting
  4. Handle errors: Instant.now() can fail in hostile environments (e.g., seccomp restrictions)
  5. Avoid subtraction: Use .since() method instead of manual timestamp arithmetic
Example:
// Good
const start = try std.time.Instant.now();
const end = try std.time.Instant.now();
const elapsed = end.since(start);

// Avoid (not guaranteed to be correct on all platforms)
const elapsed = end.timestamp - start.timestamp;

Build docs developers (and LLMs) love