lambda_appsync/aws_scalars/
timestamp.rs

1use serde::{Deserialize, Serialize};
2use std::time::{Duration, SystemTime};
3
4#[doc = "AWS AppSync specific GraphQL scalar type implemented a [String] new-type"]
5#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
6#[serde(from = "u64", into = "u64")]
7pub struct AWSTimestamp(SystemTime);
8impl AWSTimestamp {
9    /// Returns an [AWSTimestamp] representing the current date and time, as reported by the system clock.
10    ///
11    /// # Example
12    /// ```
13    /// use lambda_appsync::AWSTimestamp;
14    ///
15    /// let now = AWSTimestamp::now();
16    /// ```
17    pub fn now() -> Self {
18        Self(SystemTime::now())
19    }
20}
21impl From<AWSTimestamp> for u64 {
22    fn from(value: AWSTimestamp) -> Self {
23        value
24            .0
25            .duration_since(std::time::UNIX_EPOCH)
26            .expect("we should never manipulate dates earlier than EPOCH")
27            .as_secs()
28    }
29}
30impl From<u64> for AWSTimestamp {
31    fn from(value: u64) -> Self {
32        Self(std::time::UNIX_EPOCH + Duration::from_secs(value))
33    }
34}
35impl Default for AWSTimestamp {
36    fn default() -> Self {
37        Self::now()
38    }
39}
40impl std::ops::Add<Duration> for AWSTimestamp {
41    type Output = Self;
42    fn add(self, rhs: Duration) -> Self::Output {
43        Self(self.0 + rhs)
44    }
45}
46impl std::ops::Sub<Duration> for AWSTimestamp {
47    type Output = Self;
48    fn sub(self, rhs: Duration) -> Self::Output {
49        Self(self.0 - rhs)
50    }
51}
52impl std::ops::Sub<AWSTimestamp> for AWSTimestamp {
53    type Output = Duration;
54    fn sub(self, rhs: AWSTimestamp) -> Self::Output {
55        self.0
56            .duration_since(rhs.0)
57            .expect("the substracted AWSTimestamp MUST be earlier")
58    }
59}
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_timestamp_now() {
66        let ts = AWSTimestamp::now();
67        let now = SystemTime::now();
68        let diff = now.duration_since(ts.0).unwrap();
69        assert!(diff < Duration::from_secs(1));
70    }
71
72    #[test]
73    fn test_timestamp_default() {
74        let ts = AWSTimestamp::default();
75        let now = SystemTime::now();
76        let diff = now.duration_since(ts.0).unwrap();
77        assert!(diff < Duration::from_secs(1));
78    }
79
80    #[test]
81    fn test_timestamp_conversion() {
82        let now = SystemTime::now();
83        let secs = now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
84        let ts = AWSTimestamp::from(secs);
85        let back_to_secs: u64 = ts.into();
86        assert_eq!(secs, back_to_secs);
87    }
88
89    #[test]
90    fn test_timestamp_add() {
91        let ts = AWSTimestamp::from(1000);
92        let ts2 = ts + Duration::from_secs(500);
93        let secs: u64 = ts2.into();
94        assert_eq!(secs, 1500);
95    }
96
97    #[test]
98    fn test_timestamp_sub_duration() {
99        let ts = AWSTimestamp::from(1000);
100        let ts2 = ts - Duration::from_secs(500);
101        let secs: u64 = ts2.into();
102        assert_eq!(secs, 500);
103    }
104
105    #[test]
106    fn test_timestamp_sub_timestamp() {
107        let ts1 = AWSTimestamp::from(1500);
108        let ts2 = AWSTimestamp::from(1000);
109        let diff = ts1 - ts2;
110        assert_eq!(diff.as_secs(), 500);
111    }
112
113    #[test]
114    #[should_panic(expected = "the substracted AWSTimestamp MUST be earlier")]
115    fn test_timestamp_sub_panic() {
116        let ts1 = AWSTimestamp::from(1000);
117        let ts2 = AWSTimestamp::from(1500);
118        let _diff = ts1 - ts2;
119    }
120}