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}