time/ext/
numerical_std_duration.rs

1use core::time::Duration as StdDuration;
2
3use num_conv::prelude::*;
4
5use crate::convert::*;
6
7/// Sealed trait to prevent downstream implementations.
8mod sealed {
9    /// A trait that cannot be implemented by downstream users.
10    pub trait Sealed {}
11    impl Sealed for u64 {}
12    impl Sealed for f64 {}
13}
14
15/// Create [`std::time::Duration`]s from numeric literals.
16///
17/// # Examples
18///
19/// Basic construction of [`std::time::Duration`]s.
20///
21/// ```rust
22/// # use time::ext::NumericalStdDuration;
23/// # use core::time::Duration;
24/// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5));
25/// assert_eq!(5.std_microseconds(), Duration::from_micros(5));
26/// assert_eq!(5.std_milliseconds(), Duration::from_millis(5));
27/// assert_eq!(5.std_seconds(), Duration::from_secs(5));
28/// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60));
29/// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600));
30/// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400));
31/// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800));
32/// ```
33///
34/// Just like any other [`std::time::Duration`], they can be added, subtracted, etc.
35///
36/// ```rust
37/// # use time::ext::NumericalStdDuration;
38/// assert_eq!(
39///     2.std_seconds() + 500.std_milliseconds(),
40///     2_500.std_milliseconds()
41/// );
42/// assert_eq!(
43///     2.std_seconds() - 500.std_milliseconds(),
44///     1_500.std_milliseconds()
45/// );
46/// ```
47///
48/// When called on floating point values, any remainder of the floating point value will be
49/// truncated. Keep in mind that floating point numbers are inherently imprecise and have
50/// limited capacity.
51pub trait NumericalStdDuration: sealed::Sealed {
52    /// Create a [`std::time::Duration`] from the number of nanoseconds.
53    fn std_nanoseconds(self) -> StdDuration;
54    /// Create a [`std::time::Duration`] from the number of microseconds.
55    fn std_microseconds(self) -> StdDuration;
56    /// Create a [`std::time::Duration`] from the number of milliseconds.
57    fn std_milliseconds(self) -> StdDuration;
58    /// Create a [`std::time::Duration`] from the number of seconds.
59    fn std_seconds(self) -> StdDuration;
60    /// Create a [`std::time::Duration`] from the number of minutes.
61    fn std_minutes(self) -> StdDuration;
62    /// Create a [`std::time::Duration`] from the number of hours.
63    fn std_hours(self) -> StdDuration;
64    /// Create a [`std::time::Duration`] from the number of days.
65    fn std_days(self) -> StdDuration;
66    /// Create a [`std::time::Duration`] from the number of weeks.
67    fn std_weeks(self) -> StdDuration;
68}
69
70impl NumericalStdDuration for u64 {
71    fn std_nanoseconds(self) -> StdDuration {
72        StdDuration::from_nanos(self)
73    }
74
75    fn std_microseconds(self) -> StdDuration {
76        StdDuration::from_micros(self)
77    }
78
79    fn std_milliseconds(self) -> StdDuration {
80        StdDuration::from_millis(self)
81    }
82
83    fn std_seconds(self) -> StdDuration {
84        StdDuration::from_secs(self)
85    }
86
87    /// # Panics
88    ///
89    /// This may panic if an overflow occurs.
90    fn std_minutes(self) -> StdDuration {
91        StdDuration::from_secs(
92            self.checked_mul(Second::per(Minute).extend())
93                .expect("overflow constructing `time::Duration`"),
94        )
95    }
96
97    /// # Panics
98    ///
99    /// This may panic if an overflow occurs.
100    fn std_hours(self) -> StdDuration {
101        StdDuration::from_secs(
102            self.checked_mul(Second::per(Hour).extend())
103                .expect("overflow constructing `time::Duration`"),
104        )
105    }
106
107    /// # Panics
108    ///
109    /// This may panic if an overflow occurs.
110    fn std_days(self) -> StdDuration {
111        StdDuration::from_secs(
112            self.checked_mul(Second::per(Day).extend())
113                .expect("overflow constructing `time::Duration`"),
114        )
115    }
116
117    /// # Panics
118    ///
119    /// This may panic if an overflow occurs.
120    fn std_weeks(self) -> StdDuration {
121        StdDuration::from_secs(
122            self.checked_mul(Second::per(Week).extend())
123                .expect("overflow constructing `time::Duration`"),
124        )
125    }
126}
127
128impl NumericalStdDuration for f64 {
129    /// # Panics
130    ///
131    /// This will panic if self is negative.
132    fn std_nanoseconds(self) -> StdDuration {
133        assert!(self >= 0.);
134        StdDuration::from_nanos(self as _)
135    }
136
137    /// # Panics
138    ///
139    /// This will panic if self is negative.
140    fn std_microseconds(self) -> StdDuration {
141        assert!(self >= 0.);
142        StdDuration::from_nanos((self * Nanosecond::per(Microsecond) as Self) as _)
143    }
144
145    /// # Panics
146    ///
147    /// This will panic if self is negative.
148    fn std_milliseconds(self) -> StdDuration {
149        assert!(self >= 0.);
150        StdDuration::from_nanos((self * Nanosecond::per(Millisecond) as Self) as _)
151    }
152
153    /// # Panics
154    ///
155    /// This will panic if self is negative.
156    fn std_seconds(self) -> StdDuration {
157        assert!(self >= 0.);
158        StdDuration::from_nanos((self * Nanosecond::per(Second) as Self) as _)
159    }
160
161    /// # Panics
162    ///
163    /// This will panic if self is negative.
164    fn std_minutes(self) -> StdDuration {
165        assert!(self >= 0.);
166        StdDuration::from_nanos((self * Nanosecond::per(Minute) as Self) as _)
167    }
168
169    /// # Panics
170    ///
171    /// This will panic if self is negative.
172    fn std_hours(self) -> StdDuration {
173        assert!(self >= 0.);
174        StdDuration::from_nanos((self * Nanosecond::per(Hour) as Self) as _)
175    }
176
177    /// # Panics
178    ///
179    /// This will panic if self is negative.
180    fn std_days(self) -> StdDuration {
181        assert!(self >= 0.);
182        StdDuration::from_nanos((self * Nanosecond::per(Day) as Self) as _)
183    }
184
185    /// # Panics
186    ///
187    /// This will panic if self is negative.
188    fn std_weeks(self) -> StdDuration {
189        assert!(self >= 0.);
190        StdDuration::from_nanos((self * Nanosecond::per(Week) as Self) as _)
191    }
192}