1use std::time::Duration;
2
3pub trait DurationExt {
34 fn seconds(self) -> Duration;
36 fn minutes(self) -> Duration;
38 fn hours(self) -> Duration;
40 fn milliseconds(self) -> Duration;
42 fn microseconds(self) -> Duration;
44 fn nanoseconds(self) -> Duration;
46}
47
48impl DurationExt for u64 {
50 fn seconds(self) -> Duration {
51 Duration::from_secs(self)
52 }
53
54 fn minutes(self) -> Duration {
55 let secs = self.checked_mul(60)
56 .expect(&format!("duration value {} minutes overflows u64 seconds capacity", self));
57 Duration::from_secs(secs)
58 }
59
60 fn hours(self) -> Duration {
61 let secs = self.checked_mul(3600)
62 .expect(&format!("duration value {} hours overflows u64 seconds capacity", self));
63 Duration::from_secs(secs)
64 }
65
66 fn milliseconds(self) -> Duration {
67 Duration::from_millis(self)
68 }
69
70 fn microseconds(self) -> Duration {
71 Duration::from_micros(self)
72 }
73
74 fn nanoseconds(self) -> Duration {
75 Duration::from_nanos(self)
76 }
77}
78
79impl DurationExt for u32 {
80 fn seconds(self) -> Duration {
81 Duration::from_secs(self as u64)
82 }
83
84 fn minutes(self) -> Duration {
86 (self as u64).minutes()
87 }
88
89 fn hours(self) -> Duration {
91 (self as u64).hours()
92 }
93
94 fn milliseconds(self) -> Duration {
95 Duration::from_millis(self as u64)
96 }
97
98 fn microseconds(self) -> Duration {
99 Duration::from_micros(self as u64)
100 }
101
102 fn nanoseconds(self) -> Duration {
103 Duration::from_nanos(self as u64)
104 }
105}
106
107impl DurationExt for i64 {
109 fn seconds(self) -> Duration {
110 assert!(self >= 0, "duration cannot be negative: got {} seconds", self);
111 Duration::from_secs(self as u64)
112 }
113
114 fn minutes(self) -> Duration {
115 assert!(self >= 0, "duration cannot be negative: got {} minutes", self);
116 (self as u64).minutes()
118 }
119
120 fn hours(self) -> Duration {
121 assert!(self >= 0, "duration cannot be negative: got {} hours", self);
122 (self as u64).hours()
124 }
125
126 fn milliseconds(self) -> Duration {
127 assert!(self >= 0, "duration cannot be negative: got {} milliseconds", self);
128 Duration::from_millis(self as u64)
129 }
130
131 fn microseconds(self) -> Duration {
132 assert!(self >= 0, "duration cannot be negative: got {} microseconds", self);
133 Duration::from_micros(self as u64)
134 }
135
136 fn nanoseconds(self) -> Duration {
137 assert!(self >= 0, "duration cannot be negative: got {} nanoseconds", self);
138 Duration::from_nanos(self as u64)
139 }
140}
141
142impl DurationExt for i32 {
143 fn seconds(self) -> Duration {
144 assert!(self >= 0, "duration cannot be negative: got {} seconds", self);
145 Duration::from_secs(self as u64)
146 }
147
148 fn minutes(self) -> Duration {
149 assert!(self >= 0, "duration cannot be negative: got {} minutes", self);
150 (self as u64).minutes()
152 }
153
154 fn hours(self) -> Duration {
155 assert!(self >= 0, "duration cannot be negative: got {} hours", self);
156 (self as u64).hours()
158 }
159
160 fn milliseconds(self) -> Duration {
161 assert!(self >= 0, "duration cannot be negative: got {} milliseconds", self);
162 Duration::from_millis(self as u64)
163 }
164
165 fn microseconds(self) -> Duration {
166 assert!(self >= 0, "duration cannot be negative: got {} microseconds", self);
167 Duration::from_micros(self as u64)
168 }
169
170 fn nanoseconds(self) -> Duration {
171 assert!(self >= 0, "duration cannot be negative: got {} nanoseconds", self);
172 Duration::from_nanos(self as u64)
173 }
174}
175
176impl DurationExt for f64 {
177 fn seconds(self) -> Duration {
178 Duration::from_secs_f64(self)
179 }
180
181 fn minutes(self) -> Duration {
182 Duration::from_secs_f64(self * 60.0)
183 }
184
185 fn hours(self) -> Duration {
186 Duration::from_secs_f64(self * 3600.0)
187 }
188
189 fn milliseconds(self) -> Duration {
190 Duration::from_secs_f64(self / 1000.0)
191 }
192
193 fn microseconds(self) -> Duration {
194 Duration::from_secs_f64(self / 1_000_000.0)
195 }
196
197 fn nanoseconds(self) -> Duration {
198 Duration::from_secs_f64(self / 1_000_000_000.0)
199 }
200}
201
202
203impl DurationExt for f32 {
204 fn seconds(self) -> Duration {
205 Duration::from_secs_f32(self)
206 }
207
208 fn minutes(self) -> Duration {
209 Duration::from_secs_f32(self * 60.0)
210 }
211
212 fn hours(self) -> Duration {
213 Duration::from_secs_f32(self * 3600.0)
214 }
215
216 fn milliseconds(self) -> Duration {
217 Duration::from_secs_f32(self / 1000.0)
218 }
219
220 fn microseconds(self) -> Duration {
221 Duration::from_secs_f32(self / 1_000_000.0)
222 }
223
224 fn nanoseconds(self) -> Duration {
225 Duration::from_secs_f32(self / 1_000_000_000.0)
226 }
227}
228
229#[cfg(test)]
231mod tests {
232 use super::*;
233 use std::time::Duration;
234
235 const MAX_FOR_MINUTES: u64 = u64::MAX / 60;
237 const MAX_FOR_HOURS: u64 = u64::MAX / 3600;
238
239 const OVERFLOW_MINUTES: u64 = MAX_FOR_MINUTES + 1;
240 const OVERFLOW_HOURS: u64 = MAX_FOR_HOURS + 1;
241
242 #[test]
244 fn test_u64_large_units() {
245 let five: u64 = 5;
246 assert_eq!(five.minutes(), Duration::from_secs(5 * 60));
247 assert_eq!(five.hours(), Duration::from_secs(5 * 3600));
248 }
249
250 #[test]
251 #[should_panic(expected = "overflows u64 seconds capacity")]
252 fn test_u64_minutes_panics_on_overflow() {
253 let _ = OVERFLOW_MINUTES.minutes();
254 }
255
256 #[test]
257 #[should_panic(expected = "overflows u64 seconds capacity")]
258 fn test_u64_hours_panics_on_overflow() {
259 let _ = OVERFLOW_HOURS.hours();
260 }
261
262 #[test]
263 fn test_max_u64_small_units() {
264 let max_u64 = u64::MAX;
265 assert_eq!(max_u64.milliseconds(), Duration::from_millis(u64::MAX));
266 assert_eq!(max_u64.microseconds(), Duration::from_micros(u64::MAX));
267 assert_eq!(max_u64.nanoseconds(), Duration::from_nanos(u64::MAX));
268 }
269
270 #[test]
272 fn test_i64_positive() {
273 let pos: i64 = 10;
274 assert_eq!(pos.seconds(), Duration::from_secs(10));
275 assert_eq!(pos.minutes(), Duration::from_secs(600));
276 assert_eq!(pos.hours(), Duration::from_secs(36000));
277 }
278
279 #[test]
280 #[should_panic(expected = "duration cannot be negative")]
281 fn test_i64_negative_panics() {
282 let neg: i64 = -10;
283 let _ = neg.minutes();
284 }
285
286 #[test]
287 #[should_panic(expected = "overflows u64 seconds capacity")]
288 fn test_i64_minutes_panics_on_overflow() {
289 let _ = (OVERFLOW_MINUTES as i64).minutes();
290 }
291
292 #[test]
293 #[should_panic(expected = "overflows u64 seconds capacity")]
294 fn test_i64_hours_panics_on_overflow() {
295 let _ = (OVERFLOW_HOURS as i64).hours();
296 }
297
298 #[test]
301 fn test_i32_positive_full() {
302 let val: i32 = 5;
303 assert_eq!(val.seconds(), Duration::from_secs(5));
304 assert_eq!(val.minutes(), Duration::from_secs(300));
305 assert_eq!(val.hours(), Duration::from_secs(18000));
306 }
307
308 #[test]
309 #[should_panic(expected = "duration cannot be negative")]
310 fn test_i32_negative_panics() { let _ = (-5).seconds(); }
311
312 #[test]
314 fn test_u32_positive_full() {
315 let val: u32 = 5;
316 assert_eq!(val.seconds(), Duration::from_secs(5));
317 assert_eq!(val.minutes(), Duration::from_secs(300));
318 assert_eq!(val.hours(), Duration::from_secs(18000));
319 }
320
321 #[test]
322 fn test_f64_fractional() {
323 let half = 0.5.seconds();
324 assert_eq!(half, Duration::from_millis(500));
325
326 let two_half = 2.5.minutes();
327 assert_eq!(two_half, Duration::from_secs(150));
328
329 let one_half_hour = 1.5.hours();
330 assert_eq!(one_half_hour, Duration::from_secs(5400));
331 }
332
333 #[test]
334 #[should_panic]
335 fn test_f64_nan_panics() {
336 let _ = f64::NAN.seconds();
337 }
338
339 #[test]
340 #[should_panic]
341 fn test_f64_infinity_panics() {
342 let _ = f64::INFINITY.seconds();
343 }
344
345 #[test]
346 #[should_panic]
347 fn test_f64_negative_panics() {
348 let _ = (-1.5).seconds();
349 }
350
351 #[test]
352 fn test_f64_zero() {
353 let zero = 0.0.seconds();
354 assert_eq!(zero, Duration::ZERO);
355 }
356
357 #[test]
359 fn test_f32_fractional() {
360 let half: f32 = 0.5;
361 assert_eq!(half.seconds(), Duration::from_millis(500));
362 }
363
364 #[test]
365 #[should_panic]
366 fn test_f32_nan_panics() {
367 let _ = f32::NAN.seconds();
368 }
369}