1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Primitives for obtaining, working with, and mocking system
//! time and timers, enabling faster and more robust testing.
//!
//! # Quick Start
//!
//! ```no_run
//! 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 tick::ClockControl;
//!
//! use super::*;
//!
//! #[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-util` feature, [`ClockControl`] lets 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
//! as `SystemTime` and relative time measurements via stopwatch. Used when creating other
//! time primitives.
//! - [`ClockControl`] - Controls the passage of time. Available when the `test-util` feature
//! 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 formatting `SystemTime` into various formats. Available when
//! the `fmt` feature is enabled.
//! - [`runtime`] - Infrastructure for integrating time primitives into async runtimes.
//!
//! # Extensions
//!
//! - [`FutureExt`] - Extensions for the `Future` trait, providing timeout functionality.
//! - [`SystemTimeExt`] - Extensions for [`SystemTime`][`std::time::SystemTime`].
//!
//! # 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.
//!
//! [jiff]: https://crates.io/crates/jiff
//! [chrono]: https://crates.io/crates/chrono
//! [time]: https://crates.io/crates/time
//!
//! # Thread-aware relocation
//!
//! All clock types implement [`ThreadAware`](thread_aware::ThreadAware), supporting per-core
//! timer isolation in thread-per-core runtime architectures.
//!
//! When an [`InactiveClock`][runtime::InactiveClock] is
//! [relocated](thread_aware::ThreadAware::relocate) to a target thread, the underlying timer
//! storage is duplicated per core. After activation, each thread's [`Clock`] and
//! [`ClockDriver`][runtime::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-util` feature for production code. Only use it in your `dev-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;
//!
//! # fn retrieve_absolute_time(clock: &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;
//!
//! # fn retrieve_relative_time(clock: &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;
//!
//! # fn measure(clock: &Clock) -> Duration {
//! 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};
//!
//! # async fn periodic_timer_example(clock: &Clock) {
//! // 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](https://tokio.rs/) runtime. Enables
//! [`Clock::new_tokio`] for creating clocks that use Tokio's time facilities.
//! - **`test-util`** - Enables the [`ClockControl`] type 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 in `dev-dependencies`.**
//! - **`serde`** - Adds serialization and deserialization support via [serde](https://serde.rs/).
//! - **`fmt`** - Enables the [`fmt`] module with utilities for formatting `SystemTime` into
//! various formats (e.g., ISO 8601, RFC 2822).
//!
//! # Additional Examples
//!
//! The [time examples](https://github.com/microsoft/oxidizer/tree/main/crates/tick/examples)
//! contain additional examples of how to use the time primitives.
pub
pub use Clock;
pub use ClockControl;
pub use Delay;
pub use ;
pub use FutureExt;
pub use PeriodicTimer;
pub use Stopwatch;
pub use SystemTimeExt;
pub use Timeout;
/// Implements [`ThreadAware`](thread_aware::ThreadAware) for types that don't require any special relocation handling.
pub use thread_aware_move;