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}