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(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}