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}