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))]
13pub struct Timestamp(u64);
14
15impl Timestamp {
16    /// Construct a [`Timestamp`] from raw nanoseconds since the Unix epoch.
17    #[inline]
18    pub const fn from_nanos(nanos: u64) -> Self {
19        Self(nanos)
20    }
21
22    /// Return the raw nanosecond value.
23    #[inline]
24    pub const fn as_nanos(&self) -> u64 {
25        self.0
26    }
27}
28
29#[cfg(feature = "std")]
30impl From<std::time::SystemTime> for Timestamp {
31    fn from(t: std::time::SystemTime) -> Self {
32        let nanos = t
33            .duration_since(std::time::UNIX_EPOCH)
34            .expect("system time before Unix epoch")
35            .as_nanos() as u64;
36        Self(nanos)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn round_trips_nanos() {
46        let ts = Timestamp::from_nanos(1_000_000_000);
47        assert_eq!(ts.as_nanos(), 1_000_000_000);
48    }
49
50    #[cfg(feature = "std")]
51    #[test]
52    fn from_system_time_at_epoch_is_zero() {
53        let ts = Timestamp::from(std::time::SystemTime::UNIX_EPOCH);
54        assert_eq!(ts.as_nanos(), 0);
55    }
56}