Skip to main content

qubit_clock/clock/
nano_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//! High-precision clock trait providing nanosecond accuracy.
11//!
12//! This module defines the [`NanoClock`] trait, which extends [`Clock`] to
13//! provide nanosecond-precision time measurements.
14//!
15
16use crate::Clock;
17use chrono::{
18    DateTime,
19    Utc,
20};
21
22/// A trait representing a clock with nanosecond precision.
23///
24/// This trait extends [`Clock`] to provide high-precision time measurements
25/// at the nanosecond level. It's useful for performance testing,
26/// microbenchmarking, and scenarios requiring very precise time measurements.
27///
28/// # Note
29///
30/// The nanosecond timestamp is stored as an `i128` to avoid overflow issues.
31///
32/// # Examples
33///
34/// ```
35/// use qubit_clock::{NanoClock, NanoMonotonicClock};
36///
37/// let clock = NanoMonotonicClock::new();
38/// let start = clock.nanos();
39///
40/// // Perform some operation
41/// for _ in 0..1000 {
42///     // Some work
43/// }
44///
45/// let elapsed = clock.nanos() - start;
46/// println!("Elapsed: {} ns", elapsed);
47/// ```
48///
49pub trait NanoClock: Clock {
50    /// Returns the current time as a Unix timestamp in nanoseconds (UTC).
51    ///
52    /// The timestamp represents the number of nanoseconds since the Unix
53    /// epoch (1970-01-01 00:00:00 UTC).
54    ///
55    /// # Returns
56    ///
57    /// The current time as nanoseconds since the Unix epoch.
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use qubit_clock::{NanoClock, NanoMonotonicClock};
63    ///
64    /// let clock = NanoMonotonicClock::new();
65    /// let nanos = clock.nanos();
66    /// assert!(nanos > 0);
67    /// ```
68    fn nanos(&self) -> i128;
69
70    /// Returns the current time as a `DateTime<Utc>` with nanosecond
71    /// precision.
72    ///
73    /// This method has a default implementation that constructs a
74    /// `DateTime<Utc>` from the result of [`nanos()`](NanoClock::nanos).
75    /// If the nanosecond timestamp is outside chrono's representable range,
76    /// the result is clamped to the nearest representable UTC datetime.
77    ///
78    /// # Returns
79    ///
80    /// The current time as a `DateTime<Utc>` object with nanosecond
81    /// precision.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// use qubit_clock::{NanoClock, NanoMonotonicClock};
87    ///
88    /// let clock = NanoMonotonicClock::new();
89    /// let time = clock.time_precise();
90    /// println!("Current time (precise): {}", time);
91    /// ```
92    #[inline]
93    fn time_precise(&self) -> DateTime<Utc> {
94        let nanos = self.nanos();
95        let secs = nanos.div_euclid(1_000_000_000);
96        let nsecs = nanos.rem_euclid(1_000_000_000) as u32;
97        let secs = match i64::try_from(secs) {
98            Ok(value) => value,
99            Err(_) if nanos < 0 => return DateTime::<Utc>::MIN_UTC,
100            Err(_) => return DateTime::<Utc>::MAX_UTC,
101        };
102        DateTime::from_timestamp(secs, nsecs).unwrap_or({
103            if nanos < 0 {
104                DateTime::<Utc>::MIN_UTC
105            } else {
106                DateTime::<Utc>::MAX_UTC
107            }
108        })
109    }
110}