rust_helpers/
time.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2#[cfg(feature = "async")]
3use std::{future::Future, pin::Pin};
4
5macro_rules! impl_for{
6    ($($t:ty),*) => {
7        $(
8        impl DurationExt for $t {
9            fn millis(&self) -> std::time::Duration {
10                std::time::Duration::from_millis(*self as u64)
11            }
12            fn seconds(&self) -> std::time::Duration {
13                std::time::Duration::from_secs(*self as u64)
14            }
15        }
16    )*
17    };
18}
19
20pub trait DurationExt {
21    fn millis(&self) -> std::time::Duration;
22    fn seconds(&self) -> std::time::Duration;
23    fn minutes(&self) -> std::time::Duration {
24        self.seconds() * 60
25    }
26    fn hours(&self) -> std::time::Duration {
27        self.minutes() * 60
28    }
29    fn days(&self) -> std::time::Duration {
30        self.hours() * 24
31    }
32}
33
34impl_for!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f64, f32, u128, i128);
35
36#[cfg(feature = "async")]
37type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
38#[cfg(feature = "time_async")]
39pub trait SleepAsyncExt {
40    fn sleep_async(&self) -> BoxFuture<'_, ()>;
41}
42#[cfg(feature = "time_async")]
43impl SleepAsyncExt for std::time::Duration {
44    fn sleep_async(&self) -> BoxFuture<'_, ()> {
45        Box::pin(tokio::time::sleep(*self))
46    }
47}
48pub trait DurationToUnix {
49    fn to_past_unix_secs(&self) -> u64;
50    fn to_future_unix_secs(&self) -> u64;
51}
52impl DurationToUnix for std::time::Duration {
53    fn to_past_unix_secs(&self) -> u64 {
54        (now() - *self).unix_secs()
55    }
56    fn to_future_unix_secs(&self) -> u64 {
57        (now() + *self).unix_secs()
58    }
59}
60pub trait TimeExt {
61    fn unix_secs(&self) -> u64;
62    fn unix_millis(&self) -> u64;
63    fn unix_nanos(&self) -> u64;
64    fn unix_micros(&self) -> u64;
65    fn unix_days(&self) -> u32 {
66        (self.unix_secs() / (60 * 60 * 24)) as u32
67    }
68}
69impl TimeExt for SystemTime {
70    fn unix_millis(&self) -> u64 {
71        self.duration_since(UNIX_EPOCH)
72            .unwrap_or_default()
73            .as_millis() as u64
74    }
75
76    fn unix_secs(&self) -> u64 {
77        self.duration_since(UNIX_EPOCH)
78            .unwrap_or_default()
79            .as_secs()
80    }
81
82    fn unix_nanos(&self) -> u64 {
83        self.duration_since(UNIX_EPOCH)
84            .unwrap_or_default()
85            .as_nanos() as u64
86    }
87
88    fn unix_micros(&self) -> u64 {
89        self.duration_since(UNIX_EPOCH)
90            .unwrap_or_default()
91            .as_micros() as u64
92    }
93}
94
95pub trait SleepExt {
96    fn sleep_sync(&self);
97}
98impl SleepExt for std::time::Duration {
99    fn sleep_sync(&self) {
100        SystemTime::now().unix_secs();
101        std::thread::sleep(*self)
102    }
103}
104pub trait HMS {
105    fn hms(&self) -> String;
106    fn hmsxxx(&self) -> String;
107}
108
109impl HMS for std::time::Duration {
110    fn hms(&self) -> String {
111        let secs = self.as_secs();
112        let hours = secs / 3600;
113        let minutes = (secs % 3600) / 60;
114        let seconds = secs % 60;
115        format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
116    }
117    fn hmsxxx(&self) -> String {
118        let secs = self.as_secs();
119        let hours = secs / 3600;
120        let minutes = (secs % 3600) / 60;
121        let seconds = secs % 60;
122        let millis = self.subsec_millis();
123        format!("{:02}:{:02}:{:02}.{:03}", hours, minutes, seconds, millis)
124    }
125}
126pub fn now() -> SystemTime {
127    SystemTime::now()
128}
129pub fn instant_now() -> std::time::Instant {
130    std::time::Instant::now()
131}
132pub trait InstantExt {
133    fn print_elapsed(&self);
134    fn reset(&mut self);
135    fn eprint_elapsed(&self);
136    fn print_elapsed_with_msg(&self, msg: &str);
137    fn eprint_elapsed_with_msg(&self, msg: &str);
138}
139impl InstantExt for std::time::Instant {
140    fn print_elapsed(&self) {
141        let elapsed = self.elapsed();
142        println!("{elapsed:?}");
143    }
144    fn eprint_elapsed(&self) {
145        let elapsed = self.elapsed();
146        eprintln!("{elapsed:?}");
147    }
148    fn reset(&mut self) {
149        *self = std::time::Instant::now();
150    }
151    fn print_elapsed_with_msg(&self, msg: &str) {
152        let elapsed = self.elapsed();
153        println!("{msg} {elapsed:?}");
154    }
155    fn eprint_elapsed_with_msg(&self, msg: &str) {
156        let elapsed = self.elapsed();
157        eprintln!("{msg} {elapsed:?}");
158    }
159}
160impl InstantExt for std::time::SystemTime {
161    fn print_elapsed(&self) {
162        let elapsed = self.elapsed().unwrap_or_default();
163        println!("{elapsed:?}");
164    }
165    fn eprint_elapsed(&self) {
166        let elapsed = self.elapsed().unwrap_or_default();
167        eprintln!("{elapsed:?}");
168    }
169    fn reset(&mut self) {
170        *self = std::time::SystemTime::now();
171    }
172    fn print_elapsed_with_msg(&self, msg: &str) {
173        let elapsed = self.elapsed().unwrap_or_default();
174        println!("{msg} {elapsed:?}");
175    }
176    fn eprint_elapsed_with_msg(&self, msg: &str) {
177        let elapsed = self.elapsed().unwrap_or_default();
178        eprintln!("{msg} {elapsed:?}");
179    }
180}
181#[cfg(test)]
182mod tests {
183    use super::*;
184    #[test]
185    fn test_hms() {
186        let d = 1.hours() + 1.minutes() + 1.seconds() + 10.millis();
187        assert_eq!(d.hms(), "01:01:01");
188        assert_eq!(d.hmsxxx(), "01:01:01.010");
189    }
190}