Skip to main content

aa_core/
time.rs

1//! Timestamp abstraction compatible with `no_std` environments.
2//!
3//! In `no_std` mode the caller is responsible for supplying the nanosecond
4//! value. In `std` mode a [`From<SystemTime>`] convenience impl is available.
5
6/// Nanoseconds since the Unix epoch.
7///
8/// In `no_std` environments use [`Timestamp::from_nanos`] to construct a value
9/// directly. In `std` environments the [`From<std::time::SystemTime>`] impl
10/// can be used as a convenience.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
14#[cfg_attr(feature = "schemars", schemars(transparent))]
15pub struct Timestamp(u64);
16
17impl Timestamp {
18    /// Construct a [`Timestamp`] from raw nanoseconds since the Unix epoch.
19    #[inline]
20    pub const fn from_nanos(nanos: u64) -> Self {
21        Self(nanos)
22    }
23
24    /// Return the raw nanosecond value.
25    #[inline]
26    pub const fn as_nanos(&self) -> u64 {
27        self.0
28    }
29}
30
31#[cfg(feature = "std")]
32impl From<std::time::SystemTime> for Timestamp {
33    fn from(t: std::time::SystemTime) -> Self {
34        let nanos = t
35            .duration_since(std::time::UNIX_EPOCH)
36            .expect("system time before Unix epoch")
37            .as_nanos() as u64;
38        Self(nanos)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn round_trips_nanos() {
48        let ts = Timestamp::from_nanos(1_000_000_000);
49        assert_eq!(ts.as_nanos(), 1_000_000_000);
50    }
51
52    #[cfg(feature = "std")]
53    #[test]
54    fn from_system_time_at_epoch_is_zero() {
55        let ts = Timestamp::from(std::time::SystemTime::UNIX_EPOCH);
56        assert_eq!(ts.as_nanos(), 0);
57    }
58}