time/interop/
systemdatetime_timestamp.rs1use core::cmp::Ordering;
2use core::ops::Sub;
3use std::time::SystemTime;
4
5#[allow(unused_imports)] use num_conv::prelude::*;
7
8use crate::ext::SystemTimeExt;
9use crate::unit::*;
10use crate::{Duration, Timestamp};
11
12impl Sub<SystemTime> for Timestamp {
13 type Output = Duration;
14
15 #[inline]
16 fn sub(self, rhs: SystemTime) -> Self::Output {
17 let lhs_duration = self - Self::UNIX_EPOCH;
18 match rhs.duration_since(SystemTime::UNIX_EPOCH) {
19 Ok(duration) => lhs_duration - duration,
20 Err(err) => lhs_duration + err.duration(),
21 }
22 }
23}
24
25impl Sub<Timestamp> for SystemTime {
26 type Output = Duration;
27
28 #[inline]
29 fn sub(self, rhs: Timestamp) -> Self::Output {
30 let rhs_duration = rhs - Timestamp::UNIX_EPOCH;
31
32 match self.duration_since(Self::UNIX_EPOCH) {
33 Ok(lhs) => lhs - rhs_duration,
34 Err(err) => -(err.duration() + rhs_duration),
35 }
36 }
37}
38
39impl PartialEq<SystemTime> for Timestamp {
40 #[inline]
41 fn eq(&self, other: &SystemTime) -> bool {
42 *self - Self::UNIX_EPOCH == other.signed_duration_since(SystemTime::UNIX_EPOCH)
43 }
44}
45
46impl PartialEq<Timestamp> for SystemTime {
47 #[inline]
48 fn eq(&self, other: &Timestamp) -> bool {
49 other == self
50 }
51}
52
53impl PartialOrd<SystemTime> for Timestamp {
54 #[inline]
55 fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
56 (*self - Self::UNIX_EPOCH).partial_cmp(&other.signed_duration_since(SystemTime::UNIX_EPOCH))
57 }
58}
59
60impl PartialOrd<Timestamp> for SystemTime {
61 #[inline]
62 fn partial_cmp(&self, other: &Timestamp) -> Option<Ordering> {
63 other.partial_cmp(self).map(Ordering::reverse)
64 }
65}
66
67impl From<SystemTime> for Timestamp {
68 #[inline]
72 #[track_caller]
73 fn from(datetime: SystemTime) -> Self {
74 let duration = datetime.signed_duration_since(SystemTime::UNIX_EPOCH);
75 let mut seconds = duration.whole_seconds();
76 let mut nanoseconds = duration.subsec_nanoseconds();
77
78 if nanoseconds < 0 {
79 seconds -= 1;
80 nanoseconds += Nanosecond::per_t::<i32>(Second);
81 }
82
83 Self::new(seconds, nanoseconds.cast_unsigned())
84 .expect("SystemTime value is out of valid range")
85 }
86}
87
88impl From<Timestamp> for SystemTime {
89 #[inline]
93 #[track_caller]
94 fn from(timestamp: Timestamp) -> Self {
95 Self::UNIX_EPOCH + (timestamp - Timestamp::UNIX_EPOCH)
96 }
97}
98
99#[cfg(test)]
100mod test {
101 use super::*;
102 use crate::ext::NumericalDuration;
103
104 #[test]
105 fn systime_to_timestamp() -> crate::Result<()> {
106 let ts = Timestamp::from(SystemTime::UNIX_EPOCH + 5.seconds());
107 assert_eq!(ts, Timestamp::from_seconds(5)?);
108
109 let ts = Timestamp::from(SystemTime::UNIX_EPOCH - 5.seconds());
110 assert_eq!(ts, Timestamp::from_seconds(-5)?);
111
112 let ts = Timestamp::from(SystemTime::UNIX_EPOCH + 5.seconds() + 1.milliseconds());
113 assert_eq!(ts, Timestamp::from_milliseconds(5_001)?);
114
115 let ts = Timestamp::from(SystemTime::UNIX_EPOCH - 5.seconds() - 1.milliseconds());
116 assert_eq!(ts, Timestamp::from_milliseconds(-5_001)?);
117
118 Ok(())
119 }
120}