]>
Commit | Line | Data |
---|---|---|
3b2f2976 | 1 | // Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
0531ce1d | 10 | #![stable(feature = "duration_core", since = "1.25.0")] |
2c00a5a8 XL |
11 | |
12 | //! Temporal quantification. | |
13 | //! | |
14 | //! Example: | |
15 | //! | |
16 | //! ``` | |
17 | //! use std::time::Duration; | |
18 | //! | |
19 | //! let five_seconds = Duration::new(5, 0); | |
20 | //! // both declarations are equivalent | |
21 | //! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); | |
22 | //! ``` | |
1a4d82fc | 23 | |
94b46f34 | 24 | use fmt; |
32a655c1 | 25 | use iter::Sum; |
54a0048b | 26 | use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; |
d9579d0f AL |
27 | |
28 | const NANOS_PER_SEC: u32 = 1_000_000_000; | |
29 | const NANOS_PER_MILLI: u32 = 1_000_000; | |
ea8adc8c | 30 | const NANOS_PER_MICRO: u32 = 1_000; |
d9579d0f | 31 | const MILLIS_PER_SEC: u64 = 1_000; |
ea8adc8c | 32 | const MICROS_PER_SEC: u64 = 1_000_000; |
d9579d0f | 33 | |
32a655c1 | 34 | /// A `Duration` type to represent a span of time, typically used for system |
d9579d0f AL |
35 | /// timeouts. |
36 | /// | |
3b2f2976 XL |
37 | /// Each `Duration` is composed of a whole number of seconds and a fractional part |
38 | /// represented in nanoseconds. If the underlying system does not support | |
39 | /// nanosecond-level precision, APIs binding a system timeout will typically round up | |
40 | /// the number of nanoseconds. | |
d9579d0f | 41 | /// |
32a655c1 SL |
42 | /// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other |
43 | /// [`ops`] traits. | |
44 | /// | |
45 | /// [`Add`]: ../../std/ops/trait.Add.html | |
46 | /// [`Sub`]: ../../std/ops/trait.Sub.html | |
47 | /// [`ops`]: ../../std/ops/index.html | |
d9579d0f AL |
48 | /// |
49 | /// # Examples | |
50 | /// | |
51 | /// ``` | |
d9579d0f AL |
52 | /// use std::time::Duration; |
53 | /// | |
54 | /// let five_seconds = Duration::new(5, 0); | |
55 | /// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); | |
56 | /// | |
c1a9b12d SL |
57 | /// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5); |
58 | /// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5); | |
d9579d0f AL |
59 | /// |
60 | /// let ten_millis = Duration::from_millis(10); | |
61 | /// ``` | |
0531ce1d | 62 | #[stable(feature = "duration", since = "1.3.0")] |
94b46f34 | 63 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] |
1a4d82fc | 64 | pub struct Duration { |
d9579d0f AL |
65 | secs: u64, |
66 | nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC | |
1a4d82fc JJ |
67 | } |
68 | ||
1a4d82fc | 69 | impl Duration { |
3b2f2976 XL |
70 | /// Creates a new `Duration` from the specified number of whole seconds and |
71 | /// additional nanoseconds. | |
d9579d0f | 72 | /// |
3b2f2976 XL |
73 | /// If the number of nanoseconds is greater than 1 billion (the number of |
74 | /// nanoseconds in a second), then it will carry over into the seconds provided. | |
a7813a04 XL |
75 | /// |
76 | /// # Panics | |
77 | /// | |
78 | /// This constructor will panic if the carry from the nanoseconds overflows | |
79 | /// the seconds counter. | |
32a655c1 SL |
80 | /// |
81 | /// # Examples | |
82 | /// | |
83 | /// ``` | |
84 | /// use std::time::Duration; | |
85 | /// | |
86 | /// let five_seconds = Duration::new(5, 0); | |
87 | /// ``` | |
c1a9b12d | 88 | #[stable(feature = "duration", since = "1.3.0")] |
54a0048b | 89 | #[inline] |
d9579d0f | 90 | pub fn new(secs: u64, nanos: u32) -> Duration { |
a7813a04 XL |
91 | let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) |
92 | .expect("overflow in Duration::new"); | |
d9579d0f | 93 | let nanos = nanos % NANOS_PER_SEC; |
1a4d82fc JJ |
94 | Duration { secs: secs, nanos: nanos } |
95 | } | |
96 | ||
3b2f2976 | 97 | /// Creates a new `Duration` from the specified number of whole seconds. |
32a655c1 SL |
98 | /// |
99 | /// # Examples | |
100 | /// | |
101 | /// ``` | |
102 | /// use std::time::Duration; | |
103 | /// | |
7cac9316 XL |
104 | /// let duration = Duration::from_secs(5); |
105 | /// | |
106 | /// assert_eq!(5, duration.as_secs()); | |
107 | /// assert_eq!(0, duration.subsec_nanos()); | |
32a655c1 | 108 | /// ``` |
c1a9b12d | 109 | #[stable(feature = "duration", since = "1.3.0")] |
54a0048b | 110 | #[inline] |
2c00a5a8 | 111 | pub const fn from_secs(secs: u64) -> Duration { |
d9579d0f | 112 | Duration { secs: secs, nanos: 0 } |
1a4d82fc JJ |
113 | } |
114 | ||
d9579d0f | 115 | /// Creates a new `Duration` from the specified number of milliseconds. |
32a655c1 SL |
116 | /// |
117 | /// # Examples | |
118 | /// | |
119 | /// ``` | |
120 | /// use std::time::Duration; | |
121 | /// | |
7cac9316 XL |
122 | /// let duration = Duration::from_millis(2569); |
123 | /// | |
124 | /// assert_eq!(2, duration.as_secs()); | |
ff7c6d11 | 125 | /// assert_eq!(569_000_000, duration.subsec_nanos()); |
32a655c1 | 126 | /// ``` |
c1a9b12d | 127 | #[stable(feature = "duration", since = "1.3.0")] |
54a0048b | 128 | #[inline] |
2c00a5a8 XL |
129 | pub const fn from_millis(millis: u64) -> Duration { |
130 | Duration { | |
131 | secs: millis / MILLIS_PER_SEC, | |
132 | nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI, | |
133 | } | |
1a4d82fc | 134 | } |
1a4d82fc | 135 | |
ea8adc8c XL |
136 | /// Creates a new `Duration` from the specified number of microseconds. |
137 | /// | |
138 | /// # Examples | |
139 | /// | |
140 | /// ``` | |
ea8adc8c XL |
141 | /// use std::time::Duration; |
142 | /// | |
143 | /// let duration = Duration::from_micros(1_000_002); | |
144 | /// | |
145 | /// assert_eq!(1, duration.as_secs()); | |
146 | /// assert_eq!(2000, duration.subsec_nanos()); | |
147 | /// ``` | |
83c7162d | 148 | #[stable(feature = "duration_from_micros", since = "1.27.0")] |
ea8adc8c | 149 | #[inline] |
2c00a5a8 XL |
150 | pub const fn from_micros(micros: u64) -> Duration { |
151 | Duration { | |
152 | secs: micros / MICROS_PER_SEC, | |
153 | nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO, | |
154 | } | |
ea8adc8c XL |
155 | } |
156 | ||
ff7c6d11 XL |
157 | /// Creates a new `Duration` from the specified number of nanoseconds. |
158 | /// | |
159 | /// # Examples | |
160 | /// | |
161 | /// ``` | |
ff7c6d11 XL |
162 | /// use std::time::Duration; |
163 | /// | |
164 | /// let duration = Duration::from_nanos(1_000_000_123); | |
165 | /// | |
166 | /// assert_eq!(1, duration.as_secs()); | |
167 | /// assert_eq!(123, duration.subsec_nanos()); | |
168 | /// ``` | |
83c7162d | 169 | #[stable(feature = "duration_extras", since = "1.27.0")] |
ff7c6d11 | 170 | #[inline] |
2c00a5a8 XL |
171 | pub const fn from_nanos(nanos: u64) -> Duration { |
172 | Duration { | |
173 | secs: nanos / (NANOS_PER_SEC as u64), | |
174 | nanos: (nanos % (NANOS_PER_SEC as u64)) as u32, | |
175 | } | |
ff7c6d11 XL |
176 | } |
177 | ||
3b2f2976 | 178 | /// Returns the number of _whole_ seconds contained by this `Duration`. |
d9579d0f | 179 | /// |
3b2f2976 XL |
180 | /// The returned value does not include the fractional (nanosecond) part of the |
181 | /// duration, which can be obtained using [`subsec_nanos`]. | |
32a655c1 SL |
182 | /// |
183 | /// # Examples | |
184 | /// | |
185 | /// ``` | |
186 | /// use std::time::Duration; | |
187 | /// | |
7cac9316 XL |
188 | /// let duration = Duration::new(5, 730023852); |
189 | /// assert_eq!(duration.as_secs(), 5); | |
190 | /// ``` | |
191 | /// | |
192 | /// To determine the total number of seconds represented by the `Duration`, | |
193 | /// use `as_secs` in combination with [`subsec_nanos`]: | |
194 | /// | |
32a655c1 | 195 | /// ``` |
7cac9316 XL |
196 | /// use std::time::Duration; |
197 | /// | |
198 | /// let duration = Duration::new(5, 730023852); | |
199 | /// | |
200 | /// assert_eq!(5.730023852, | |
201 | /// duration.as_secs() as f64 | |
202 | /// + duration.subsec_nanos() as f64 * 1e-9); | |
203 | /// ``` | |
204 | /// | |
205 | /// [`subsec_nanos`]: #method.subsec_nanos | |
c1a9b12d | 206 | #[stable(feature = "duration", since = "1.3.0")] |
94b46f34 | 207 | #[rustc_const_unstable(feature="duration_getters")] |
54a0048b | 208 | #[inline] |
94b46f34 | 209 | pub const fn as_secs(&self) -> u64 { self.secs } |
c1a9b12d | 210 | |
ff7c6d11 XL |
211 | /// Returns the fractional part of this `Duration`, in milliseconds. |
212 | /// | |
213 | /// This method does **not** return the length of the duration when | |
214 | /// represented by milliseconds. The returned number always represents a | |
215 | /// fractional portion of a second (i.e. it is less than one thousand). | |
216 | /// | |
217 | /// # Examples | |
218 | /// | |
219 | /// ``` | |
ff7c6d11 XL |
220 | /// use std::time::Duration; |
221 | /// | |
222 | /// let duration = Duration::from_millis(5432); | |
223 | /// assert_eq!(duration.as_secs(), 5); | |
2c00a5a8 | 224 | /// assert_eq!(duration.subsec_millis(), 432); |
ff7c6d11 | 225 | /// ``` |
83c7162d | 226 | #[stable(feature = "duration_extras", since = "1.27.0")] |
94b46f34 | 227 | #[rustc_const_unstable(feature="duration_getters")] |
ff7c6d11 | 228 | #[inline] |
94b46f34 | 229 | pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI } |
ff7c6d11 XL |
230 | |
231 | /// Returns the fractional part of this `Duration`, in microseconds. | |
232 | /// | |
233 | /// This method does **not** return the length of the duration when | |
234 | /// represented by microseconds. The returned number always represents a | |
235 | /// fractional portion of a second (i.e. it is less than one million). | |
236 | /// | |
237 | /// # Examples | |
238 | /// | |
239 | /// ``` | |
ff7c6d11 XL |
240 | /// use std::time::Duration; |
241 | /// | |
242 | /// let duration = Duration::from_micros(1_234_567); | |
243 | /// assert_eq!(duration.as_secs(), 1); | |
2c00a5a8 | 244 | /// assert_eq!(duration.subsec_micros(), 234_567); |
ff7c6d11 | 245 | /// ``` |
83c7162d | 246 | #[stable(feature = "duration_extras", since = "1.27.0")] |
94b46f34 | 247 | #[rustc_const_unstable(feature="duration_getters")] |
ff7c6d11 | 248 | #[inline] |
94b46f34 | 249 | pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO } |
ff7c6d11 | 250 | |
3b2f2976 | 251 | /// Returns the fractional part of this `Duration`, in nanoseconds. |
c1a9b12d SL |
252 | /// |
253 | /// This method does **not** return the length of the duration when | |
254 | /// represented by nanoseconds. The returned number always represents a | |
9e0c209e | 255 | /// fractional portion of a second (i.e. it is less than one billion). |
32a655c1 SL |
256 | /// |
257 | /// # Examples | |
258 | /// | |
259 | /// ``` | |
260 | /// use std::time::Duration; | |
261 | /// | |
262 | /// let duration = Duration::from_millis(5010); | |
3b2f2976 XL |
263 | /// assert_eq!(duration.as_secs(), 5); |
264 | /// assert_eq!(duration.subsec_nanos(), 10_000_000); | |
32a655c1 | 265 | /// ``` |
c1a9b12d | 266 | #[stable(feature = "duration", since = "1.3.0")] |
94b46f34 | 267 | #[rustc_const_unstable(feature="duration_getters")] |
54a0048b | 268 | #[inline] |
94b46f34 XL |
269 | pub const fn subsec_nanos(&self) -> u32 { self.nanos } |
270 | ||
271 | /// Returns the total number of milliseconds contained by this `Duration`. | |
272 | /// | |
273 | /// # Examples | |
274 | /// | |
275 | /// ``` | |
276 | /// # #![feature(duration_as_u128)] | |
277 | /// use std::time::Duration; | |
278 | /// | |
279 | /// let duration = Duration::new(5, 730023852); | |
280 | /// assert_eq!(duration.as_millis(), 5730); | |
281 | /// ``` | |
282 | #[unstable(feature = "duration_as_u128", issue = "50202")] | |
283 | #[inline] | |
284 | pub fn as_millis(&self) -> u128 { | |
285 | self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128 | |
286 | } | |
287 | ||
288 | /// Returns the total number of microseconds contained by this `Duration`. | |
289 | /// | |
290 | /// # Examples | |
291 | /// | |
292 | /// ``` | |
293 | /// # #![feature(duration_as_u128)] | |
294 | /// use std::time::Duration; | |
295 | /// | |
296 | /// let duration = Duration::new(5, 730023852); | |
297 | /// assert_eq!(duration.as_micros(), 5730023); | |
298 | /// ``` | |
299 | #[unstable(feature = "duration_as_u128", issue = "50202")] | |
300 | #[inline] | |
301 | pub fn as_micros(&self) -> u128 { | |
302 | self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128 | |
303 | } | |
304 | ||
305 | /// Returns the total number of nanoseconds contained by this `Duration`. | |
306 | /// | |
307 | /// # Examples | |
308 | /// | |
309 | /// ``` | |
310 | /// # #![feature(duration_as_u128)] | |
311 | /// use std::time::Duration; | |
312 | /// | |
313 | /// let duration = Duration::new(5, 730023852); | |
314 | /// assert_eq!(duration.as_nanos(), 5730023852); | |
315 | /// ``` | |
316 | #[unstable(feature = "duration_as_u128", issue = "50202")] | |
317 | #[inline] | |
318 | pub fn as_nanos(&self) -> u128 { | |
319 | self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128 | |
320 | } | |
9e0c209e | 321 | |
32a655c1 | 322 | /// Checked `Duration` addition. Computes `self + other`, returning [`None`] |
9e0c209e SL |
323 | /// if overflow occurred. |
324 | /// | |
32a655c1 SL |
325 | /// [`None`]: ../../std/option/enum.Option.html#variant.None |
326 | /// | |
9e0c209e SL |
327 | /// # Examples |
328 | /// | |
329 | /// Basic usage: | |
330 | /// | |
331 | /// ``` | |
9e0c209e SL |
332 | /// use std::time::Duration; |
333 | /// | |
334 | /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); | |
335 | /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None); | |
336 | /// ``` | |
32a655c1 | 337 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |
9e0c209e SL |
338 | #[inline] |
339 | pub fn checked_add(self, rhs: Duration) -> Option<Duration> { | |
340 | if let Some(mut secs) = self.secs.checked_add(rhs.secs) { | |
341 | let mut nanos = self.nanos + rhs.nanos; | |
342 | if nanos >= NANOS_PER_SEC { | |
343 | nanos -= NANOS_PER_SEC; | |
344 | if let Some(new_secs) = secs.checked_add(1) { | |
345 | secs = new_secs; | |
346 | } else { | |
347 | return None; | |
348 | } | |
349 | } | |
350 | debug_assert!(nanos < NANOS_PER_SEC); | |
351 | Some(Duration { | |
3b2f2976 XL |
352 | secs, |
353 | nanos, | |
9e0c209e SL |
354 | }) |
355 | } else { | |
356 | None | |
357 | } | |
358 | } | |
359 | ||
32a655c1 | 360 | /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] |
ff7c6d11 | 361 | /// if the result would be negative or if overflow occurred. |
9e0c209e | 362 | /// |
32a655c1 SL |
363 | /// [`None`]: ../../std/option/enum.Option.html#variant.None |
364 | /// | |
9e0c209e SL |
365 | /// # Examples |
366 | /// | |
367 | /// Basic usage: | |
368 | /// | |
369 | /// ``` | |
9e0c209e SL |
370 | /// use std::time::Duration; |
371 | /// | |
372 | /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1))); | |
373 | /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); | |
374 | /// ``` | |
32a655c1 | 375 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |
9e0c209e SL |
376 | #[inline] |
377 | pub fn checked_sub(self, rhs: Duration) -> Option<Duration> { | |
378 | if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { | |
379 | let nanos = if self.nanos >= rhs.nanos { | |
380 | self.nanos - rhs.nanos | |
381 | } else { | |
382 | if let Some(sub_secs) = secs.checked_sub(1) { | |
383 | secs = sub_secs; | |
384 | self.nanos + NANOS_PER_SEC - rhs.nanos | |
385 | } else { | |
386 | return None; | |
387 | } | |
388 | }; | |
389 | debug_assert!(nanos < NANOS_PER_SEC); | |
390 | Some(Duration { secs: secs, nanos: nanos }) | |
391 | } else { | |
392 | None | |
393 | } | |
394 | } | |
395 | ||
32a655c1 SL |
396 | /// Checked `Duration` multiplication. Computes `self * other`, returning |
397 | /// [`None`] if overflow occurred. | |
398 | /// | |
399 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
9e0c209e SL |
400 | /// |
401 | /// # Examples | |
402 | /// | |
403 | /// Basic usage: | |
404 | /// | |
405 | /// ``` | |
9e0c209e SL |
406 | /// use std::time::Duration; |
407 | /// | |
408 | /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2))); | |
409 | /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None); | |
410 | /// ``` | |
32a655c1 | 411 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |
9e0c209e SL |
412 | #[inline] |
413 | pub fn checked_mul(self, rhs: u32) -> Option<Duration> { | |
414 | // Multiply nanoseconds as u64, because it cannot overflow that way. | |
415 | let total_nanos = self.nanos as u64 * rhs as u64; | |
416 | let extra_secs = total_nanos / (NANOS_PER_SEC as u64); | |
417 | let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; | |
418 | if let Some(secs) = self.secs | |
419 | .checked_mul(rhs as u64) | |
420 | .and_then(|s| s.checked_add(extra_secs)) { | |
421 | debug_assert!(nanos < NANOS_PER_SEC); | |
422 | Some(Duration { | |
3b2f2976 XL |
423 | secs, |
424 | nanos, | |
9e0c209e SL |
425 | }) |
426 | } else { | |
427 | None | |
428 | } | |
429 | } | |
430 | ||
32a655c1 SL |
431 | /// Checked `Duration` division. Computes `self / other`, returning [`None`] |
432 | /// if `other == 0`. | |
433 | /// | |
434 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
9e0c209e SL |
435 | /// |
436 | /// # Examples | |
437 | /// | |
438 | /// Basic usage: | |
439 | /// | |
440 | /// ``` | |
9e0c209e SL |
441 | /// use std::time::Duration; |
442 | /// | |
443 | /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); | |
444 | /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); | |
445 | /// assert_eq!(Duration::new(2, 0).checked_div(0), None); | |
446 | /// ``` | |
32a655c1 | 447 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |
9e0c209e SL |
448 | #[inline] |
449 | pub fn checked_div(self, rhs: u32) -> Option<Duration> { | |
450 | if rhs != 0 { | |
451 | let secs = self.secs / (rhs as u64); | |
452 | let carry = self.secs - secs * (rhs as u64); | |
453 | let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); | |
454 | let nanos = self.nanos / rhs + (extra_nanos as u32); | |
455 | debug_assert!(nanos < NANOS_PER_SEC); | |
456 | Some(Duration { secs: secs, nanos: nanos }) | |
457 | } else { | |
458 | None | |
459 | } | |
460 | } | |
1a4d82fc JJ |
461 | } |
462 | ||
92a42be0 | 463 | #[stable(feature = "duration", since = "1.3.0")] |
1a4d82fc JJ |
464 | impl Add for Duration { |
465 | type Output = Duration; | |
466 | ||
467 | fn add(self, rhs: Duration) -> Duration { | |
9e0c209e | 468 | self.checked_add(rhs).expect("overflow when adding durations") |
1a4d82fc JJ |
469 | } |
470 | } | |
471 | ||
54a0048b SL |
472 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
473 | impl AddAssign for Duration { | |
474 | fn add_assign(&mut self, rhs: Duration) { | |
475 | *self = *self + rhs; | |
476 | } | |
477 | } | |
478 | ||
92a42be0 | 479 | #[stable(feature = "duration", since = "1.3.0")] |
1a4d82fc JJ |
480 | impl Sub for Duration { |
481 | type Output = Duration; | |
482 | ||
483 | fn sub(self, rhs: Duration) -> Duration { | |
9e0c209e | 484 | self.checked_sub(rhs).expect("overflow when subtracting durations") |
1a4d82fc JJ |
485 | } |
486 | } | |
487 | ||
54a0048b SL |
488 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
489 | impl SubAssign for Duration { | |
490 | fn sub_assign(&mut self, rhs: Duration) { | |
491 | *self = *self - rhs; | |
492 | } | |
493 | } | |
494 | ||
92a42be0 | 495 | #[stable(feature = "duration", since = "1.3.0")] |
d9579d0f | 496 | impl Mul<u32> for Duration { |
1a4d82fc JJ |
497 | type Output = Duration; |
498 | ||
d9579d0f | 499 | fn mul(self, rhs: u32) -> Duration { |
9e0c209e | 500 | self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") |
1a4d82fc JJ |
501 | } |
502 | } | |
503 | ||
54a0048b SL |
504 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
505 | impl MulAssign<u32> for Duration { | |
506 | fn mul_assign(&mut self, rhs: u32) { | |
507 | *self = *self * rhs; | |
508 | } | |
509 | } | |
510 | ||
92a42be0 | 511 | #[stable(feature = "duration", since = "1.3.0")] |
d9579d0f | 512 | impl Div<u32> for Duration { |
1a4d82fc JJ |
513 | type Output = Duration; |
514 | ||
d9579d0f | 515 | fn div(self, rhs: u32) -> Duration { |
9e0c209e | 516 | self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") |
1a4d82fc JJ |
517 | } |
518 | } | |
519 | ||
54a0048b SL |
520 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
521 | impl DivAssign<u32> for Duration { | |
522 | fn div_assign(&mut self, rhs: u32) { | |
523 | *self = *self / rhs; | |
524 | } | |
525 | } | |
526 | ||
32a655c1 SL |
527 | #[stable(feature = "duration_sum", since = "1.16.0")] |
528 | impl Sum for Duration { | |
529 | fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration { | |
530 | iter.fold(Duration::new(0, 0), |a, b| a + b) | |
531 | } | |
532 | } | |
533 | ||
534 | #[stable(feature = "duration_sum", since = "1.16.0")] | |
535 | impl<'a> Sum<&'a Duration> for Duration { | |
536 | fn sum<I: Iterator<Item=&'a Duration>>(iter: I) -> Duration { | |
537 | iter.fold(Duration::new(0, 0), |a, b| a + *b) | |
538 | } | |
539 | } | |
94b46f34 XL |
540 | |
541 | #[stable(feature = "duration_debug_impl", since = "1.27.0")] | |
542 | impl fmt::Debug for Duration { | |
543 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
544 | /// Formats a floating point number in decimal notation. | |
545 | /// | |
546 | /// The number is given as the `integer_part` and a fractional part. | |
547 | /// The value of the fractional part is `fractional_part / divisor`. So | |
548 | /// `integer_part` = 3, `fractional_part` = 12 and `divisor` = 100 | |
549 | /// represents the number `3.012`. Trailing zeros are omitted. | |
550 | /// | |
551 | /// `divisor` must not be above 100_000_000. It also should be a power | |
552 | /// of 10, everything else doesn't make sense. `fractional_part` has | |
553 | /// to be less than `10 * divisor`! | |
554 | fn fmt_decimal( | |
555 | f: &mut fmt::Formatter, | |
556 | mut integer_part: u64, | |
557 | mut fractional_part: u32, | |
558 | mut divisor: u32, | |
559 | ) -> fmt::Result { | |
560 | // Encode the fractional part into a temporary buffer. The buffer | |
561 | // only need to hold 9 elements, because `fractional_part` has to | |
562 | // be smaller than 10^9. The buffer is prefilled with '0' digits | |
563 | // to simplify the code below. | |
564 | let mut buf = [b'0'; 9]; | |
565 | ||
566 | // The next digit is written at this position | |
567 | let mut pos = 0; | |
568 | ||
569 | // We keep writing digits into the buffer while there are non-zero | |
570 | // digits left and we haven't written enough digits yet. | |
571 | while fractional_part > 0 && pos < f.precision().unwrap_or(9) { | |
572 | // Write new digit into the buffer | |
573 | buf[pos] = b'0' + (fractional_part / divisor) as u8; | |
574 | ||
575 | fractional_part %= divisor; | |
576 | divisor /= 10; | |
577 | pos += 1; | |
578 | } | |
579 | ||
580 | // If a precision < 9 was specified, there may be some non-zero | |
581 | // digits left that weren't written into the buffer. In that case we | |
582 | // need to perform rounding to match the semantics of printing | |
583 | // normal floating point numbers. However, we only need to do work | |
584 | // when rounding up. This happens if the first digit of the | |
585 | // remaining ones is >= 5. | |
586 | if fractional_part > 0 && fractional_part >= divisor * 5 { | |
587 | // Round up the number contained in the buffer. We go through | |
588 | // the buffer backwards and keep track of the carry. | |
589 | let mut rev_pos = pos; | |
590 | let mut carry = true; | |
591 | while carry && rev_pos > 0 { | |
592 | rev_pos -= 1; | |
593 | ||
594 | // If the digit in the buffer is not '9', we just need to | |
595 | // increment it and can stop then (since we don't have a | |
596 | // carry anymore). Otherwise, we set it to '0' (overflow) | |
597 | // and continue. | |
598 | if buf[rev_pos] < b'9' { | |
599 | buf[rev_pos] += 1; | |
600 | carry = false; | |
601 | } else { | |
602 | buf[rev_pos] = b'0'; | |
603 | } | |
604 | } | |
605 | ||
606 | // If we still have the carry bit set, that means that we set | |
607 | // the whole buffer to '0's and need to increment the integer | |
608 | // part. | |
609 | if carry { | |
610 | integer_part += 1; | |
611 | } | |
612 | } | |
613 | ||
614 | // Determine the end of the buffer: if precision is set, we just | |
615 | // use as many digits from the buffer (capped to 9). If it isn't | |
616 | // set, we only use all digits up to the last non-zero one. | |
617 | let end = f.precision().map(|p| ::cmp::min(p, 9)).unwrap_or(pos); | |
618 | ||
619 | // If we haven't emitted a single fractional digit and the precision | |
620 | // wasn't set to a non-zero value, we don't print the decimal point. | |
621 | if end == 0 { | |
622 | write!(f, "{}", integer_part) | |
623 | } else { | |
624 | // We are only writing ASCII digits into the buffer and it was | |
625 | // initialized with '0's, so it contains valid UTF8. | |
626 | let s = unsafe { | |
627 | ::str::from_utf8_unchecked(&buf[..end]) | |
628 | }; | |
629 | ||
630 | // If the user request a precision > 9, we pad '0's at the end. | |
631 | let w = f.precision().unwrap_or(pos); | |
632 | write!(f, "{}.{:0<width$}", integer_part, s, width = w) | |
633 | } | |
634 | } | |
635 | ||
636 | // Print leading '+' sign if requested | |
637 | if f.sign_plus() { | |
638 | write!(f, "+")?; | |
639 | } | |
640 | ||
641 | if self.secs > 0 { | |
642 | fmt_decimal(f, self.secs, self.nanos, 100_000_000)?; | |
643 | f.write_str("s") | |
644 | } else if self.nanos >= 1_000_000 { | |
645 | fmt_decimal(f, self.nanos as u64 / 1_000_000, self.nanos % 1_000_000, 100_000)?; | |
646 | f.write_str("ms") | |
647 | } else if self.nanos >= 1_000 { | |
648 | fmt_decimal(f, self.nanos as u64 / 1_000, self.nanos % 1_000, 100)?; | |
649 | f.write_str("µs") | |
650 | } else { | |
651 | fmt_decimal(f, self.nanos as u64, 0, 1)?; | |
652 | f.write_str("ns") | |
653 | } | |
654 | } | |
655 | } |