Skip to main content

clock_lib/
wall.rs

1//! Wall-clock readings.
2//!
3//! Wall-clock time is calendar time, sourced from the operating system's
4//! real-time clock. It is the right tool for timestamps in logs, audit
5//! records, and anything that needs to line up with what a wristwatch
6//! shows. It is the wrong tool for measuring elapsed time — wall-clock
7//! readings can jump backwards or forwards at any moment (NTP corrections,
8//! DST changes, manual adjustments).
9//!
10//! For elapsed-time measurement, use [`Monotonic`](crate::Monotonic).
11
12#[cfg(feature = "std")]
13use std::time::{SystemTime, UNIX_EPOCH};
14
15/// A captured wall-clock instant.
16///
17/// `Wall` wraps a single sample of the operating system's real-time clock.
18/// Convert it to Unix time with [`unix_seconds`](Wall::unix_seconds),
19/// [`unix_millis`](Wall::unix_millis), or [`unix_nanos`](Wall::unix_nanos).
20///
21/// `Wall` and [`Monotonic`](crate::Monotonic) are deliberately distinct
22/// types and cannot be mixed. If your system clock predates the Unix
23/// epoch (1970-01-01 UTC), the `unix_*` accessors saturate at zero — they
24/// never panic and never silently wrap.
25///
26/// Construct one with [`Wall::now`] or the crate-level
27/// [`wall`](crate::wall) shortcut.
28///
29/// # Examples
30///
31/// ```
32/// use clock_lib::Wall;
33///
34/// let stamp = Wall::now();
35/// let seconds = stamp.unix_seconds();
36/// assert!(seconds > 0);
37/// ```
38#[cfg(feature = "std")]
39#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
40#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub struct Wall(pub(crate) SystemTime);
42
43#[cfg(feature = "std")]
44impl Wall {
45    /// Captures the current wall-clock time from the operating system.
46    ///
47    /// This is the constructor for [`Wall`]. The crate-level
48    /// [`wall`](crate::wall) function is a one-line shortcut for the same
49    /// thing.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use clock_lib::Wall;
55    ///
56    /// let stamp = Wall::now();
57    /// # let _ = stamp;
58    /// ```
59    #[inline]
60    #[must_use]
61    pub fn now() -> Self {
62        Self(SystemTime::now())
63    }
64
65    /// Returns Unix time in whole seconds.
66    ///
67    /// Returns zero if the system clock is set to a moment before the Unix
68    /// epoch. The return type is [`u64`], which is sufficient to represent
69    /// any plausible wall-clock value through year 584,942,417,355 — Unix
70    /// time will not overflow this accessor.
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// use clock_lib::Wall;
76    ///
77    /// let seconds = Wall::now().unix_seconds();
78    /// assert!(seconds > 0);
79    /// ```
80    #[inline]
81    #[must_use]
82    pub fn unix_seconds(self) -> u64 {
83        self.0.duration_since(UNIX_EPOCH).map_or(0, |d| d.as_secs())
84    }
85
86    /// Returns Unix time in whole milliseconds.
87    ///
88    /// Returns zero if the system clock is set to a moment before the Unix
89    /// epoch. The return type is [`u128`], which cannot overflow for any
90    /// representable [`SystemTime`].
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use clock_lib::Wall;
96    ///
97    /// let millis = Wall::now().unix_millis();
98    /// assert!(millis > 0);
99    /// ```
100    #[inline]
101    #[must_use]
102    pub fn unix_millis(self) -> u128 {
103        self.0
104            .duration_since(UNIX_EPOCH)
105            .map_or(0, |d| d.as_millis())
106    }
107
108    /// Returns Unix time in whole nanoseconds.
109    ///
110    /// Returns zero if the system clock is set to a moment before the Unix
111    /// epoch. The return type is [`u128`], which cannot overflow for any
112    /// representable [`SystemTime`].
113    ///
114    /// # Examples
115    ///
116    /// ```
117    /// use clock_lib::Wall;
118    ///
119    /// let nanos = Wall::now().unix_nanos();
120    /// assert!(nanos > 0);
121    /// ```
122    #[inline]
123    #[must_use]
124    pub fn unix_nanos(self) -> u128 {
125        self.0
126            .duration_since(UNIX_EPOCH)
127            .map_or(0, |d| d.as_nanos())
128    }
129}