5 unstable releases
Uses new Rust 2024
| 0.2.0 | Feb 17, 2026 |
|---|---|
| 0.1.2 | Jan 5, 2026 |
| 0.1.0 | Dec 16, 2025 |
| 0.0.1 | Dec 5, 2015 |
| 0.0.0 | Sep 9, 2015 |
#84 in Data structures
255 downloads per month
Used in 6 crates
(5 directly)
300KB
4.5K
SLoC
Primitives for obtaining, working with, and mocking system time and timers, enabling faster and more robust testing.
Quick Start
use std::time::Duration;
use tick::{Clock, Delay};
async fn produce_value(clock: &Clock) -> u64 {
let stopwatch = clock.stopwatch();
clock.delay(Duration::from_secs(60)).await;
println!("elapsed time: {}ms", stopwatch.elapsed().as_millis());
123
}
#[tokio::main]
async fn main() {
let clock = Clock::new_tokio();
let value = produce_value(&clock).await;
assert_eq!(value, 123);
}
#[cfg(test)]
mod tests {
use super::*;
use tick::ClockControl;
#[tokio::test]
async fn test_produce_value() {
// Automatically advance timers for instant, deterministic testing
let clock: Clock = ClockControl::new().auto_advance_timers(true).to_clock();
assert_eq!(produce_value(&clock).await, 123);
}
}
Why?
This crate provides a unified API for working with time that:
- Easy async runtime integration - Provides built-in support for Tokio and can be extended to work with other runtimes without tight coupling to any specific implementation.
- Enables deterministic testing - With the
test-utilfeature,ClockControllets you manipulate the passage of time: advance it instantly, pause it, or jump forward. No waiting for a 1-minute periodic job in your tests. - Improves testability - Time-dependent code becomes fast and reproducible to test without relying on wall-clock time.
The testability features are transparent to consuming code, as using Clock works identically
in production and tests, with zero runtime overhead when test-util is disabled.
Overview
Clock- Provides an abstraction for time-related operations. Returns absolute time asSystemTimeand relative time measurements via stopwatch. Used when creating other time primitives.ClockControl- Controls the passage of time. Available when thetest-utilfeature is enabled.Stopwatch- Measures elapsed time.Delay- Delays the execution for a specified duration.PeriodicTimer- Schedules a task to run periodically.Error- Represents an error that can occur when working with time. Provides limited introspection capabilities.fmt- Utilities for formattingSystemTimeinto various formats. Available when thefmtfeature is enabled.runtime- Infrastructure for integrating time primitives into async runtimes.
Extensions
FutureExt- Extensions for theFuturetrait, providing timeout functionality.SystemTimeExt- Extensions forSystemTime.
Machine-Centric vs. Human-Centric Time
When working with time, two different use cases are considered:
- Machine-Centric - Measuring time intervals such as timeouts, periodic activities, cache TTLs, etc. For persistent data, this includes storing, retrieving, and manipulating timestamps, as well as parsing timestamps in well-known formats such as ISO 8601. Machine-centric time has little ambiguity.
- Human-Centric - Wall clock time, formatting, parsing, time zones, calendars. Dealing with human-centric time involves significant ambiguity.
This crate is designed for machine-centric time. For human-centric time manipulation,
consider using other crates such as jiff, chrono, or time. The time primitives in
this crate are designed for easy interoperability with these crates. See the time_interop*
examples for more details.
Thread-aware relocation
All clock types implement ThreadAware, supporting per-core
timer isolation in thread-per-core runtime architectures.
When an InactiveClock is
relocated to a target thread, the underlying timer
storage is duplicated per core. After activation, each thread’s Clock and
ClockDriver operate on an independent set of timers with no
cross-thread lock contention.
ClockControl clocks are unaffected by relocation, all clones always share the same
controlled time state regardless of thread, so a single ClockControl can drive time for
the entire test.
See the runtime module documentation for setup examples.
Testing
This crate provides a way to control the passage of time in tests via the ClockControl
type, which is exposed when the test-util feature is enabled.
Important: Never enable the
test-utilfeature for production code. Only use it in yourdev-dependencies.
Examples
Use Clock to retrieve absolute time
The clock provides absolute time as SystemTime. See Clock documentation for detailed
information.
use std::time::{Duration, SystemTime};
use tick::Clock;
// Using SystemTime for basic absolute time needs
let time1: SystemTime = clock.system_time();
let time2: SystemTime = clock.system_time();
// Time is always moving forward. Note that system time might be
// adjusted by the operating system between calls.
assert!(time1 <= time2);
Use Clock to retrieve relative time
The clock provides relative time via Clock::instant and Stopwatch.
use std::time::{Duration, Instant};
use tick::Clock;
// Using clock.stopwatch() for convenient elapsed time measurement
let stopwatch = clock.stopwatch();
// Perform some operation...
let elapsed: Duration = stopwatch.elapsed();
// Using Clock::instant for lower-level access to monotonic time
let start: Instant = clock.instant();
// Perform some operation...
let end: Instant = clock.instant();
Use Stopwatch for measurements
use std::time::Duration;
use tick::Clock;
let stopwatch = clock.stopwatch();
// Perform some operation...
stopwatch.elapsed()
Use Clock to create a PeriodicTimer
use std::time::Duration;
use futures::StreamExt;
use tick::{Clock, PeriodicTimer};
// Delay for 10ms before the timer starts ticking
clock.delay(Duration::from_millis(10)).await;
let timer = PeriodicTimer::new(clock, Duration::from_millis(1));
timer
.take(3)
.for_each(async |()| {
// Do something every 1ms
})
.await;
Features
This crate provides several optional features that can be enabled in your Cargo.toml:
tokio- Integration with the Tokio runtime. EnablesClock::new_tokiofor creating clocks that use Tokio’s time facilities.test-util- Enables theClockControltype for controlling the passage of time in tests. This allows you to pause time, advance it manually, or automatically advance timers for fast, deterministic testing. Only enable this indev-dependencies.serde- Adds serialization and deserialization support via serde.fmt- Enables thefmtmodule with utilities for formattingSystemTimeinto various formats (e.g., ISO 8601, RFC 2822).
Additional Examples
The time examples contain additional examples of how to use the time primitives.
This crate was developed as part of The Oxidizer Project. Browse this crate's source code.
Dependencies
~0–1.9MB
~28K SLoC