Skip to main content

qubit_clock/
clock.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! The base clock trait providing UTC time.
10//!
11//! This module defines the [`Clock`] trait, which is the foundation of the
12//! clock abstraction. All clock implementations must implement this trait.
13//!
14//! # Author
15//!
16//! Haixing Hu
17
18use chrono::{DateTime, Utc};
19
20/// Clamps an out-of-range millisecond timestamp to chrono's nearest boundary.
21fn clamp_out_of_range_millis(millis: i64) -> DateTime<Utc> {
22    if millis < 0 {
23        DateTime::<Utc>::MIN_UTC
24    } else {
25        DateTime::<Utc>::MAX_UTC
26    }
27}
28
29/// A trait representing a clock that provides UTC time.
30///
31/// This is the base trait for all clock implementations. It provides methods
32/// to get the current time as a Unix timestamp (milliseconds) or as a
33/// `DateTime<Utc>` object.
34///
35/// All methods return **UTC time** only. For timezone support, see
36/// [`ZonedClock`](crate::ZonedClock).
37///
38/// # Thread Safety
39///
40/// All implementations must be `Send + Sync` to ensure thread safety.
41///
42/// # Examples
43///
44/// ```
45/// use qubit_clock::{Clock, SystemClock};
46///
47/// let clock = SystemClock::new();
48/// let timestamp = clock.millis();
49/// let time = clock.time();
50/// println!("Current time: {}", time);
51/// ```
52///
53/// # Author
54///
55/// Haixing Hu
56pub trait Clock: Send + Sync {
57    /// Returns the current time as a Unix timestamp in milliseconds (UTC).
58    ///
59    /// The timestamp represents the number of milliseconds since the Unix
60    /// epoch (1970-01-01 00:00:00 UTC).
61    ///
62    /// # Returns
63    ///
64    /// The current time as milliseconds since the Unix epoch.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use qubit_clock::{Clock, SystemClock};
70    ///
71    /// let clock = SystemClock::new();
72    /// let millis = clock.millis();
73    /// assert!(millis > 0);
74    /// ```
75    fn millis(&self) -> i64;
76
77    /// Returns the current time as a `DateTime<Utc>`.
78    ///
79    /// This method has a default implementation that constructs a
80    /// `DateTime<Utc>` from the result of [`millis()`](Clock::millis).
81    /// If the millisecond timestamp is outside chrono's representable range,
82    /// the result is clamped to the nearest representable UTC datetime.
83    ///
84    /// # Returns
85    ///
86    /// The current time as a `DateTime<Utc>` object.
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// use qubit_clock::{Clock, SystemClock};
92    ///
93    /// let clock = SystemClock::new();
94    /// let time = clock.time();
95    /// println!("Current time: {}", time);
96    /// ```
97    #[inline]
98    fn time(&self) -> DateTime<Utc> {
99        let millis = self.millis();
100        DateTime::from_timestamp_millis(millis).unwrap_or_else(|| clamp_out_of_range_millis(millis))
101    }
102}