1use core::time::Duration;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct SystemTime {
6 since_unix_epoch: Duration,
7}
8
9pub const UNIX_EPOCH: SystemTime = SystemTime::from_unix_duration(Duration::ZERO);
11
12impl SystemTime {
13 #[inline]
15 pub const fn from_unix_duration(since_unix_epoch: Duration) -> Self {
16 Self { since_unix_epoch }
17 }
18
19 #[inline]
21 pub const fn as_unix_duration(self) -> Duration {
22 self.since_unix_epoch
23 }
24
25 #[inline]
34 pub fn now() -> Self {
35 #[cfg(all(
36 feature = "std",
37 not(all(target_family = "wasm", target_os = "unknown"))
38 ))]
39 {
40 let now = std::time::SystemTime::now();
41 let since_unix_epoch = now
42 .duration_since(std::time::UNIX_EPOCH)
43 .unwrap_or(Duration::ZERO);
44 Self::from_unix_duration(since_unix_epoch)
45 }
46
47 #[cfg(any(
48 not(feature = "std"),
49 all(feature = "std", target_family = "wasm", target_os = "unknown")
50 ))]
51 {
52 crate::global::get_time_provider().system_time()
53 }
54 }
55
56 pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, Duration> {
58 if self.since_unix_epoch >= earlier.since_unix_epoch {
59 Ok(self.since_unix_epoch - earlier.since_unix_epoch)
60 } else {
61 Err(earlier.since_unix_epoch - self.since_unix_epoch)
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn unix_epoch_is_zero() {
72 assert_eq!(UNIX_EPOCH.as_unix_duration(), Duration::ZERO);
73 }
74
75 #[test]
76 fn roundtrip_unix_duration() {
77 let duration = Duration::from_secs(123) + Duration::from_nanos(456);
78 let time = SystemTime::from_unix_duration(duration);
79 assert_eq!(time.as_unix_duration(), duration);
80 }
81
82 #[test]
83 fn duration_since_forward() {
84 let earlier = SystemTime::from_unix_duration(Duration::from_secs(10));
85 let later = SystemTime::from_unix_duration(Duration::from_secs(12));
86 assert_eq!(later.duration_since(earlier), Ok(Duration::from_secs(2)));
87 }
88
89 #[test]
90 fn duration_since_backward() {
91 let earlier = SystemTime::from_unix_duration(Duration::from_secs(10));
92 let later = SystemTime::from_unix_duration(Duration::from_secs(12));
93 assert_eq!(earlier.duration_since(later), Err(Duration::from_secs(2)));
94 }
95
96 #[test]
97 #[cfg(all(
98 feature = "std",
99 not(all(target_family = "wasm", target_os = "unknown"))
100 ))]
101 fn now_is_after_unix_epoch() {
102 let now = SystemTime::now();
103 assert!(now.duration_since(UNIX_EPOCH).is_ok());
104 }
105}