time/ext/
numerical_std_duration.rs

1use core::time::Duration as StdDuration;
2
3use crate::convert::*;
4
5/// Sealed trait to prevent downstream implementations.
6mod sealed {
7    /// A trait that cannot be implemented by downstream users.
8    pub trait Sealed {}
9    impl Sealed for u64 {}
10    impl Sealed for f64 {}
11}
12
13/// Create [`std::time::Duration`]s from numeric literals.
14///
15/// # Examples
16///
17/// Basic construction of [`std::time::Duration`]s.
18///
19/// ```rust
20/// # use time::ext::NumericalStdDuration;
21/// # use core::time::Duration;
22/// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5));
23/// assert_eq!(5.std_microseconds(), Duration::from_micros(5));
24/// assert_eq!(5.std_milliseconds(), Duration::from_millis(5));
25/// assert_eq!(5.std_seconds(), Duration::from_secs(5));
26/// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60));
27/// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600));
28/// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400));
29/// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800));
30/// ```
31///
32/// Just like any other [`std::time::Duration`], they can be added, subtracted, etc.
33///
34/// ```rust
35/// # use time::ext::NumericalStdDuration;
36/// assert_eq!(
37///     2.std_seconds() + 500.std_milliseconds(),
38///     2_500.std_milliseconds()
39/// );
40/// assert_eq!(
41///     2.std_seconds() - 500.std_milliseconds(),
42///     1_500.std_milliseconds()
43/// );
44/// ```
45///
46/// When called on floating point values, any remainder of the floating point value will be
47/// truncated. Keep in mind that floating point numbers are inherently imprecise and have
48/// limited capacity.
49#[diagnostic::on_unimplemented(note = "this extension trait is intended to be used with numeric \
50                                       literals, such as `5.std_seconds()`")]
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    #[inline]
72    fn std_nanoseconds(self) -> StdDuration {
73        StdDuration::from_nanos(self)
74    }
75
76    #[inline]
77    fn std_microseconds(self) -> StdDuration {
78        StdDuration::from_micros(self)
79    }
80
81    #[inline]
82    fn std_milliseconds(self) -> StdDuration {
83        StdDuration::from_millis(self)
84    }
85
86    #[inline]
87    fn std_seconds(self) -> StdDuration {
88        StdDuration::from_secs(self)
89    }
90
91    /// # Panics
92    ///
93    /// This may panic if an overflow occurs.
94    #[inline]
95    #[track_caller]
96    fn std_minutes(self) -> StdDuration {
97        StdDuration::from_secs(
98            self.checked_mul(Second::per_t(Minute))
99                .expect("overflow constructing `time::Duration`"),
100        )
101    }
102
103    /// # Panics
104    ///
105    /// This may panic if an overflow occurs.
106    #[inline]
107    #[track_caller]
108    fn std_hours(self) -> StdDuration {
109        StdDuration::from_secs(
110            self.checked_mul(Second::per_t(Hour))
111                .expect("overflow constructing `time::Duration`"),
112        )
113    }
114
115    /// # Panics
116    ///
117    /// This may panic if an overflow occurs.
118    #[inline]
119    #[track_caller]
120    fn std_days(self) -> StdDuration {
121        StdDuration::from_secs(
122            self.checked_mul(Second::per_t(Day))
123                .expect("overflow constructing `time::Duration`"),
124        )
125    }
126
127    /// # Panics
128    ///
129    /// This may panic if an overflow occurs.
130    #[inline]
131    #[track_caller]
132    fn std_weeks(self) -> StdDuration {
133        StdDuration::from_secs(
134            self.checked_mul(Second::per_t(Week))
135                .expect("overflow constructing `time::Duration`"),
136        )
137    }
138}
139
140impl NumericalStdDuration for f64 {
141    /// # Panics
142    ///
143    /// This will panic if self is negative.
144    #[inline]
145    #[track_caller]
146    fn std_nanoseconds(self) -> StdDuration {
147        assert!(self >= 0.);
148        StdDuration::from_nanos(self as u64)
149    }
150
151    /// # Panics
152    ///
153    /// This will panic if self is negative.
154    #[inline]
155    #[track_caller]
156    fn std_microseconds(self) -> StdDuration {
157        assert!(self >= 0.);
158        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Microsecond)) as u64)
159    }
160
161    /// # Panics
162    ///
163    /// This will panic if self is negative.
164    #[inline]
165    #[track_caller]
166    fn std_milliseconds(self) -> StdDuration {
167        assert!(self >= 0.);
168        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Millisecond)) as u64)
169    }
170
171    /// # Panics
172    ///
173    /// This will panic if self is negative.
174    #[inline]
175    #[track_caller]
176    fn std_seconds(self) -> StdDuration {
177        assert!(self >= 0.);
178        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Second)) as u64)
179    }
180
181    /// # Panics
182    ///
183    /// This will panic if self is negative.
184    #[inline]
185    #[track_caller]
186    fn std_minutes(self) -> StdDuration {
187        assert!(self >= 0.);
188        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Minute)) as u64)
189    }
190
191    /// # Panics
192    ///
193    /// This will panic if self is negative.
194    #[inline]
195    #[track_caller]
196    fn std_hours(self) -> StdDuration {
197        assert!(self >= 0.);
198        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Hour)) as u64)
199    }
200
201    /// # Panics
202    ///
203    /// This will panic if self is negative.
204    #[inline]
205    #[track_caller]
206    fn std_days(self) -> StdDuration {
207        assert!(self >= 0.);
208        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Day)) as u64)
209    }
210
211    /// # Panics
212    ///
213    /// This will panic if self is negative.
214    #[inline]
215    #[track_caller]
216    fn std_weeks(self) -> StdDuration {
217        assert!(self >= 0.);
218        StdDuration::from_nanos((self * Nanosecond::per_t::<Self>(Week)) as u64)
219    }
220}