]> git.lizzy.rs Git - rust.git/blob - library/core/src/time.rs
Rollup merge of #102300 - scottmcm:simpler-fold-closures, r=Mark-Simulacrum
[rust.git] / library / core / src / time.rs
1 #![stable(feature = "duration_core", since = "1.25.0")]
2
3 //! Temporal quantification.
4 //!
5 //! # Examples:
6 //!
7 //! There are multiple ways to create a new [`Duration`]:
8 //!
9 //! ```
10 //! # use std::time::Duration;
11 //! let five_seconds = Duration::from_secs(5);
12 //! assert_eq!(five_seconds, Duration::from_millis(5_000));
13 //! assert_eq!(five_seconds, Duration::from_micros(5_000_000));
14 //! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
15 //!
16 //! let ten_seconds = Duration::from_secs(10);
17 //! let seven_nanos = Duration::from_nanos(7);
18 //! let total = ten_seconds + seven_nanos;
19 //! assert_eq!(total, Duration::new(10, 7));
20 //! ```
21
22 use crate::fmt;
23 use crate::iter::Sum;
24 use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
25
26 const NANOS_PER_SEC: u32 = 1_000_000_000;
27 const NANOS_PER_MILLI: u32 = 1_000_000;
28 const NANOS_PER_MICRO: u32 = 1_000;
29 const MILLIS_PER_SEC: u64 = 1_000;
30 const MICROS_PER_SEC: u64 = 1_000_000;
31
32 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
33 #[repr(transparent)]
34 #[rustc_layout_scalar_valid_range_start(0)]
35 #[rustc_layout_scalar_valid_range_end(999_999_999)]
36 struct Nanoseconds(u32);
37
38 impl Default for Nanoseconds {
39     #[inline]
40     fn default() -> Self {
41         // SAFETY: 0 is within the valid range
42         unsafe { Nanoseconds(0) }
43     }
44 }
45
46 /// A `Duration` type to represent a span of time, typically used for system
47 /// timeouts.
48 ///
49 /// Each `Duration` is composed of a whole number of seconds and a fractional part
50 /// represented in nanoseconds. If the underlying system does not support
51 /// nanosecond-level precision, APIs binding a system timeout will typically round up
52 /// the number of nanoseconds.
53 ///
54 /// [`Duration`]s implement many common traits, including [`Add`], [`Sub`], and other
55 /// [`ops`] traits. It implements [`Default`] by returning a zero-length `Duration`.
56 ///
57 /// [`ops`]: crate::ops
58 ///
59 /// # Examples
60 ///
61 /// ```
62 /// use std::time::Duration;
63 ///
64 /// let five_seconds = Duration::new(5, 0);
65 /// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
66 ///
67 /// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
68 /// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
69 ///
70 /// let ten_millis = Duration::from_millis(10);
71 /// ```
72 ///
73 /// # Formatting `Duration` values
74 ///
75 /// `Duration` intentionally does not have a `Display` impl, as there are a
76 /// variety of ways to format spans of time for human readability. `Duration`
77 /// provides a `Debug` impl that shows the full precision of the value.
78 ///
79 /// The `Debug` output uses the non-ASCII "µs" suffix for microseconds. If your
80 /// program output may appear in contexts that cannot rely on full Unicode
81 /// compatibility, you may wish to format `Duration` objects yourself or use a
82 /// crate to do so.
83 #[stable(feature = "duration", since = "1.3.0")]
84 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
85 #[cfg_attr(not(test), rustc_diagnostic_item = "Duration")]
86 pub struct Duration {
87     secs: u64,
88     nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC
89 }
90
91 impl Duration {
92     /// The duration of one second.
93     ///
94     /// # Examples
95     ///
96     /// ```
97     /// #![feature(duration_constants)]
98     /// use std::time::Duration;
99     ///
100     /// assert_eq!(Duration::SECOND, Duration::from_secs(1));
101     /// ```
102     #[unstable(feature = "duration_constants", issue = "57391")]
103     pub const SECOND: Duration = Duration::from_secs(1);
104
105     /// The duration of one millisecond.
106     ///
107     /// # Examples
108     ///
109     /// ```
110     /// #![feature(duration_constants)]
111     /// use std::time::Duration;
112     ///
113     /// assert_eq!(Duration::MILLISECOND, Duration::from_millis(1));
114     /// ```
115     #[unstable(feature = "duration_constants", issue = "57391")]
116     pub const MILLISECOND: Duration = Duration::from_millis(1);
117
118     /// The duration of one microsecond.
119     ///
120     /// # Examples
121     ///
122     /// ```
123     /// #![feature(duration_constants)]
124     /// use std::time::Duration;
125     ///
126     /// assert_eq!(Duration::MICROSECOND, Duration::from_micros(1));
127     /// ```
128     #[unstable(feature = "duration_constants", issue = "57391")]
129     pub const MICROSECOND: Duration = Duration::from_micros(1);
130
131     /// The duration of one nanosecond.
132     ///
133     /// # Examples
134     ///
135     /// ```
136     /// #![feature(duration_constants)]
137     /// use std::time::Duration;
138     ///
139     /// assert_eq!(Duration::NANOSECOND, Duration::from_nanos(1));
140     /// ```
141     #[unstable(feature = "duration_constants", issue = "57391")]
142     pub const NANOSECOND: Duration = Duration::from_nanos(1);
143
144     /// A duration of zero time.
145     ///
146     /// # Examples
147     ///
148     /// ```
149     /// use std::time::Duration;
150     ///
151     /// let duration = Duration::ZERO;
152     /// assert!(duration.is_zero());
153     /// assert_eq!(duration.as_nanos(), 0);
154     /// ```
155     #[stable(feature = "duration_zero", since = "1.53.0")]
156     pub const ZERO: Duration = Duration::from_nanos(0);
157
158     /// The maximum duration.
159     ///
160     /// May vary by platform as necessary. Must be able to contain the difference between
161     /// two instances of [`Instant`] or two instances of [`SystemTime`].
162     /// This constraint gives it a value of about 584,942,417,355 years in practice,
163     /// which is currently used on all platforms.
164     ///
165     /// # Examples
166     ///
167     /// ```
168     /// use std::time::Duration;
169     ///
170     /// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1));
171     /// ```
172     /// [`Instant`]: ../../std/time/struct.Instant.html
173     /// [`SystemTime`]: ../../std/time/struct.SystemTime.html
174     #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
175     pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1);
176
177     /// Creates a new `Duration` from the specified number of whole seconds and
178     /// additional nanoseconds.
179     ///
180     /// If the number of nanoseconds is greater than 1 billion (the number of
181     /// nanoseconds in a second), then it will carry over into the seconds provided.
182     ///
183     /// # Panics
184     ///
185     /// This constructor will panic if the carry from the nanoseconds overflows
186     /// the seconds counter.
187     ///
188     /// # Examples
189     ///
190     /// ```
191     /// use std::time::Duration;
192     ///
193     /// let five_seconds = Duration::new(5, 0);
194     /// ```
195     #[stable(feature = "duration", since = "1.3.0")]
196     #[inline]
197     #[must_use]
198     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
199     pub const fn new(secs: u64, nanos: u32) -> Duration {
200         let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
201             Some(secs) => secs,
202             None => panic!("overflow in Duration::new"),
203         };
204         let nanos = nanos % NANOS_PER_SEC;
205         // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range
206         Duration { secs, nanos: unsafe { Nanoseconds(nanos) } }
207     }
208
209     /// Creates a new `Duration` from the specified number of whole seconds.
210     ///
211     /// # Examples
212     ///
213     /// ```
214     /// use std::time::Duration;
215     ///
216     /// let duration = Duration::from_secs(5);
217     ///
218     /// assert_eq!(5, duration.as_secs());
219     /// assert_eq!(0, duration.subsec_nanos());
220     /// ```
221     #[stable(feature = "duration", since = "1.3.0")]
222     #[must_use]
223     #[inline]
224     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
225     pub const fn from_secs(secs: u64) -> Duration {
226         Duration::new(secs, 0)
227     }
228
229     /// Creates a new `Duration` from the specified number of milliseconds.
230     ///
231     /// # Examples
232     ///
233     /// ```
234     /// use std::time::Duration;
235     ///
236     /// let duration = Duration::from_millis(2569);
237     ///
238     /// assert_eq!(2, duration.as_secs());
239     /// assert_eq!(569_000_000, duration.subsec_nanos());
240     /// ```
241     #[stable(feature = "duration", since = "1.3.0")]
242     #[must_use]
243     #[inline]
244     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
245     pub const fn from_millis(millis: u64) -> Duration {
246         Duration::new(millis / MILLIS_PER_SEC, ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI)
247     }
248
249     /// Creates a new `Duration` from the specified number of microseconds.
250     ///
251     /// # Examples
252     ///
253     /// ```
254     /// use std::time::Duration;
255     ///
256     /// let duration = Duration::from_micros(1_000_002);
257     ///
258     /// assert_eq!(1, duration.as_secs());
259     /// assert_eq!(2000, duration.subsec_nanos());
260     /// ```
261     #[stable(feature = "duration_from_micros", since = "1.27.0")]
262     #[must_use]
263     #[inline]
264     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
265     pub const fn from_micros(micros: u64) -> Duration {
266         Duration::new(micros / MICROS_PER_SEC, ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO)
267     }
268
269     /// Creates a new `Duration` from the specified number of nanoseconds.
270     ///
271     /// # Examples
272     ///
273     /// ```
274     /// use std::time::Duration;
275     ///
276     /// let duration = Duration::from_nanos(1_000_000_123);
277     ///
278     /// assert_eq!(1, duration.as_secs());
279     /// assert_eq!(123, duration.subsec_nanos());
280     /// ```
281     #[stable(feature = "duration_extras", since = "1.27.0")]
282     #[must_use]
283     #[inline]
284     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
285     pub const fn from_nanos(nanos: u64) -> Duration {
286         Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32)
287     }
288
289     /// Returns true if this `Duration` spans no time.
290     ///
291     /// # Examples
292     ///
293     /// ```
294     /// use std::time::Duration;
295     ///
296     /// assert!(Duration::ZERO.is_zero());
297     /// assert!(Duration::new(0, 0).is_zero());
298     /// assert!(Duration::from_nanos(0).is_zero());
299     /// assert!(Duration::from_secs(0).is_zero());
300     ///
301     /// assert!(!Duration::new(1, 1).is_zero());
302     /// assert!(!Duration::from_nanos(1).is_zero());
303     /// assert!(!Duration::from_secs(1).is_zero());
304     /// ```
305     #[must_use]
306     #[stable(feature = "duration_zero", since = "1.53.0")]
307     #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")]
308     #[inline]
309     pub const fn is_zero(&self) -> bool {
310         self.secs == 0 && self.nanos.0 == 0
311     }
312
313     /// Returns the number of _whole_ seconds contained by this `Duration`.
314     ///
315     /// The returned value does not include the fractional (nanosecond) part of the
316     /// duration, which can be obtained using [`subsec_nanos`].
317     ///
318     /// # Examples
319     ///
320     /// ```
321     /// use std::time::Duration;
322     ///
323     /// let duration = Duration::new(5, 730023852);
324     /// assert_eq!(duration.as_secs(), 5);
325     /// ```
326     ///
327     /// To determine the total number of seconds represented by the `Duration`
328     /// including the fractional part, use [`as_secs_f64`] or [`as_secs_f32`]
329     ///
330     /// [`as_secs_f64`]: Duration::as_secs_f64
331     /// [`as_secs_f32`]: Duration::as_secs_f32
332     /// [`subsec_nanos`]: Duration::subsec_nanos
333     #[stable(feature = "duration", since = "1.3.0")]
334     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
335     #[must_use]
336     #[inline]
337     pub const fn as_secs(&self) -> u64 {
338         self.secs
339     }
340
341     /// Returns the fractional part of this `Duration`, in whole milliseconds.
342     ///
343     /// This method does **not** return the length of the duration when
344     /// represented by milliseconds. The returned number always represents a
345     /// fractional portion of a second (i.e., it is less than one thousand).
346     ///
347     /// # Examples
348     ///
349     /// ```
350     /// use std::time::Duration;
351     ///
352     /// let duration = Duration::from_millis(5432);
353     /// assert_eq!(duration.as_secs(), 5);
354     /// assert_eq!(duration.subsec_millis(), 432);
355     /// ```
356     #[stable(feature = "duration_extras", since = "1.27.0")]
357     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
358     #[must_use]
359     #[inline]
360     pub const fn subsec_millis(&self) -> u32 {
361         self.nanos.0 / NANOS_PER_MILLI
362     }
363
364     /// Returns the fractional part of this `Duration`, in whole microseconds.
365     ///
366     /// This method does **not** return the length of the duration when
367     /// represented by microseconds. The returned number always represents a
368     /// fractional portion of a second (i.e., it is less than one million).
369     ///
370     /// # Examples
371     ///
372     /// ```
373     /// use std::time::Duration;
374     ///
375     /// let duration = Duration::from_micros(1_234_567);
376     /// assert_eq!(duration.as_secs(), 1);
377     /// assert_eq!(duration.subsec_micros(), 234_567);
378     /// ```
379     #[stable(feature = "duration_extras", since = "1.27.0")]
380     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
381     #[must_use]
382     #[inline]
383     pub const fn subsec_micros(&self) -> u32 {
384         self.nanos.0 / NANOS_PER_MICRO
385     }
386
387     /// Returns the fractional part of this `Duration`, in nanoseconds.
388     ///
389     /// This method does **not** return the length of the duration when
390     /// represented by nanoseconds. The returned number always represents a
391     /// fractional portion of a second (i.e., it is less than one billion).
392     ///
393     /// # Examples
394     ///
395     /// ```
396     /// use std::time::Duration;
397     ///
398     /// let duration = Duration::from_millis(5010);
399     /// assert_eq!(duration.as_secs(), 5);
400     /// assert_eq!(duration.subsec_nanos(), 10_000_000);
401     /// ```
402     #[stable(feature = "duration", since = "1.3.0")]
403     #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
404     #[must_use]
405     #[inline]
406     pub const fn subsec_nanos(&self) -> u32 {
407         self.nanos.0
408     }
409
410     /// Returns the total number of whole milliseconds contained by this `Duration`.
411     ///
412     /// # Examples
413     ///
414     /// ```
415     /// use std::time::Duration;
416     ///
417     /// let duration = Duration::new(5, 730023852);
418     /// assert_eq!(duration.as_millis(), 5730);
419     /// ```
420     #[stable(feature = "duration_as_u128", since = "1.33.0")]
421     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
422     #[must_use]
423     #[inline]
424     pub const fn as_millis(&self) -> u128 {
425         self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128
426     }
427
428     /// Returns the total number of whole microseconds contained by this `Duration`.
429     ///
430     /// # Examples
431     ///
432     /// ```
433     /// use std::time::Duration;
434     ///
435     /// let duration = Duration::new(5, 730023852);
436     /// assert_eq!(duration.as_micros(), 5730023);
437     /// ```
438     #[stable(feature = "duration_as_u128", since = "1.33.0")]
439     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
440     #[must_use]
441     #[inline]
442     pub const fn as_micros(&self) -> u128 {
443         self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128
444     }
445
446     /// Returns the total number of nanoseconds contained by this `Duration`.
447     ///
448     /// # Examples
449     ///
450     /// ```
451     /// use std::time::Duration;
452     ///
453     /// let duration = Duration::new(5, 730023852);
454     /// assert_eq!(duration.as_nanos(), 5730023852);
455     /// ```
456     #[stable(feature = "duration_as_u128", since = "1.33.0")]
457     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
458     #[must_use]
459     #[inline]
460     pub const fn as_nanos(&self) -> u128 {
461         self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128
462     }
463
464     /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
465     /// if overflow occurred.
466     ///
467     /// # Examples
468     ///
469     /// Basic usage:
470     ///
471     /// ```
472     /// use std::time::Duration;
473     ///
474     /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
475     /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
476     /// ```
477     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
478     #[must_use = "this returns the result of the operation, \
479                   without modifying the original"]
480     #[inline]
481     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
482     pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
483         if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
484             let mut nanos = self.nanos.0 + rhs.nanos.0;
485             if nanos >= NANOS_PER_SEC {
486                 nanos -= NANOS_PER_SEC;
487                 if let Some(new_secs) = secs.checked_add(1) {
488                     secs = new_secs;
489                 } else {
490                     return None;
491                 }
492             }
493             debug_assert!(nanos < NANOS_PER_SEC);
494             Some(Duration::new(secs, nanos))
495         } else {
496             None
497         }
498     }
499
500     /// Saturating `Duration` addition. Computes `self + other`, returning [`Duration::MAX`]
501     /// if overflow occurred.
502     ///
503     /// # Examples
504     ///
505     /// ```
506     /// #![feature(duration_constants)]
507     /// use std::time::Duration;
508     ///
509     /// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
510     /// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
511     /// ```
512     #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
513     #[must_use = "this returns the result of the operation, \
514                   without modifying the original"]
515     #[inline]
516     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
517     pub const fn saturating_add(self, rhs: Duration) -> Duration {
518         match self.checked_add(rhs) {
519             Some(res) => res,
520             None => Duration::MAX,
521         }
522     }
523
524     /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
525     /// if the result would be negative or if overflow occurred.
526     ///
527     /// # Examples
528     ///
529     /// Basic usage:
530     ///
531     /// ```
532     /// use std::time::Duration;
533     ///
534     /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
535     /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
536     /// ```
537     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
538     #[must_use = "this returns the result of the operation, \
539                   without modifying the original"]
540     #[inline]
541     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
542     pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
543         if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
544             let nanos = if self.nanos.0 >= rhs.nanos.0 {
545                 self.nanos.0 - rhs.nanos.0
546             } else if let Some(sub_secs) = secs.checked_sub(1) {
547                 secs = sub_secs;
548                 self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0
549             } else {
550                 return None;
551             };
552             debug_assert!(nanos < NANOS_PER_SEC);
553             Some(Duration::new(secs, nanos))
554         } else {
555             None
556         }
557     }
558
559     /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`]
560     /// if the result would be negative or if overflow occurred.
561     ///
562     /// # Examples
563     ///
564     /// ```
565     /// use std::time::Duration;
566     ///
567     /// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
568     /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
569     /// ```
570     #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
571     #[must_use = "this returns the result of the operation, \
572                   without modifying the original"]
573     #[inline]
574     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
575     pub const fn saturating_sub(self, rhs: Duration) -> Duration {
576         match self.checked_sub(rhs) {
577             Some(res) => res,
578             None => Duration::ZERO,
579         }
580     }
581
582     /// Checked `Duration` multiplication. Computes `self * other`, returning
583     /// [`None`] if overflow occurred.
584     ///
585     /// # Examples
586     ///
587     /// Basic usage:
588     ///
589     /// ```
590     /// use std::time::Duration;
591     ///
592     /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
593     /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
594     /// ```
595     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
596     #[must_use = "this returns the result of the operation, \
597                   without modifying the original"]
598     #[inline]
599     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
600     pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
601         // Multiply nanoseconds as u64, because it cannot overflow that way.
602         let total_nanos = self.nanos.0 as u64 * rhs as u64;
603         let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
604         let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
605         if let Some(s) = self.secs.checked_mul(rhs as u64) {
606             if let Some(secs) = s.checked_add(extra_secs) {
607                 debug_assert!(nanos < NANOS_PER_SEC);
608                 return Some(Duration::new(secs, nanos));
609             }
610         }
611         None
612     }
613
614     /// Saturating `Duration` multiplication. Computes `self * other`, returning
615     /// [`Duration::MAX`] if overflow occurred.
616     ///
617     /// # Examples
618     ///
619     /// ```
620     /// #![feature(duration_constants)]
621     /// use std::time::Duration;
622     ///
623     /// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));
624     /// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
625     /// ```
626     #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
627     #[must_use = "this returns the result of the operation, \
628                   without modifying the original"]
629     #[inline]
630     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
631     pub const fn saturating_mul(self, rhs: u32) -> Duration {
632         match self.checked_mul(rhs) {
633             Some(res) => res,
634             None => Duration::MAX,
635         }
636     }
637
638     /// Checked `Duration` division. Computes `self / other`, returning [`None`]
639     /// if `other == 0`.
640     ///
641     /// # Examples
642     ///
643     /// Basic usage:
644     ///
645     /// ```
646     /// use std::time::Duration;
647     ///
648     /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
649     /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
650     /// assert_eq!(Duration::new(2, 0).checked_div(0), None);
651     /// ```
652     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
653     #[must_use = "this returns the result of the operation, \
654                   without modifying the original"]
655     #[inline]
656     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
657     pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
658         if rhs != 0 {
659             let secs = self.secs / (rhs as u64);
660             let carry = self.secs - secs * (rhs as u64);
661             let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
662             let nanos = self.nanos.0 / rhs + (extra_nanos as u32);
663             debug_assert!(nanos < NANOS_PER_SEC);
664             Some(Duration::new(secs, nanos))
665         } else {
666             None
667         }
668     }
669
670     /// Returns the number of seconds contained by this `Duration` as `f64`.
671     ///
672     /// The returned value does include the fractional (nanosecond) part of the duration.
673     ///
674     /// # Examples
675     /// ```
676     /// use std::time::Duration;
677     ///
678     /// let dur = Duration::new(2, 700_000_000);
679     /// assert_eq!(dur.as_secs_f64(), 2.7);
680     /// ```
681     #[stable(feature = "duration_float", since = "1.38.0")]
682     #[must_use]
683     #[inline]
684     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
685     pub const fn as_secs_f64(&self) -> f64 {
686         (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64)
687     }
688
689     /// Returns the number of seconds contained by this `Duration` as `f32`.
690     ///
691     /// The returned value does include the fractional (nanosecond) part of the duration.
692     ///
693     /// # Examples
694     /// ```
695     /// use std::time::Duration;
696     ///
697     /// let dur = Duration::new(2, 700_000_000);
698     /// assert_eq!(dur.as_secs_f32(), 2.7);
699     /// ```
700     #[stable(feature = "duration_float", since = "1.38.0")]
701     #[must_use]
702     #[inline]
703     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
704     pub const fn as_secs_f32(&self) -> f32 {
705         (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32)
706     }
707
708     /// Creates a new `Duration` from the specified number of seconds represented
709     /// as `f64`.
710     ///
711     /// # Panics
712     /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite.
713     ///
714     /// # Examples
715     /// ```
716     /// use std::time::Duration;
717     ///
718     /// let res = Duration::from_secs_f64(0.0);
719     /// assert_eq!(res, Duration::new(0, 0));
720     /// let res = Duration::from_secs_f64(1e-20);
721     /// assert_eq!(res, Duration::new(0, 0));
722     /// let res = Duration::from_secs_f64(4.2e-7);
723     /// assert_eq!(res, Duration::new(0, 420));
724     /// let res = Duration::from_secs_f64(2.7);
725     /// assert_eq!(res, Duration::new(2, 700_000_000));
726     /// let res = Duration::from_secs_f64(3e10);
727     /// assert_eq!(res, Duration::new(30_000_000_000, 0));
728     /// // subnormal float
729     /// let res = Duration::from_secs_f64(f64::from_bits(1));
730     /// assert_eq!(res, Duration::new(0, 0));
731     /// // conversion uses rounding
732     /// let res = Duration::from_secs_f64(0.999e-9);
733     /// assert_eq!(res, Duration::new(0, 1));
734     /// ```
735     #[stable(feature = "duration_float", since = "1.38.0")]
736     #[must_use]
737     #[inline]
738     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
739     pub const fn from_secs_f64(secs: f64) -> Duration {
740         match Duration::try_from_secs_f64(secs) {
741             Ok(v) => v,
742             Err(e) => panic!("{}", e.description()),
743         }
744     }
745
746     /// Creates a new `Duration` from the specified number of seconds represented
747     /// as `f32`.
748     ///
749     /// # Panics
750     /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite.
751     ///
752     /// # Examples
753     /// ```
754     /// use std::time::Duration;
755     ///
756     /// let res = Duration::from_secs_f32(0.0);
757     /// assert_eq!(res, Duration::new(0, 0));
758     /// let res = Duration::from_secs_f32(1e-20);
759     /// assert_eq!(res, Duration::new(0, 0));
760     /// let res = Duration::from_secs_f32(4.2e-7);
761     /// assert_eq!(res, Duration::new(0, 420));
762     /// let res = Duration::from_secs_f32(2.7);
763     /// assert_eq!(res, Duration::new(2, 700_000_048));
764     /// let res = Duration::from_secs_f32(3e10);
765     /// assert_eq!(res, Duration::new(30_000_001_024, 0));
766     /// // subnormal float
767     /// let res = Duration::from_secs_f32(f32::from_bits(1));
768     /// assert_eq!(res, Duration::new(0, 0));
769     /// // conversion uses rounding
770     /// let res = Duration::from_secs_f32(0.999e-9);
771     /// assert_eq!(res, Duration::new(0, 1));
772     /// ```
773     #[stable(feature = "duration_float", since = "1.38.0")]
774     #[must_use]
775     #[inline]
776     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
777     pub const fn from_secs_f32(secs: f32) -> Duration {
778         match Duration::try_from_secs_f32(secs) {
779             Ok(v) => v,
780             Err(e) => panic!("{}", e.description()),
781         }
782     }
783
784     /// Multiplies `Duration` by `f64`.
785     ///
786     /// # Panics
787     /// This method will panic if result is negative, overflows `Duration` or not finite.
788     ///
789     /// # Examples
790     /// ```
791     /// use std::time::Duration;
792     ///
793     /// let dur = Duration::new(2, 700_000_000);
794     /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
795     /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
796     /// ```
797     #[stable(feature = "duration_float", since = "1.38.0")]
798     #[must_use = "this returns the result of the operation, \
799                   without modifying the original"]
800     #[inline]
801     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
802     pub const fn mul_f64(self, rhs: f64) -> Duration {
803         Duration::from_secs_f64(rhs * self.as_secs_f64())
804     }
805
806     /// Multiplies `Duration` by `f32`.
807     ///
808     /// # Panics
809     /// This method will panic if result is negative, overflows `Duration` or not finite.
810     ///
811     /// # Examples
812     /// ```
813     /// use std::time::Duration;
814     ///
815     /// let dur = Duration::new(2, 700_000_000);
816     /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
817     /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
818     /// ```
819     #[stable(feature = "duration_float", since = "1.38.0")]
820     #[must_use = "this returns the result of the operation, \
821                   without modifying the original"]
822     #[inline]
823     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
824     pub const fn mul_f32(self, rhs: f32) -> Duration {
825         Duration::from_secs_f32(rhs * self.as_secs_f32())
826     }
827
828     /// Divide `Duration` by `f64`.
829     ///
830     /// # Panics
831     /// This method will panic if result is negative, overflows `Duration` or not finite.
832     ///
833     /// # Examples
834     /// ```
835     /// use std::time::Duration;
836     ///
837     /// let dur = Duration::new(2, 700_000_000);
838     /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
839     /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
840     /// ```
841     #[stable(feature = "duration_float", since = "1.38.0")]
842     #[must_use = "this returns the result of the operation, \
843                   without modifying the original"]
844     #[inline]
845     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
846     pub const fn div_f64(self, rhs: f64) -> Duration {
847         Duration::from_secs_f64(self.as_secs_f64() / rhs)
848     }
849
850     /// Divide `Duration` by `f32`.
851     ///
852     /// # Panics
853     /// This method will panic if result is negative, overflows `Duration` or not finite.
854     ///
855     /// # Examples
856     /// ```
857     /// use std::time::Duration;
858     ///
859     /// let dur = Duration::new(2, 700_000_000);
860     /// // note that due to rounding errors result is slightly
861     /// // different from 0.859_872_611
862     /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
863     /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
864     /// ```
865     #[stable(feature = "duration_float", since = "1.38.0")]
866     #[must_use = "this returns the result of the operation, \
867                   without modifying the original"]
868     #[inline]
869     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
870     pub const fn div_f32(self, rhs: f32) -> Duration {
871         Duration::from_secs_f32(self.as_secs_f32() / rhs)
872     }
873
874     /// Divide `Duration` by `Duration` and return `f64`.
875     ///
876     /// # Examples
877     /// ```
878     /// #![feature(div_duration)]
879     /// use std::time::Duration;
880     ///
881     /// let dur1 = Duration::new(2, 700_000_000);
882     /// let dur2 = Duration::new(5, 400_000_000);
883     /// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
884     /// ```
885     #[unstable(feature = "div_duration", issue = "63139")]
886     #[must_use = "this returns the result of the operation, \
887                   without modifying the original"]
888     #[inline]
889     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
890     pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
891         self.as_secs_f64() / rhs.as_secs_f64()
892     }
893
894     /// Divide `Duration` by `Duration` and return `f32`.
895     ///
896     /// # Examples
897     /// ```
898     /// #![feature(div_duration)]
899     /// use std::time::Duration;
900     ///
901     /// let dur1 = Duration::new(2, 700_000_000);
902     /// let dur2 = Duration::new(5, 400_000_000);
903     /// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
904     /// ```
905     #[unstable(feature = "div_duration", issue = "63139")]
906     #[must_use = "this returns the result of the operation, \
907                   without modifying the original"]
908     #[inline]
909     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
910     pub const fn div_duration_f32(self, rhs: Duration) -> f32 {
911         self.as_secs_f32() / rhs.as_secs_f32()
912     }
913 }
914
915 #[stable(feature = "duration", since = "1.3.0")]
916 impl Add for Duration {
917     type Output = Duration;
918
919     fn add(self, rhs: Duration) -> Duration {
920         self.checked_add(rhs).expect("overflow when adding durations")
921     }
922 }
923
924 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
925 impl AddAssign for Duration {
926     fn add_assign(&mut self, rhs: Duration) {
927         *self = *self + rhs;
928     }
929 }
930
931 #[stable(feature = "duration", since = "1.3.0")]
932 impl Sub for Duration {
933     type Output = Duration;
934
935     fn sub(self, rhs: Duration) -> Duration {
936         self.checked_sub(rhs).expect("overflow when subtracting durations")
937     }
938 }
939
940 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
941 impl SubAssign for Duration {
942     fn sub_assign(&mut self, rhs: Duration) {
943         *self = *self - rhs;
944     }
945 }
946
947 #[stable(feature = "duration", since = "1.3.0")]
948 impl Mul<u32> for Duration {
949     type Output = Duration;
950
951     fn mul(self, rhs: u32) -> Duration {
952         self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
953     }
954 }
955
956 #[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")]
957 impl Mul<Duration> for u32 {
958     type Output = Duration;
959
960     fn mul(self, rhs: Duration) -> Duration {
961         rhs * self
962     }
963 }
964
965 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
966 impl MulAssign<u32> for Duration {
967     fn mul_assign(&mut self, rhs: u32) {
968         *self = *self * rhs;
969     }
970 }
971
972 #[stable(feature = "duration", since = "1.3.0")]
973 impl Div<u32> for Duration {
974     type Output = Duration;
975
976     fn div(self, rhs: u32) -> Duration {
977         self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
978     }
979 }
980
981 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
982 impl DivAssign<u32> for Duration {
983     fn div_assign(&mut self, rhs: u32) {
984         *self = *self / rhs;
985     }
986 }
987
988 macro_rules! sum_durations {
989     ($iter:expr) => {{
990         let mut total_secs: u64 = 0;
991         let mut total_nanos: u64 = 0;
992
993         for entry in $iter {
994             total_secs =
995                 total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations");
996             total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) {
997                 Some(n) => n,
998                 None => {
999                     total_secs = total_secs
1000                         .checked_add(total_nanos / NANOS_PER_SEC as u64)
1001                         .expect("overflow in iter::sum over durations");
1002                     (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64
1003                 }
1004             };
1005         }
1006         total_secs = total_secs
1007             .checked_add(total_nanos / NANOS_PER_SEC as u64)
1008             .expect("overflow in iter::sum over durations");
1009         total_nanos = total_nanos % NANOS_PER_SEC as u64;
1010         Duration::new(total_secs, total_nanos as u32)
1011     }};
1012 }
1013
1014 #[stable(feature = "duration_sum", since = "1.16.0")]
1015 impl Sum for Duration {
1016     fn sum<I: Iterator<Item = Duration>>(iter: I) -> Duration {
1017         sum_durations!(iter)
1018     }
1019 }
1020
1021 #[stable(feature = "duration_sum", since = "1.16.0")]
1022 impl<'a> Sum<&'a Duration> for Duration {
1023     fn sum<I: Iterator<Item = &'a Duration>>(iter: I) -> Duration {
1024         sum_durations!(iter)
1025     }
1026 }
1027
1028 #[stable(feature = "duration_debug_impl", since = "1.27.0")]
1029 impl fmt::Debug for Duration {
1030     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1031         /// Formats a floating point number in decimal notation.
1032         ///
1033         /// The number is given as the `integer_part` and a fractional part.
1034         /// The value of the fractional part is `fractional_part / divisor`. So
1035         /// `integer_part` = 3, `fractional_part` = 12 and `divisor` = 100
1036         /// represents the number `3.012`. Trailing zeros are omitted.
1037         ///
1038         /// `divisor` must not be above 100_000_000. It also should be a power
1039         /// of 10, everything else doesn't make sense. `fractional_part` has
1040         /// to be less than `10 * divisor`!
1041         ///
1042         /// A prefix and postfix may be added. The whole thing is padded
1043         /// to the formatter's `width`, if specified.
1044         fn fmt_decimal(
1045             f: &mut fmt::Formatter<'_>,
1046             integer_part: u64,
1047             mut fractional_part: u32,
1048             mut divisor: u32,
1049             prefix: &str,
1050             postfix: &str,
1051         ) -> fmt::Result {
1052             // Encode the fractional part into a temporary buffer. The buffer
1053             // only need to hold 9 elements, because `fractional_part` has to
1054             // be smaller than 10^9. The buffer is prefilled with '0' digits
1055             // to simplify the code below.
1056             let mut buf = [b'0'; 9];
1057
1058             // The next digit is written at this position
1059             let mut pos = 0;
1060
1061             // We keep writing digits into the buffer while there are non-zero
1062             // digits left and we haven't written enough digits yet.
1063             while fractional_part > 0 && pos < f.precision().unwrap_or(9) {
1064                 // Write new digit into the buffer
1065                 buf[pos] = b'0' + (fractional_part / divisor) as u8;
1066
1067                 fractional_part %= divisor;
1068                 divisor /= 10;
1069                 pos += 1;
1070             }
1071
1072             // If a precision < 9 was specified, there may be some non-zero
1073             // digits left that weren't written into the buffer. In that case we
1074             // need to perform rounding to match the semantics of printing
1075             // normal floating point numbers. However, we only need to do work
1076             // when rounding up. This happens if the first digit of the
1077             // remaining ones is >= 5.
1078             let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
1079                 // Round up the number contained in the buffer. We go through
1080                 // the buffer backwards and keep track of the carry.
1081                 let mut rev_pos = pos;
1082                 let mut carry = true;
1083                 while carry && rev_pos > 0 {
1084                     rev_pos -= 1;
1085
1086                     // If the digit in the buffer is not '9', we just need to
1087                     // increment it and can stop then (since we don't have a
1088                     // carry anymore). Otherwise, we set it to '0' (overflow)
1089                     // and continue.
1090                     if buf[rev_pos] < b'9' {
1091                         buf[rev_pos] += 1;
1092                         carry = false;
1093                     } else {
1094                         buf[rev_pos] = b'0';
1095                     }
1096                 }
1097
1098                 // If we still have the carry bit set, that means that we set
1099                 // the whole buffer to '0's and need to increment the integer
1100                 // part.
1101                 if carry {
1102                     // If `integer_part == u64::MAX` and precision < 9, any
1103                     // carry of the overflow during rounding of the
1104                     // `fractional_part` into the `integer_part` will cause the
1105                     // `integer_part` itself to overflow. Avoid this by using an
1106                     // `Option<u64>`, with `None` representing `u64::MAX + 1`.
1107                     integer_part.checked_add(1)
1108                 } else {
1109                     Some(integer_part)
1110                 }
1111             } else {
1112                 Some(integer_part)
1113             };
1114
1115             // Determine the end of the buffer: if precision is set, we just
1116             // use as many digits from the buffer (capped to 9). If it isn't
1117             // set, we only use all digits up to the last non-zero one.
1118             let end = f.precision().map(|p| crate::cmp::min(p, 9)).unwrap_or(pos);
1119
1120             // This closure emits the formatted duration without emitting any
1121             // padding (padding is calculated below).
1122             let emit_without_padding = |f: &mut fmt::Formatter<'_>| {
1123                 if let Some(integer_part) = integer_part {
1124                     write!(f, "{}{}", prefix, integer_part)?;
1125                 } else {
1126                     // u64::MAX + 1 == 18446744073709551616
1127                     write!(f, "{}18446744073709551616", prefix)?;
1128                 }
1129
1130                 // Write the decimal point and the fractional part (if any).
1131                 if end > 0 {
1132                     // SAFETY: We are only writing ASCII digits into the buffer and
1133                     // it was initialized with '0's, so it contains valid UTF8.
1134                     let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) };
1135
1136                     // If the user request a precision > 9, we pad '0's at the end.
1137                     let w = f.precision().unwrap_or(pos);
1138                     write!(f, ".{:0<width$}", s, width = w)?;
1139                 }
1140
1141                 write!(f, "{}", postfix)
1142             };
1143
1144             match f.width() {
1145                 None => {
1146                     // No `width` specified. There's no need to calculate the
1147                     // length of the output in this case, just emit it.
1148                     emit_without_padding(f)
1149                 }
1150                 Some(requested_w) => {
1151                     // A `width` was specified. Calculate the actual width of
1152                     // the output in order to calculate the required padding.
1153                     // It consists of 4 parts:
1154                     // 1. The prefix: is either "+" or "", so we can just use len().
1155                     // 2. The postfix: can be "µs" so we have to count UTF8 characters.
1156                     let mut actual_w = prefix.len() + postfix.chars().count();
1157                     // 3. The integer part:
1158                     if let Some(integer_part) = integer_part {
1159                         if let Some(log) = integer_part.checked_ilog10() {
1160                             // integer_part is > 0, so has length log10(x)+1
1161                             actual_w += 1 + log as usize;
1162                         } else {
1163                             // integer_part is 0, so has length 1.
1164                             actual_w += 1;
1165                         }
1166                     } else {
1167                         // integer_part is u64::MAX + 1, so has length 20
1168                         actual_w += 20;
1169                     }
1170                     // 4. The fractional part (if any):
1171                     if end > 0 {
1172                         let frac_part_w = f.precision().unwrap_or(pos);
1173                         actual_w += 1 + frac_part_w;
1174                     }
1175
1176                     if requested_w <= actual_w {
1177                         // Output is already longer than `width`, so don't pad.
1178                         emit_without_padding(f)
1179                     } else {
1180                         // We need to add padding. Use the `Formatter::padding` helper function.
1181                         let default_align = crate::fmt::rt::v1::Alignment::Left;
1182                         let post_padding = f.padding(requested_w - actual_w, default_align)?;
1183                         emit_without_padding(f)?;
1184                         post_padding.write(f)
1185                     }
1186                 }
1187             }
1188         }
1189
1190         // Print leading '+' sign if requested
1191         let prefix = if f.sign_plus() { "+" } else { "" };
1192
1193         if self.secs > 0 {
1194             fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s")
1195         } else if self.nanos.0 >= NANOS_PER_MILLI {
1196             fmt_decimal(
1197                 f,
1198                 (self.nanos.0 / NANOS_PER_MILLI) as u64,
1199                 self.nanos.0 % NANOS_PER_MILLI,
1200                 NANOS_PER_MILLI / 10,
1201                 prefix,
1202                 "ms",
1203             )
1204         } else if self.nanos.0 >= NANOS_PER_MICRO {
1205             fmt_decimal(
1206                 f,
1207                 (self.nanos.0 / NANOS_PER_MICRO) as u64,
1208                 self.nanos.0 % NANOS_PER_MICRO,
1209                 NANOS_PER_MICRO / 10,
1210                 prefix,
1211                 "µs",
1212             )
1213         } else {
1214             fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns")
1215         }
1216     }
1217 }
1218
1219 /// An error which can be returned when converting a floating-point value of seconds
1220 /// into a [`Duration`].
1221 ///
1222 /// This error is used as the error type for [`Duration::try_from_secs_f32`] and
1223 /// [`Duration::try_from_secs_f64`].
1224 ///
1225 /// # Example
1226 ///
1227 /// ```
1228 /// #![feature(duration_checked_float)]
1229 /// use std::time::Duration;
1230 ///
1231 /// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
1232 ///     println!("Failed conversion to Duration: {e}");
1233 /// }
1234 /// ```
1235 #[derive(Debug, Clone, PartialEq, Eq)]
1236 #[unstable(feature = "duration_checked_float", issue = "83400")]
1237 pub struct FromFloatSecsError {
1238     kind: FromFloatSecsErrorKind,
1239 }
1240
1241 impl FromFloatSecsError {
1242     const fn description(&self) -> &'static str {
1243         match self.kind {
1244             FromFloatSecsErrorKind::Negative => {
1245                 "can not convert float seconds to Duration: value is negative"
1246             }
1247             FromFloatSecsErrorKind::OverflowOrNan => {
1248                 "can not convert float seconds to Duration: value is either too big or NaN"
1249             }
1250         }
1251     }
1252 }
1253
1254 #[unstable(feature = "duration_checked_float", issue = "83400")]
1255 impl fmt::Display for FromFloatSecsError {
1256     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1257         self.description().fmt(f)
1258     }
1259 }
1260
1261 #[derive(Debug, Clone, PartialEq, Eq)]
1262 enum FromFloatSecsErrorKind {
1263     // Value is negative.
1264     Negative,
1265     // Value is either too big to be represented as `Duration` or `NaN`.
1266     OverflowOrNan,
1267 }
1268
1269 macro_rules! try_from_secs {
1270     (
1271         secs = $secs: expr,
1272         mantissa_bits = $mant_bits: literal,
1273         exponent_bits = $exp_bits: literal,
1274         offset = $offset: literal,
1275         bits_ty = $bits_ty:ty,
1276         double_ty = $double_ty:ty,
1277     ) => {{
1278         const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2;
1279         const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1;
1280         const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
1281
1282         if $secs.is_sign_negative() {
1283             return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::Negative });
1284         }
1285
1286         let bits = $secs.to_bits();
1287         let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
1288         let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP;
1289
1290         let (secs, nanos) = if exp < -31 {
1291             // the input represents less than 1ns and can not be rounded to it
1292             (0u64, 0u32)
1293         } else if exp < 0 {
1294             // the input is less than 1 second
1295             let t = <$double_ty>::from(mant) << ($offset + exp);
1296             let nanos_offset = $mant_bits + $offset;
1297             let nanos_tmp = u128::from(NANOS_PER_SEC) * u128::from(t);
1298             let nanos = (nanos_tmp >> nanos_offset) as u32;
1299
1300             let rem_mask = (1 << nanos_offset) - 1;
1301             let rem_msb_mask = 1 << (nanos_offset - 1);
1302             let rem = nanos_tmp & rem_mask;
1303             let is_tie = rem == rem_msb_mask;
1304             let is_even = (nanos & 1) == 0;
1305             let rem_msb = nanos_tmp & rem_msb_mask == 0;
1306             let add_ns = !(rem_msb || (is_even && is_tie));
1307
1308             // f32 does not have enough precision to trigger the second branch
1309             // since it can not represent numbers between 0.999_999_940_395 and 1.0.
1310             let nanos = nanos + add_ns as u32;
1311             if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { (0, nanos) } else { (1, 0) }
1312         } else if exp < $mant_bits {
1313             let secs = u64::from(mant >> ($mant_bits - exp));
1314             let t = <$double_ty>::from((mant << exp) & MANT_MASK);
1315             let nanos_offset = $mant_bits;
1316             let nanos_tmp = <$double_ty>::from(NANOS_PER_SEC) * t;
1317             let nanos = (nanos_tmp >> nanos_offset) as u32;
1318
1319             let rem_mask = (1 << nanos_offset) - 1;
1320             let rem_msb_mask = 1 << (nanos_offset - 1);
1321             let rem = nanos_tmp & rem_mask;
1322             let is_tie = rem == rem_msb_mask;
1323             let is_even = (nanos & 1) == 0;
1324             let rem_msb = nanos_tmp & rem_msb_mask == 0;
1325             let add_ns = !(rem_msb || (is_even && is_tie));
1326
1327             // f32 does not have enough precision to trigger the second branch.
1328             // For example, it can not represent numbers between 1.999_999_880...
1329             // and 2.0. Bigger values result in even smaller precision of the
1330             // fractional part.
1331             let nanos = nanos + add_ns as u32;
1332             if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) {
1333                 (secs, nanos)
1334             } else {
1335                 (secs + 1, 0)
1336             }
1337         } else if exp < 64 {
1338             // the input has no fractional part
1339             let secs = u64::from(mant) << (exp - $mant_bits);
1340             (secs, 0)
1341         } else {
1342             return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::OverflowOrNan });
1343         };
1344
1345         Ok(Duration::new(secs, nanos))
1346     }};
1347 }
1348
1349 impl Duration {
1350     /// The checked version of [`from_secs_f32`].
1351     ///
1352     /// [`from_secs_f32`]: Duration::from_secs_f32
1353     ///
1354     /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite.
1355     ///
1356     /// # Examples
1357     /// ```
1358     /// #![feature(duration_checked_float)]
1359     ///
1360     /// use std::time::Duration;
1361     ///
1362     /// let res = Duration::try_from_secs_f32(0.0);
1363     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1364     /// let res = Duration::try_from_secs_f32(1e-20);
1365     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1366     /// let res = Duration::try_from_secs_f32(4.2e-7);
1367     /// assert_eq!(res, Ok(Duration::new(0, 420)));
1368     /// let res = Duration::try_from_secs_f32(2.7);
1369     /// assert_eq!(res, Ok(Duration::new(2, 700_000_048)));
1370     /// let res = Duration::try_from_secs_f32(3e10);
1371     /// assert_eq!(res, Ok(Duration::new(30_000_001_024, 0)));
1372     /// // subnormal float:
1373     /// let res = Duration::try_from_secs_f32(f32::from_bits(1));
1374     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1375     ///
1376     /// let res = Duration::try_from_secs_f32(-5.0);
1377     /// assert!(res.is_err());
1378     /// let res = Duration::try_from_secs_f32(f32::NAN);
1379     /// assert!(res.is_err());
1380     /// let res = Duration::try_from_secs_f32(2e19);
1381     /// assert!(res.is_err());
1382     ///
1383     /// // the conversion uses rounding with tie resolution to even
1384     /// let res = Duration::try_from_secs_f32(0.999e-9);
1385     /// assert_eq!(res, Ok(Duration::new(0, 1)));
1386     ///
1387     /// // this float represents exactly 976562.5e-9
1388     /// let val = f32::from_bits(0x3A80_0000);
1389     /// let res = Duration::try_from_secs_f32(val);
1390     /// assert_eq!(res, Ok(Duration::new(0, 976_562)));
1391     ///
1392     /// // this float represents exactly 2929687.5e-9
1393     /// let val = f32::from_bits(0x3B40_0000);
1394     /// let res = Duration::try_from_secs_f32(val);
1395     /// assert_eq!(res, Ok(Duration::new(0, 2_929_688)));
1396     ///
1397     /// // this float represents exactly 1.000_976_562_5
1398     /// let val = f32::from_bits(0x3F802000);
1399     /// let res = Duration::try_from_secs_f32(val);
1400     /// assert_eq!(res, Ok(Duration::new(1, 976_562)));
1401     ///
1402     /// // this float represents exactly 1.002_929_687_5
1403     /// let val = f32::from_bits(0x3F806000);
1404     /// let res = Duration::try_from_secs_f32(val);
1405     /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
1406     /// ```
1407     #[unstable(feature = "duration_checked_float", issue = "83400")]
1408     #[inline]
1409     pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromFloatSecsError> {
1410         try_from_secs!(
1411             secs = secs,
1412             mantissa_bits = 23,
1413             exponent_bits = 8,
1414             offset = 41,
1415             bits_ty = u32,
1416             double_ty = u64,
1417         )
1418     }
1419
1420     /// The checked version of [`from_secs_f64`].
1421     ///
1422     /// [`from_secs_f64`]: Duration::from_secs_f64
1423     ///
1424     /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite.
1425     ///
1426     /// # Examples
1427     /// ```
1428     /// #![feature(duration_checked_float)]
1429     ///
1430     /// use std::time::Duration;
1431     ///
1432     /// let res = Duration::try_from_secs_f64(0.0);
1433     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1434     /// let res = Duration::try_from_secs_f64(1e-20);
1435     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1436     /// let res = Duration::try_from_secs_f64(4.2e-7);
1437     /// assert_eq!(res, Ok(Duration::new(0, 420)));
1438     /// let res = Duration::try_from_secs_f64(2.7);
1439     /// assert_eq!(res, Ok(Duration::new(2, 700_000_000)));
1440     /// let res = Duration::try_from_secs_f64(3e10);
1441     /// assert_eq!(res, Ok(Duration::new(30_000_000_000, 0)));
1442     /// // subnormal float
1443     /// let res = Duration::try_from_secs_f64(f64::from_bits(1));
1444     /// assert_eq!(res, Ok(Duration::new(0, 0)));
1445     ///
1446     /// let res = Duration::try_from_secs_f64(-5.0);
1447     /// assert!(res.is_err());
1448     /// let res = Duration::try_from_secs_f64(f64::NAN);
1449     /// assert!(res.is_err());
1450     /// let res = Duration::try_from_secs_f64(2e19);
1451     /// assert!(res.is_err());
1452     ///
1453     /// // the conversion uses rounding with tie resolution to even
1454     /// let res = Duration::try_from_secs_f64(0.999e-9);
1455     /// assert_eq!(res, Ok(Duration::new(0, 1)));
1456     /// let res = Duration::try_from_secs_f64(0.999_999_999_499);
1457     /// assert_eq!(res, Ok(Duration::new(0, 999_999_999)));
1458     /// let res = Duration::try_from_secs_f64(0.999_999_999_501);
1459     /// assert_eq!(res, Ok(Duration::new(1, 0)));
1460     /// let res = Duration::try_from_secs_f64(42.999_999_999_499);
1461     /// assert_eq!(res, Ok(Duration::new(42, 999_999_999)));
1462     /// let res = Duration::try_from_secs_f64(42.999_999_999_501);
1463     /// assert_eq!(res, Ok(Duration::new(43, 0)));
1464     ///
1465     /// // this float represents exactly 976562.5e-9
1466     /// let val = f64::from_bits(0x3F50_0000_0000_0000);
1467     /// let res = Duration::try_from_secs_f64(val);
1468     /// assert_eq!(res, Ok(Duration::new(0, 976_562)));
1469     ///
1470     /// // this float represents exactly 2929687.5e-9
1471     /// let val = f64::from_bits(0x3F68_0000_0000_0000);
1472     /// let res = Duration::try_from_secs_f64(val);
1473     /// assert_eq!(res, Ok(Duration::new(0, 2_929_688)));
1474     ///
1475     /// // this float represents exactly 1.000_976_562_5
1476     /// let val = f64::from_bits(0x3FF0_0400_0000_0000);
1477     /// let res = Duration::try_from_secs_f64(val);
1478     /// assert_eq!(res, Ok(Duration::new(1, 976_562)));
1479     ///
1480     /// // this float represents exactly 1.002_929_687_5
1481     /// let val = f64::from_bits(0x3_FF00_C000_0000_000);
1482     /// let res = Duration::try_from_secs_f64(val);
1483     /// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
1484     /// ```
1485     #[unstable(feature = "duration_checked_float", issue = "83400")]
1486     #[inline]
1487     pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromFloatSecsError> {
1488         try_from_secs!(
1489             secs = secs,
1490             mantissa_bits = 52,
1491             exponent_bits = 11,
1492             offset = 44,
1493             bits_ty = u64,
1494             double_ty = u128,
1495         )
1496     }
1497 }