lambda_appsync/aws_scalars/
timestamp.rs1use serde::{Deserialize, Serialize};
2use std::time::{Duration, SystemTime};
3
4#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
7#[serde(from = "u64", into = "u64")]
8pub struct AWSTimestamp(SystemTime);
9
10impl AWSTimestamp {
11 pub fn now() -> Self {
20 Self(SystemTime::now())
21 }
22
23 pub fn into_u64(self) -> u64 {
33 self.into()
34 }
35
36 pub fn from_u64(value: u64) -> Self {
46 Self::from(value)
47 }
48}
49
50impl From<SystemTime> for AWSTimestamp {
51 fn from(time: SystemTime) -> Self {
52 Self(time)
53 }
54}
55
56impl PartialEq<SystemTime> for AWSTimestamp {
57 fn eq(&self, other: &SystemTime) -> bool {
58 self.0 == *other
59 }
60}
61
62impl From<AWSTimestamp> for u64 {
63 fn from(value: AWSTimestamp) -> Self {
64 value
65 .0
66 .duration_since(std::time::UNIX_EPOCH)
67 .expect("we should never manipulate dates earlier than EPOCH")
68 .as_secs()
69 }
70}
71
72impl std::fmt::Display for AWSTimestamp {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 write!(f, "{}", u64::from(*self))
75 }
76}
77
78impl From<u64> for AWSTimestamp {
79 fn from(value: u64) -> Self {
80 Self(std::time::UNIX_EPOCH + Duration::from_secs(value))
81 }
82}
83
84impl Default for AWSTimestamp {
85 fn default() -> Self {
86 Self::now()
87 }
88}
89
90impl std::ops::Add<Duration> for AWSTimestamp {
91 type Output = Self;
92 fn add(self, rhs: Duration) -> Self::Output {
93 Self(self.0 + rhs)
94 }
95}
96
97impl std::ops::AddAssign<Duration> for AWSTimestamp {
98 fn add_assign(&mut self, rhs: Duration) {
99 self.0 += rhs;
100 }
101}
102
103impl std::ops::Sub<Duration> for AWSTimestamp {
104 type Output = Self;
105 fn sub(self, rhs: Duration) -> Self::Output {
106 Self(self.0 - rhs)
107 }
108}
109
110impl std::ops::SubAssign<Duration> for AWSTimestamp {
111 fn sub_assign(&mut self, rhs: Duration) {
112 self.0 -= rhs;
113 }
114}
115
116impl std::ops::Sub<AWSTimestamp> for AWSTimestamp {
117 type Output = Duration;
118 fn sub(self, rhs: AWSTimestamp) -> Self::Output {
119 self.0
120 .duration_since(rhs.0)
121 .expect("the substracted AWSTimestamp MUST be earlier")
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_timestamp_now() {
131 let ts = AWSTimestamp::now();
132 let now = SystemTime::now();
133 let diff = now.duration_since(ts.0).unwrap();
134 assert!(diff < Duration::from_secs(1));
135 }
136
137 #[test]
138 fn test_timestamp_default() {
139 let ts = AWSTimestamp::default();
140 let now = SystemTime::now();
141 let diff = now.duration_since(ts.0).unwrap();
142 assert!(diff < Duration::from_secs(1));
143 }
144
145 #[test]
146 fn test_timestamp_conversion() {
147 let now = SystemTime::now();
148 let secs = now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
149 let ts = AWSTimestamp::from(secs);
150 let back_to_secs: u64 = ts.into();
151 assert_eq!(secs, back_to_secs);
152 }
153
154 #[test]
155 fn test_timestamp_add() {
156 let ts = AWSTimestamp::from(1000);
157 let ts2 = ts + Duration::from_secs(500);
158 let secs: u64 = ts2.into();
159 assert_eq!(secs, 1500);
160 }
161
162 #[test]
163 fn test_timestamp_add_assign() {
164 let mut ts = AWSTimestamp::from(1000);
165 ts += Duration::from_secs(500);
166 let secs: u64 = ts.into();
167 assert_eq!(secs, 1500);
168 }
169
170 #[test]
171 fn test_timestamp_sub_duration() {
172 let ts = AWSTimestamp::from(1000);
173 let ts2 = ts - Duration::from_secs(500);
174 let secs: u64 = ts2.into();
175 assert_eq!(secs, 500);
176 }
177
178 #[test]
179 fn test_timestamp_sub_assign() {
180 let mut ts = AWSTimestamp::from(1000);
181 ts -= Duration::from_secs(500);
182 let secs: u64 = ts.into();
183 assert_eq!(secs, 500);
184 }
185
186 #[test]
187 fn test_timestamp_sub_timestamp() {
188 let ts1 = AWSTimestamp::from(1500);
189 let ts2 = AWSTimestamp::from(1000);
190 let diff = ts1 - ts2;
191 assert_eq!(diff.as_secs(), 500);
192 }
193
194 #[test]
195 #[should_panic(expected = "the substracted AWSTimestamp MUST be earlier")]
196 fn test_timestamp_sub_panic() {
197 let ts1 = AWSTimestamp::from(1000);
198 let ts2 = AWSTimestamp::from(1500);
199 let _diff = ts1 - ts2;
200 }
201
202 #[test]
203 fn test_display() {
204 let ts = AWSTimestamp::from(1234);
205 assert_eq!(ts.to_string(), "1234");
206 }
207
208 #[test]
209 fn test_from_system_time() {
210 let now = SystemTime::now();
211 let ts = AWSTimestamp::from(now);
212 assert_eq!(ts.0, now);
213 }
214
215 #[test]
216 fn test_partial_eq_system_time() {
217 let now = SystemTime::now();
218 let ts = AWSTimestamp::from(now);
219 assert_eq!(ts, now);
220 }
221
222 #[test]
223 fn test_into_u64() {
224 let ts = AWSTimestamp::from(1234);
225 assert_eq!(ts.into_u64(), 1234);
226 }
227
228 #[test]
229 fn test_from_u64() {
230 let ts = AWSTimestamp::from_u64(1234);
231 assert_eq!(ts.into_u64(), 1234);
232 }
233}