nostr_types/types/
unixtime.rs

1use derive_more::{AsMut, AsRef, Deref, Display, From, Into};
2use serde::{Deserialize, Serialize};
3#[cfg(feature = "speedy")]
4use speedy::{Readable, Writable};
5use std::ops::{Add, Sub};
6use std::time::Duration;
7
8/// An integer count of the number of seconds from 1st January 1970.
9/// This does not count any of the leap seconds that have occurred, it
10/// simply presumes UTC never had leap seconds; yet it is well known
11/// and well understood.
12#[derive(
13    AsMut,
14    AsRef,
15    Clone,
16    Copy,
17    Debug,
18    Deref,
19    Deserialize,
20    Display,
21    Eq,
22    From,
23    Into,
24    Ord,
25    PartialEq,
26    PartialOrd,
27    Serialize,
28)]
29#[cfg_attr(feature = "speedy", derive(Readable, Writable))]
30pub struct Unixtime(pub i64);
31
32impl Unixtime {
33    /// Get the current unixtime (depends on the system clock being accurate)
34    pub fn now() -> Unixtime {
35        Unixtime(std::time::UNIX_EPOCH.elapsed().unwrap().as_secs() as i64)
36    }
37
38    // Mock data for testing
39    #[allow(dead_code)]
40    pub(crate) fn mock() -> Unixtime {
41        Unixtime(1668572286)
42    }
43}
44
45impl Add<Duration> for Unixtime {
46    type Output = Self;
47
48    fn add(self, rhs: Duration) -> Self::Output {
49        Unixtime(self.0 + rhs.as_secs() as i64)
50    }
51}
52
53impl Sub<Duration> for Unixtime {
54    type Output = Self;
55
56    fn sub(self, rhs: Duration) -> Self::Output {
57        Unixtime(self.0 - rhs.as_secs() as i64)
58    }
59}
60
61impl Sub<Unixtime> for Unixtime {
62    type Output = Duration;
63
64    fn sub(self, rhs: Unixtime) -> Self::Output {
65        Duration::from_secs((self.0 - rhs.0).unsigned_abs())
66    }
67}
68
69#[cfg(test)]
70mod test {
71    use super::*;
72
73    test_serde! {Unixtime, test_unixtime_serde}
74
75    #[test]
76    fn test_print_now() {
77        println!("NOW: {}", Unixtime::now());
78    }
79
80    #[test]
81    fn test_unixtime_math() {
82        let now = Unixtime::now();
83        let fut = now + Duration::from_secs(70);
84        assert!(fut > now);
85        assert_eq!(fut.0 - now.0, 70);
86        let back = fut - Duration::from_secs(70);
87        assert_eq!(now, back);
88        assert_eq!(now - back, Duration::ZERO);
89    }
90}