1//! Extension traits.
2
3use core::time::Duration as StdDuration;
4
5use crate::convert::*;
6use crate::Duration;
7
8/// Sealed trait to prevent downstream implementations.
9mod sealed {
10 /// A trait that cannot be implemented by downstream users.
11 pub trait Sealed {}
12 impl Sealed for i64 {}
13 impl Sealed for u64 {}
14 impl Sealed for f64 {}
15}
16
17// region: NumericalDuration
18/// Create [`Duration`]s from numeric literals.
19///
20/// # Examples
21///
22/// Basic construction of [`Duration`]s.
23///
24/// ```rust
25/// # use time::{Duration, ext::NumericalDuration};
26/// assert_eq!(5.nanoseconds(), Duration::nanoseconds(5));
27/// assert_eq!(5.microseconds(), Duration::microseconds(5));
28/// assert_eq!(5.milliseconds(), Duration::milliseconds(5));
29/// assert_eq!(5.seconds(), Duration::seconds(5));
30/// assert_eq!(5.minutes(), Duration::minutes(5));
31/// assert_eq!(5.hours(), Duration::hours(5));
32/// assert_eq!(5.days(), Duration::days(5));
33/// assert_eq!(5.weeks(), Duration::weeks(5));
34/// ```
35///
36/// Signed integers work as well!
37///
38/// ```rust
39/// # use time::{Duration, ext::NumericalDuration};
40/// assert_eq!((-5).nanoseconds(), Duration::nanoseconds(-5));
41/// assert_eq!((-5).microseconds(), Duration::microseconds(-5));
42/// assert_eq!((-5).milliseconds(), Duration::milliseconds(-5));
43/// assert_eq!((-5).seconds(), Duration::seconds(-5));
44/// assert_eq!((-5).minutes(), Duration::minutes(-5));
45/// assert_eq!((-5).hours(), Duration::hours(-5));
46/// assert_eq!((-5).days(), Duration::days(-5));
47/// assert_eq!((-5).weeks(), Duration::weeks(-5));
48/// ```
49///
50/// Just like any other [`Duration`], they can be added, subtracted, etc.
51///
52/// ```rust
53/// # use time::ext::NumericalDuration;
54/// assert_eq!(2.seconds() + 500.milliseconds(), 2_500.milliseconds());
55/// assert_eq!(2.seconds() - 500.milliseconds(), 1_500.milliseconds());
56/// ```
57///
58/// When called on floating point values, any remainder of the floating point value will be
59/// truncated. Keep in mind that floating point numbers are inherently imprecise and have limited
60/// capacity.
61pub trait NumericalDuration: sealed::Sealed {
62 /// Create a [`Duration`] from the number of nanoseconds.
63 fn nanoseconds(self) -> Duration;
64 /// Create a [`Duration`] from the number of microseconds.
65 fn microseconds(self) -> Duration;
66 /// Create a [`Duration`] from the number of milliseconds.
67 fn milliseconds(self) -> Duration;
68 /// Create a [`Duration`] from the number of seconds.
69 fn seconds(self) -> Duration;
70 /// Create a [`Duration`] from the number of minutes.
71 fn minutes(self) -> Duration;
72 /// Create a [`Duration`] from the number of hours.
73 fn hours(self) -> Duration;
74 /// Create a [`Duration`] from the number of days.
75 fn days(self) -> Duration;
76 /// Create a [`Duration`] from the number of weeks.
77 fn weeks(self) -> Duration;
78}
79
80impl NumericalDuration for i64 {
81 fn nanoseconds(self) -> Duration {
82 Duration::nanoseconds(self)
83 }
84
85 fn microseconds(self) -> Duration {
86 Duration::microseconds(self)
87 }
88
89 fn milliseconds(self) -> Duration {
90 Duration::milliseconds(self)
91 }
92
93 fn seconds(self) -> Duration {
94 Duration::seconds(self)
95 }
96
97 fn minutes(self) -> Duration {
98 Duration::minutes(self)
99 }
100
101 fn hours(self) -> Duration {
102 Duration::hours(self)
103 }
104
105 fn days(self) -> Duration {
106 Duration::days(self)
107 }
108
109 fn weeks(self) -> Duration {
110 Duration::weeks(self)
111 }
112}
113
114impl NumericalDuration for f64 {
115 fn nanoseconds(self) -> Duration {
116 Duration::nanoseconds(self as _)
117 }
118
119 fn microseconds(self) -> Duration {
120 Duration::nanoseconds((self * Nanosecond.per(Microsecond) as Self) as _)
121 }
122
123 fn milliseconds(self) -> Duration {
124 Duration::nanoseconds((self * Nanosecond.per(Millisecond) as Self) as _)
125 }
126
127 fn seconds(self) -> Duration {
128 Duration::nanoseconds((self * Nanosecond.per(Second) as Self) as _)
129 }
130
131 fn minutes(self) -> Duration {
132 Duration::nanoseconds((self * Nanosecond.per(Minute) as Self) as _)
133 }
134
135 fn hours(self) -> Duration {
136 Duration::nanoseconds((self * Nanosecond.per(Hour) as Self) as _)
137 }
138
139 fn days(self) -> Duration {
140 Duration::nanoseconds((self * Nanosecond.per(Day) as Self) as _)
141 }
142
143 fn weeks(self) -> Duration {
144 Duration::nanoseconds((self * Nanosecond.per(Week) as Self) as _)
145 }
146}
147// endregion NumericalDuration
148
149// region: NumericalStdDuration
150/// Create [`std::time::Duration`]s from numeric literals.
151///
152/// # Examples
153///
154/// Basic construction of [`std::time::Duration`]s.
155///
156/// ```rust
157/// # use time::ext::NumericalStdDuration;
158/// # use core::time::Duration;
159/// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5));
160/// assert_eq!(5.std_microseconds(), Duration::from_micros(5));
161/// assert_eq!(5.std_milliseconds(), Duration::from_millis(5));
162/// assert_eq!(5.std_seconds(), Duration::from_secs(5));
163/// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60));
164/// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600));
165/// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400));
166/// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800));
167/// ```
168///
169/// Just like any other [`std::time::Duration`], they can be added, subtracted, etc.
170///
171/// ```rust
172/// # use time::ext::NumericalStdDuration;
173/// assert_eq!(
174/// 2.std_seconds() + 500.std_milliseconds(),
175/// 2_500.std_milliseconds()
176/// );
177/// assert_eq!(
178/// 2.std_seconds() - 500.std_milliseconds(),
179/// 1_500.std_milliseconds()
180/// );
181/// ```
182///
183/// When called on floating point values, any remainder of the floating point value will be
184/// truncated. Keep in mind that floating point numbers are inherently imprecise and have limited
185/// capacity.
186pub trait NumericalStdDuration: sealed::Sealed {
187 /// Create a [`std::time::Duration`] from the number of nanoseconds.
188 fn std_nanoseconds(self) -> StdDuration;
189 /// Create a [`std::time::Duration`] from the number of microseconds.
190 fn std_microseconds(self) -> StdDuration;
191 /// Create a [`std::time::Duration`] from the number of milliseconds.
192 fn std_milliseconds(self) -> StdDuration;
193 /// Create a [`std::time::Duration`] from the number of seconds.
194 fn std_seconds(self) -> StdDuration;
195 /// Create a [`std::time::Duration`] from the number of minutes.
196 fn std_minutes(self) -> StdDuration;
197 /// Create a [`std::time::Duration`] from the number of hours.
198 fn std_hours(self) -> StdDuration;
199 /// Create a [`std::time::Duration`] from the number of days.
200 fn std_days(self) -> StdDuration;
201 /// Create a [`std::time::Duration`] from the number of weeks.
202 fn std_weeks(self) -> StdDuration;
203}
204
205impl NumericalStdDuration for u64 {
206 fn std_nanoseconds(self) -> StdDuration {
207 StdDuration::from_nanos(self)
208 }
209
210 fn std_microseconds(self) -> StdDuration {
211 StdDuration::from_micros(self)
212 }
213
214 fn std_milliseconds(self) -> StdDuration {
215 StdDuration::from_millis(self)
216 }
217
218 fn std_seconds(self) -> StdDuration {
219 StdDuration::from_secs(self)
220 }
221
222 fn std_minutes(self) -> StdDuration {
223 StdDuration::from_secs(self * Second.per(Minute) as Self)
224 }
225
226 fn std_hours(self) -> StdDuration {
227 StdDuration::from_secs(self * Second.per(Hour) as Self)
228 }
229
230 fn std_days(self) -> StdDuration {
231 StdDuration::from_secs(self * Second.per(Day) as Self)
232 }
233
234 fn std_weeks(self) -> StdDuration {
235 StdDuration::from_secs(self * Second.per(Week) as Self)
236 }
237}
238
239impl NumericalStdDuration for f64 {
240 fn std_nanoseconds(self) -> StdDuration {
241 assert!(self >= 0.);
242 StdDuration::from_nanos(self as _)
243 }
244
245 fn std_microseconds(self) -> StdDuration {
246 assert!(self >= 0.);
247 StdDuration::from_nanos((self * Nanosecond.per(Microsecond) as Self) as _)
248 }
249
250 fn std_milliseconds(self) -> StdDuration {
251 assert!(self >= 0.);
252 StdDuration::from_nanos((self * Nanosecond.per(Millisecond) as Self) as _)
253 }
254
255 fn std_seconds(self) -> StdDuration {
256 assert!(self >= 0.);
257 StdDuration::from_nanos((self * Nanosecond.per(Second) as Self) as _)
258 }
259
260 fn std_minutes(self) -> StdDuration {
261 assert!(self >= 0.);
262 StdDuration::from_nanos((self * Nanosecond.per(Minute) as Self) as _)
263 }
264
265 fn std_hours(self) -> StdDuration {
266 assert!(self >= 0.);
267 StdDuration::from_nanos((self * Nanosecond.per(Hour) as Self) as _)
268 }
269
270 fn std_days(self) -> StdDuration {
271 assert!(self >= 0.);
272 StdDuration::from_nanos((self * Nanosecond.per(Day) as Self) as _)
273 }
274
275 fn std_weeks(self) -> StdDuration {
276 assert!(self >= 0.);
277 StdDuration::from_nanos((self * Nanosecond.per(Week) as Self) as _)
278 }
279}
280// endregion NumericalStdDuration
281