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}