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