1use std::time::{Duration, SystemTime, UNIX_EPOCH};
18
19pub trait CheckedSystemTime {
21 fn checked_add(self, _d: Duration) -> Option<SystemTime>;
24 fn checked_sub(self, _d: Duration) -> Option<SystemTime>;
26}
27
28impl CheckedSystemTime for SystemTime {
29 fn checked_add(self, dur: Duration) -> Option<SystemTime> {
30 let this_dur = self.duration_since(UNIX_EPOCH).ok()?;
31 let total_time = this_dur.checked_add(dur)?;
32
33 if total_time.as_secs() <= i32::max_value() as u64 {
34 Some(self + dur)
35 } else {
36 None
37 }
38 }
39
40 fn checked_sub(self, dur: Duration) -> Option<SystemTime> {
41 let this_dur = self.duration_since(UNIX_EPOCH).ok()?;
42 let total_time = this_dur.checked_sub(dur)?;
43
44 if total_time.as_secs() <= i32::max_value() as u64 {
45 Some(self - dur)
46 } else {
47 None
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 #[test]
55 fn it_works() {
56 use super::CheckedSystemTime;
57 use std::time::{Duration, SystemTime, UNIX_EPOCH};
58
59 assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_none());
60 assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_some());
61 assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_some());
62
63 assert!(CheckedSystemTime::checked_sub(UNIX_EPOCH, Duration::from_secs(120)).is_none());
64 assert!(CheckedSystemTime::checked_sub(SystemTime::now(), Duration::from_secs(1000)).is_some());
65 }
66}