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}