prism3_clock/monotonic.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Monotonic clock implementation.
10//!
11//! This module provides [`MonotonicClock`], a clock implementation that
12//! guarantees monotonically increasing time values, unaffected by system time
13//! adjustments.
14//!
15//! # Author
16//!
17//! Haixing Hu
18
19use crate::Clock;
20use chrono::Utc;
21use std::time::Instant;
22
23/// A clock implementation that provides monotonically increasing time.
24///
25/// This clock uses `std::time::Instant` as its time source, which guarantees
26/// that time always moves forward and is not affected by system time
27/// adjustments (e.g., NTP synchronization, manual changes).
28///
29/// The clock records a base point when created, and all subsequent time
30/// queries are calculated relative to this base point.
31///
32/// # Use Cases
33///
34/// - Performance monitoring
35/// - Timeout control
36/// - Measuring time intervals
37/// - Any scenario requiring stable, monotonic time
38///
39/// # Note
40///
41/// This clock is designed for measuring time intervals, not for getting the
42/// "current time" for display purposes. For timezone support, you can wrap it
43/// with [`Zoned`](crate::Zoned), but this is generally not recommended as
44/// timezone information is not meaningful for interval measurements.
45///
46/// # Thread Safety
47///
48/// This type is completely thread-safe as all fields are immutable after
49/// creation.
50///
51/// # Examples
52///
53/// ```
54/// use prism3_clock::{Clock, MonotonicClock};
55/// use std::thread;
56/// use std::time::Duration;
57///
58/// let clock = MonotonicClock::new();
59/// let start = clock.millis();
60///
61/// thread::sleep(Duration::from_millis(100));
62///
63/// let elapsed = clock.millis() - start;
64/// assert!(elapsed >= 100);
65/// ```
66///
67/// # Author
68///
69/// Haixing Hu
70#[derive(Debug, Clone)]
71pub struct MonotonicClock {
72 /// The base instant when this clock was created.
73 instant_base: Instant,
74 /// The system time (in milliseconds) when this clock was created.
75 system_time_base_millis: i64,
76}
77
78impl MonotonicClock {
79 /// Creates a new `MonotonicClock`.
80 ///
81 /// The clock records the current instant and system time as its base
82 /// point. All subsequent time queries will be calculated relative to this
83 /// base point.
84 ///
85 /// # Returns
86 ///
87 /// A new `MonotonicClock` instance.
88 ///
89 /// # Examples
90 ///
91 /// ```
92 /// use prism3_clock::MonotonicClock;
93 ///
94 /// let clock = MonotonicClock::new();
95 /// ```
96 ///
97 pub fn new() -> Self {
98 MonotonicClock {
99 instant_base: Instant::now(),
100 system_time_base_millis: Utc::now().timestamp_millis(),
101 }
102 }
103}
104
105impl Default for MonotonicClock {
106 fn default() -> Self {
107 Self::new()
108 }
109}
110
111impl Clock for MonotonicClock {
112 fn millis(&self) -> i64 {
113 let elapsed = self.instant_base.elapsed();
114 let elapsed_millis = elapsed.as_millis() as i64;
115 self.system_time_base_millis + elapsed_millis
116 }
117}