Skip to main content

qubit_clock/clock/
clock.rs

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