elfo_utils/time/
system.rs1use std::time::{Duration, SystemTime as StdSystemTime};
6
7#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
9pub struct SystemTime(u64 ); impl SystemTime {
12 pub const UNIX_EPOCH: Self = Self(0);
14
15 #[inline]
17 pub fn now() -> Self {
18 #[cfg(any(test, feature = "test-util"))]
19 if let Some(now_ns) = mock::NOW_NS.with(|t| t.get()) {
20 return Self(now_ns);
21 }
22
23 StdSystemTime::now().into()
24 }
25
26 #[inline]
28 pub fn from_unix_time_nanos(nanos: u64) -> Self {
29 Self(nanos)
30 }
31
32 #[inline]
34 pub fn to_unix_time_secs(&self) -> u64 {
35 self.to_unix_time_nanos() / 1_000_000_000
36 }
37
38 #[inline]
40 pub fn to_unix_time_nanos(&self) -> u64 {
41 self.0
42 }
43}
44
45impl From<StdSystemTime> for SystemTime {
46 fn from(sys_time: StdSystemTime) -> Self {
47 let unix_time_ns = sys_time
48 .duration_since(StdSystemTime::UNIX_EPOCH)
49 .unwrap_or_default()
50 .as_nanos() as u64;
51
52 Self(unix_time_ns)
53 }
54}
55
56impl From<SystemTime> for StdSystemTime {
57 fn from(sys_time: SystemTime) -> Self {
58 StdSystemTime::UNIX_EPOCH + Duration::from_nanos(sys_time.0)
59 }
60}
61
62#[cfg(any(test, feature = "test-util"))]
63pub use mock::{with_system_time_mock, SystemTimeMock};
64
65#[cfg(any(test, feature = "test-util"))]
66mod mock {
67 use std::cell::Cell;
68
69 use super::*;
70
71 thread_local! {
72 pub(super) static NOW_NS: Cell<Option<u64>> = const { Cell::new(None) };
73 }
74
75 pub fn with_system_time_mock(f: impl FnOnce(SystemTimeMock)) {
77 NOW_NS.with(|t| t.set(Some(0)));
78 f(SystemTimeMock);
79 NOW_NS.with(|t| t.set(None));
80 }
81
82 #[non_exhaustive]
84 pub struct SystemTimeMock;
85
86 impl SystemTimeMock {
87 pub fn advance(&self, duration: Duration) {
89 NOW_NS.with(|t| {
90 let mut now_ns = t.get().expect("use of moved system time mock");
91 now_ns += duration.as_nanos() as u64;
92 t.set(Some(now_ns));
93 })
94 }
95 }
96}