time/
duration.rs

1//! The [`Duration`] struct and its associated `impl`s.
2
3use core::cmp::Ordering;
4use core::fmt;
5use core::iter::Sum;
6use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
7use core::time::Duration as StdDuration;
8#[cfg(feature = "std")]
9use std::time::SystemTime;
10
11use deranged::RangedI32;
12use num_conv::prelude::*;
13
14use crate::convert::*;
15use crate::error;
16use crate::internal_macros::{
17    const_try_opt, expect_opt, impl_add_assign, impl_div_assign, impl_mul_assign, impl_sub_assign,
18};
19#[cfg(feature = "std")]
20#[allow(deprecated)]
21use crate::Instant;
22
23/// By explicitly inserting this enum where padding is expected, the compiler is able to better
24/// perform niche value optimization.
25#[repr(u32)]
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
27pub(crate) enum Padding {
28    #[allow(clippy::missing_docs_in_private_items)]
29    Optimize,
30}
31
32/// The type of the `nanosecond` field of `Duration`.
33type Nanoseconds =
34    RangedI32<{ -(Nanosecond::per(Second) as i32 - 1) }, { Nanosecond::per(Second) as i32 - 1 }>;
35
36/// A span of time with nanosecond precision.
37///
38/// Each `Duration` is composed of a whole number of seconds and a fractional part represented in
39/// nanoseconds.
40///
41/// This implementation allows for negative durations, unlike [`core::time::Duration`].
42#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
43pub struct Duration {
44    /// Number of whole seconds.
45    seconds: i64,
46    /// Number of nanoseconds within the second. The sign always matches the `seconds` field.
47    // Sign must match that of `seconds` (though this is not a safety requirement).
48    nanoseconds: Nanoseconds,
49    padding: Padding,
50}
51
52impl fmt::Debug for Duration {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        f.debug_struct("Duration")
55            .field("seconds", &self.seconds)
56            .field("nanoseconds", &self.nanoseconds)
57            .finish()
58    }
59}
60
61impl Default for Duration {
62    fn default() -> Self {
63        Self {
64            seconds: 0,
65            nanoseconds: Nanoseconds::new_static::<0>(),
66            padding: Padding::Optimize,
67        }
68    }
69}
70
71/// This is adapted from the [`std` implementation][std], which uses mostly bit
72/// operations to ensure the highest precision:
73///
74/// Changes from `std` are marked and explained below.
75///
76/// [std]: https://github.com/rust-lang/rust/blob/3a37c2f0523c87147b64f1b8099fc9df22e8c53e/library/core/src/time.rs#L1262-L1340
77#[rustfmt::skip] // Skip `rustfmt` because it reformats the arguments of the macro weirdly.
78macro_rules! try_from_secs {
79    (
80        secs = $secs: expr,
81        mantissa_bits = $mant_bits: literal,
82        exponent_bits = $exp_bits: literal,
83        offset = $offset: literal,
84        bits_ty = $bits_ty:ty,
85        bits_ty_signed = $bits_ty_signed:ty,
86        double_ty = $double_ty:ty,
87        float_ty = $float_ty:ty,
88        is_nan = $is_nan:expr,
89        is_overflow = $is_overflow:expr,
90    ) => {{
91        'value: {
92            const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2;
93            const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1;
94            const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
95
96            // Change from std: No error check for negative values necessary.
97
98            let bits = $secs.to_bits();
99            let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
100            let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP;
101
102            let (secs, nanos) = if exp < -31 {
103                // the input represents less than 1ns and can not be rounded to it
104                (0u64, 0u32)
105            } else if exp < 0 {
106                // the input is less than 1 second
107                let t = <$double_ty>::from(mant) << ($offset + exp);
108                let nanos_offset = $mant_bits + $offset;
109                let nanos_tmp = u128::from(Nanosecond::per(Second)) * u128::from(t);
110                let nanos = (nanos_tmp >> nanos_offset) as u32;
111
112                let rem_mask = (1 << nanos_offset) - 1;
113                let rem_msb_mask = 1 << (nanos_offset - 1);
114                let rem = nanos_tmp & rem_mask;
115                let is_tie = rem == rem_msb_mask;
116                let is_even = (nanos & 1) == 0;
117                let rem_msb = nanos_tmp & rem_msb_mask == 0;
118                let add_ns = !(rem_msb || (is_even && is_tie));
119
120                // f32 does not have enough precision to trigger the second branch
121                // since it can not represent numbers between 0.999_999_940_395 and 1.0.
122                let nanos = nanos + add_ns as u32;
123                if ($mant_bits == 23) || (nanos != Nanosecond::per(Second)) {
124                    (0, nanos)
125                } else {
126                    (1, 0)
127                }
128            } else if exp < $mant_bits {
129                let secs = u64::from(mant >> ($mant_bits - exp));
130                let t = <$double_ty>::from((mant << exp) & MANT_MASK);
131                let nanos_offset = $mant_bits;
132                let nanos_tmp = <$double_ty>::from(Nanosecond::per(Second)) * t;
133                let nanos = (nanos_tmp >> nanos_offset) as u32;
134
135                let rem_mask = (1 << nanos_offset) - 1;
136                let rem_msb_mask = 1 << (nanos_offset - 1);
137                let rem = nanos_tmp & rem_mask;
138                let is_tie = rem == rem_msb_mask;
139                let is_even = (nanos & 1) == 0;
140                let rem_msb = nanos_tmp & rem_msb_mask == 0;
141                let add_ns = !(rem_msb || (is_even && is_tie));
142
143                // f32 does not have enough precision to trigger the second branch.
144                // For example, it can not represent numbers between 1.999_999_880...
145                // and 2.0. Bigger values result in even smaller precision of the
146                // fractional part.
147                let nanos = nanos + add_ns as u32;
148                if ($mant_bits == 23) || (nanos != Nanosecond::per(Second)) {
149                    (secs, nanos)
150                } else {
151                    (secs + 1, 0)
152                }
153            } else if exp < 63 {
154                // Change from std: The exponent here is 63 instead of 64,
155                // because i64::MAX + 1 is 2^63.
156
157                // the input has no fractional part
158                let secs = u64::from(mant) << (exp - $mant_bits);
159                (secs, 0)
160            } else if bits == (i64::MIN as $float_ty).to_bits() {
161                // Change from std: Signed integers are asymmetrical in that
162                // iN::MIN is -iN::MAX - 1. So for example i8 covers the
163                // following numbers -128..=127. The check above (exp < 63)
164                // doesn't cover i64::MIN as that is -2^63, so we have this
165                // additional case to handle the asymmetry of iN::MIN.
166                break 'value Self::new_ranged_unchecked(i64::MIN, Nanoseconds::new_static::<0>());
167            } else if $secs.is_nan() {
168                // Change from std: std doesn't differentiate between the error
169                // cases.
170                $is_nan
171            } else {
172                $is_overflow
173            };
174
175            // Change from std: All the code is mostly unmodified in that it
176            // simply calculates an unsigned integer. Here we extract the sign
177            // bit and assign it to the number. We basically manually do two's
178            // complement here, we could also use an if and just negate the
179            // numbers based on the sign, but it turns out to be quite a bit
180            // slower.
181            let mask = (bits as $bits_ty_signed) >> ($mant_bits + $exp_bits);
182            #[allow(trivial_numeric_casts)]
183            let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
184            #[allow(trivial_numeric_casts)]
185            let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
186            // Safety: `nanos_signed` is in range.
187            unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
188        }
189    }};
190}
191
192impl Duration {
193    /// Equivalent to `0.seconds()`.
194    ///
195    /// ```rust
196    /// # use time::{Duration, ext::NumericalDuration};
197    /// assert_eq!(Duration::ZERO, 0.seconds());
198    /// ```
199    pub const ZERO: Self = Self::seconds(0);
200
201    /// Equivalent to `1.nanoseconds()`.
202    ///
203    /// ```rust
204    /// # use time::{Duration, ext::NumericalDuration};
205    /// assert_eq!(Duration::NANOSECOND, 1.nanoseconds());
206    /// ```
207    pub const NANOSECOND: Self = Self::nanoseconds(1);
208
209    /// Equivalent to `1.microseconds()`.
210    ///
211    /// ```rust
212    /// # use time::{Duration, ext::NumericalDuration};
213    /// assert_eq!(Duration::MICROSECOND, 1.microseconds());
214    /// ```
215    pub const MICROSECOND: Self = Self::microseconds(1);
216
217    /// Equivalent to `1.milliseconds()`.
218    ///
219    /// ```rust
220    /// # use time::{Duration, ext::NumericalDuration};
221    /// assert_eq!(Duration::MILLISECOND, 1.milliseconds());
222    /// ```
223    pub const MILLISECOND: Self = Self::milliseconds(1);
224
225    /// Equivalent to `1.seconds()`.
226    ///
227    /// ```rust
228    /// # use time::{Duration, ext::NumericalDuration};
229    /// assert_eq!(Duration::SECOND, 1.seconds());
230    /// ```
231    pub const SECOND: Self = Self::seconds(1);
232
233    /// Equivalent to `1.minutes()`.
234    ///
235    /// ```rust
236    /// # use time::{Duration, ext::NumericalDuration};
237    /// assert_eq!(Duration::MINUTE, 1.minutes());
238    /// ```
239    pub const MINUTE: Self = Self::minutes(1);
240
241    /// Equivalent to `1.hours()`.
242    ///
243    /// ```rust
244    /// # use time::{Duration, ext::NumericalDuration};
245    /// assert_eq!(Duration::HOUR, 1.hours());
246    /// ```
247    pub const HOUR: Self = Self::hours(1);
248
249    /// Equivalent to `1.days()`.
250    ///
251    /// ```rust
252    /// # use time::{Duration, ext::NumericalDuration};
253    /// assert_eq!(Duration::DAY, 1.days());
254    /// ```
255    pub const DAY: Self = Self::days(1);
256
257    /// Equivalent to `1.weeks()`.
258    ///
259    /// ```rust
260    /// # use time::{Duration, ext::NumericalDuration};
261    /// assert_eq!(Duration::WEEK, 1.weeks());
262    /// ```
263    pub const WEEK: Self = Self::weeks(1);
264
265    /// The minimum possible duration. Adding any negative duration to this will cause an overflow.
266    pub const MIN: Self = Self::new_ranged(i64::MIN, Nanoseconds::MIN);
267
268    /// The maximum possible duration. Adding any positive duration to this will cause an overflow.
269    pub const MAX: Self = Self::new_ranged(i64::MAX, Nanoseconds::MAX);
270
271    /// Check if a duration is exactly zero.
272    ///
273    /// ```rust
274    /// # use time::ext::NumericalDuration;
275    /// assert!(0.seconds().is_zero());
276    /// assert!(!1.nanoseconds().is_zero());
277    /// ```
278    pub const fn is_zero(self) -> bool {
279        self.seconds == 0 && self.nanoseconds.get() == 0
280    }
281
282    /// Check if a duration is negative.
283    ///
284    /// ```rust
285    /// # use time::ext::NumericalDuration;
286    /// assert!((-1).seconds().is_negative());
287    /// assert!(!0.seconds().is_negative());
288    /// assert!(!1.seconds().is_negative());
289    /// ```
290    pub const fn is_negative(self) -> bool {
291        self.seconds < 0 || self.nanoseconds.get() < 0
292    }
293
294    /// Check if a duration is positive.
295    ///
296    /// ```rust
297    /// # use time::ext::NumericalDuration;
298    /// assert!(1.seconds().is_positive());
299    /// assert!(!0.seconds().is_positive());
300    /// assert!(!(-1).seconds().is_positive());
301    /// ```
302    pub const fn is_positive(self) -> bool {
303        self.seconds > 0 || self.nanoseconds.get() > 0
304    }
305
306    /// Get the absolute value of the duration.
307    ///
308    /// This method saturates the returned value if it would otherwise overflow.
309    ///
310    /// ```rust
311    /// # use time::ext::NumericalDuration;
312    /// assert_eq!(1.seconds().abs(), 1.seconds());
313    /// assert_eq!(0.seconds().abs(), 0.seconds());
314    /// assert_eq!((-1).seconds().abs(), 1.seconds());
315    /// ```
316    pub const fn abs(self) -> Self {
317        match self.seconds.checked_abs() {
318            Some(seconds) => Self::new_ranged_unchecked(seconds, self.nanoseconds.abs()),
319            None => Self::MAX,
320        }
321    }
322
323    /// Convert the existing `Duration` to a `std::time::Duration` and its sign. This returns a
324    /// [`std::time::Duration`] and does not saturate the returned value (unlike [`Duration::abs`]).
325    ///
326    /// ```rust
327    /// # use time::ext::{NumericalDuration, NumericalStdDuration};
328    /// assert_eq!(1.seconds().unsigned_abs(), 1.std_seconds());
329    /// assert_eq!(0.seconds().unsigned_abs(), 0.std_seconds());
330    /// assert_eq!((-1).seconds().unsigned_abs(), 1.std_seconds());
331    /// ```
332    pub const fn unsigned_abs(self) -> StdDuration {
333        StdDuration::new(
334            self.seconds.unsigned_abs(),
335            self.nanoseconds.get().unsigned_abs(),
336        )
337    }
338
339    /// Create a new `Duration` without checking the validity of the components.
340    ///
341    /// # Safety
342    ///
343    /// - `nanoseconds` must be in the range `-999_999_999..=999_999_999`.
344    ///
345    /// While the sign of `nanoseconds` is required to be the same as the sign of `seconds`, this is
346    /// not a safety invariant.
347    pub(crate) const unsafe fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
348        Self::new_ranged_unchecked(
349            seconds,
350            // Safety: The caller must uphold the safety invariants.
351            unsafe { Nanoseconds::new_unchecked(nanoseconds) },
352        )
353    }
354
355    /// Create a new `Duration` without checking the validity of the components.
356    pub(crate) const fn new_ranged_unchecked(seconds: i64, nanoseconds: Nanoseconds) -> Self {
357        if seconds < 0 {
358            debug_assert!(nanoseconds.get() <= 0);
359        } else if seconds > 0 {
360            debug_assert!(nanoseconds.get() >= 0);
361        }
362
363        Self {
364            seconds,
365            nanoseconds,
366            padding: Padding::Optimize,
367        }
368    }
369
370    /// Create a new `Duration` with the provided seconds and nanoseconds. If nanoseconds is at
371    /// least ±10<sup>9</sup>, it will wrap to the number of seconds.
372    ///
373    /// ```rust
374    /// # use time::{Duration, ext::NumericalDuration};
375    /// assert_eq!(Duration::new(1, 0), 1.seconds());
376    /// assert_eq!(Duration::new(-1, 0), (-1).seconds());
377    /// assert_eq!(Duration::new(1, 2_000_000_000), 3.seconds());
378    /// ```
379    ///
380    /// # Panics
381    ///
382    /// This may panic if an overflow occurs.
383    pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
384        seconds = expect_opt!(
385            seconds.checked_add(nanoseconds as i64 / Nanosecond::per(Second) as i64),
386            "overflow constructing `time::Duration`"
387        );
388        nanoseconds %= Nanosecond::per(Second) as i32;
389
390        if seconds > 0 && nanoseconds < 0 {
391            // `seconds` cannot overflow here because it is positive.
392            seconds -= 1;
393            nanoseconds += Nanosecond::per(Second) as i32;
394        } else if seconds < 0 && nanoseconds > 0 {
395            // `seconds` cannot overflow here because it is negative.
396            seconds += 1;
397            nanoseconds -= Nanosecond::per(Second) as i32;
398        }
399
400        // Safety: `nanoseconds` is in range due to the modulus above.
401        unsafe { Self::new_unchecked(seconds, nanoseconds) }
402    }
403
404    /// Create a new `Duration` with the provided seconds and nanoseconds.
405    pub(crate) const fn new_ranged(mut seconds: i64, mut nanoseconds: Nanoseconds) -> Self {
406        if seconds > 0 && nanoseconds.get() < 0 {
407            // `seconds` cannot overflow here because it is positive.
408            seconds -= 1;
409            // Safety: `nanoseconds` is negative with a maximum of 999,999,999, so adding a billion
410            // to it is guaranteed to result in an in-range value.
411            nanoseconds = unsafe {
412                Nanoseconds::new_unchecked(nanoseconds.get() + Nanosecond::per(Second) as i32)
413            };
414        } else if seconds < 0 && nanoseconds.get() > 0 {
415            // `seconds` cannot overflow here because it is negative.
416            seconds += 1;
417            // Safety: `nanoseconds` is positive with a minimum of -999,999,999, so subtracting a
418            // billion from it is guaranteed to result in an in-range value.
419            nanoseconds = unsafe {
420                Nanoseconds::new_unchecked(nanoseconds.get() - Nanosecond::per(Second) as i32)
421            };
422        }
423
424        Self::new_ranged_unchecked(seconds, nanoseconds)
425    }
426
427    /// Create a new `Duration` with the given number of weeks. Equivalent to
428    /// `Duration::seconds(weeks * 604_800)`.
429    ///
430    /// ```rust
431    /// # use time::{Duration, ext::NumericalDuration};
432    /// assert_eq!(Duration::weeks(1), 604_800.seconds());
433    /// ```
434    ///
435    /// # Panics
436    ///
437    /// This may panic if an overflow occurs.
438    pub const fn weeks(weeks: i64) -> Self {
439        Self::seconds(expect_opt!(
440            weeks.checked_mul(Second::per(Week) as i64),
441            "overflow constructing `time::Duration`"
442        ))
443    }
444
445    /// Create a new `Duration` with the given number of days. Equivalent to
446    /// `Duration::seconds(days * 86_400)`.
447    ///
448    /// ```rust
449    /// # use time::{Duration, ext::NumericalDuration};
450    /// assert_eq!(Duration::days(1), 86_400.seconds());
451    /// ```
452    ///
453    /// # Panics
454    ///
455    /// This may panic if an overflow occurs.
456    pub const fn days(days: i64) -> Self {
457        Self::seconds(expect_opt!(
458            days.checked_mul(Second::per(Day) as i64),
459            "overflow constructing `time::Duration`"
460        ))
461    }
462
463    /// Create a new `Duration` with the given number of hours. Equivalent to
464    /// `Duration::seconds(hours * 3_600)`.
465    ///
466    /// ```rust
467    /// # use time::{Duration, ext::NumericalDuration};
468    /// assert_eq!(Duration::hours(1), 3_600.seconds());
469    /// ```
470    ///
471    /// # Panics
472    ///
473    /// This may panic if an overflow occurs.
474    pub const fn hours(hours: i64) -> Self {
475        Self::seconds(expect_opt!(
476            hours.checked_mul(Second::per(Hour) as i64),
477            "overflow constructing `time::Duration`"
478        ))
479    }
480
481    /// Create a new `Duration` with the given number of minutes. Equivalent to
482    /// `Duration::seconds(minutes * 60)`.
483    ///
484    /// ```rust
485    /// # use time::{Duration, ext::NumericalDuration};
486    /// assert_eq!(Duration::minutes(1), 60.seconds());
487    /// ```
488    ///
489    /// # Panics
490    ///
491    /// This may panic if an overflow occurs.
492    pub const fn minutes(minutes: i64) -> Self {
493        Self::seconds(expect_opt!(
494            minutes.checked_mul(Second::per(Minute) as i64),
495            "overflow constructing `time::Duration`"
496        ))
497    }
498
499    /// Create a new `Duration` with the given number of seconds.
500    ///
501    /// ```rust
502    /// # use time::{Duration, ext::NumericalDuration};
503    /// assert_eq!(Duration::seconds(1), 1_000.milliseconds());
504    /// ```
505    pub const fn seconds(seconds: i64) -> Self {
506        Self::new_ranged_unchecked(seconds, Nanoseconds::new_static::<0>())
507    }
508
509    /// Creates a new `Duration` from the specified number of seconds represented as `f64`.
510    ///
511    /// ```rust
512    /// # use time::{Duration, ext::NumericalDuration};
513    /// assert_eq!(Duration::seconds_f64(0.5), 0.5.seconds());
514    /// assert_eq!(Duration::seconds_f64(-0.5), (-0.5).seconds());
515    /// ```
516    pub fn seconds_f64(seconds: f64) -> Self {
517        try_from_secs!(
518            secs = seconds,
519            mantissa_bits = 52,
520            exponent_bits = 11,
521            offset = 44,
522            bits_ty = u64,
523            bits_ty_signed = i64,
524            double_ty = u128,
525            float_ty = f64,
526            is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f64`"),
527            is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
528        )
529    }
530
531    /// Creates a new `Duration` from the specified number of seconds represented as `f32`.
532    ///
533    /// ```rust
534    /// # use time::{Duration, ext::NumericalDuration};
535    /// assert_eq!(Duration::seconds_f32(0.5), 0.5.seconds());
536    /// assert_eq!(Duration::seconds_f32(-0.5), (-0.5).seconds());
537    /// ```
538    pub fn seconds_f32(seconds: f32) -> Self {
539        try_from_secs!(
540            secs = seconds,
541            mantissa_bits = 23,
542            exponent_bits = 8,
543            offset = 41,
544            bits_ty = u32,
545            bits_ty_signed = i32,
546            double_ty = u64,
547            float_ty = f32,
548            is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f32`"),
549            is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
550        )
551    }
552
553    /// Creates a new `Duration` from the specified number of seconds
554    /// represented as `f64`. Any values that are out of bounds are saturated at
555    /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
556    /// of 0 seconds.
557    ///
558    /// ```rust
559    /// # use time::{Duration, ext::NumericalDuration};
560    /// assert_eq!(Duration::saturating_seconds_f64(0.5), 0.5.seconds());
561    /// assert_eq!(Duration::saturating_seconds_f64(-0.5), (-0.5).seconds());
562    /// assert_eq!(
563    ///     Duration::saturating_seconds_f64(f64::NAN),
564    ///     Duration::new(0, 0),
565    /// );
566    /// assert_eq!(
567    ///     Duration::saturating_seconds_f64(f64::NEG_INFINITY),
568    ///     Duration::MIN,
569    /// );
570    /// assert_eq!(
571    ///     Duration::saturating_seconds_f64(f64::INFINITY),
572    ///     Duration::MAX,
573    /// );
574    /// ```
575    pub fn saturating_seconds_f64(seconds: f64) -> Self {
576        try_from_secs!(
577            secs = seconds,
578            mantissa_bits = 52,
579            exponent_bits = 11,
580            offset = 44,
581            bits_ty = u64,
582            bits_ty_signed = i64,
583            double_ty = u128,
584            float_ty = f64,
585            is_nan = return Self::ZERO,
586            is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
587        )
588    }
589
590    /// Creates a new `Duration` from the specified number of seconds
591    /// represented as `f32`. Any values that are out of bounds are saturated at
592    /// the minimum or maximum respectively. `NaN` gets turned into a `Duration`
593    /// of 0 seconds.
594    ///
595    /// ```rust
596    /// # use time::{Duration, ext::NumericalDuration};
597    /// assert_eq!(Duration::saturating_seconds_f32(0.5), 0.5.seconds());
598    /// assert_eq!(Duration::saturating_seconds_f32(-0.5), (-0.5).seconds());
599    /// assert_eq!(
600    ///     Duration::saturating_seconds_f32(f32::NAN),
601    ///     Duration::new(0, 0),
602    /// );
603    /// assert_eq!(
604    ///     Duration::saturating_seconds_f32(f32::NEG_INFINITY),
605    ///     Duration::MIN,
606    /// );
607    /// assert_eq!(
608    ///     Duration::saturating_seconds_f32(f32::INFINITY),
609    ///     Duration::MAX,
610    /// );
611    /// ```
612    pub fn saturating_seconds_f32(seconds: f32) -> Self {
613        try_from_secs!(
614            secs = seconds,
615            mantissa_bits = 23,
616            exponent_bits = 8,
617            offset = 41,
618            bits_ty = u32,
619            bits_ty_signed = i32,
620            double_ty = u64,
621            float_ty = f32,
622            is_nan = return Self::ZERO,
623            is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
624        )
625    }
626
627    /// Creates a new `Duration` from the specified number of seconds
628    /// represented as `f64`. Returns `None` if the `Duration` can't be
629    /// represented.
630    ///
631    /// ```rust
632    /// # use time::{Duration, ext::NumericalDuration};
633    /// assert_eq!(Duration::checked_seconds_f64(0.5), Some(0.5.seconds()));
634    /// assert_eq!(Duration::checked_seconds_f64(-0.5), Some((-0.5).seconds()));
635    /// assert_eq!(Duration::checked_seconds_f64(f64::NAN), None);
636    /// assert_eq!(Duration::checked_seconds_f64(f64::NEG_INFINITY), None);
637    /// assert_eq!(Duration::checked_seconds_f64(f64::INFINITY), None);
638    /// ```
639    pub fn checked_seconds_f64(seconds: f64) -> Option<Self> {
640        Some(try_from_secs!(
641            secs = seconds,
642            mantissa_bits = 52,
643            exponent_bits = 11,
644            offset = 44,
645            bits_ty = u64,
646            bits_ty_signed = i64,
647            double_ty = u128,
648            float_ty = f64,
649            is_nan = return None,
650            is_overflow = return None,
651        ))
652    }
653
654    /// Creates a new `Duration` from the specified number of seconds
655    /// represented as `f32`. Returns `None` if the `Duration` can't be
656    /// represented.
657    ///
658    /// ```rust
659    /// # use time::{Duration, ext::NumericalDuration};
660    /// assert_eq!(Duration::checked_seconds_f32(0.5), Some(0.5.seconds()));
661    /// assert_eq!(Duration::checked_seconds_f32(-0.5), Some((-0.5).seconds()));
662    /// assert_eq!(Duration::checked_seconds_f32(f32::NAN), None);
663    /// assert_eq!(Duration::checked_seconds_f32(f32::NEG_INFINITY), None);
664    /// assert_eq!(Duration::checked_seconds_f32(f32::INFINITY), None);
665    /// ```
666    pub fn checked_seconds_f32(seconds: f32) -> Option<Self> {
667        Some(try_from_secs!(
668            secs = seconds,
669            mantissa_bits = 23,
670            exponent_bits = 8,
671            offset = 41,
672            bits_ty = u32,
673            bits_ty_signed = i32,
674            double_ty = u64,
675            float_ty = f32,
676            is_nan = return None,
677            is_overflow = return None,
678        ))
679    }
680
681    /// Create a new `Duration` with the given number of milliseconds.
682    ///
683    /// ```rust
684    /// # use time::{Duration, ext::NumericalDuration};
685    /// assert_eq!(Duration::milliseconds(1), 1_000.microseconds());
686    /// assert_eq!(Duration::milliseconds(-1), (-1_000).microseconds());
687    /// ```
688    pub const fn milliseconds(milliseconds: i64) -> Self {
689        // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
690        unsafe {
691            Self::new_unchecked(
692                milliseconds / Millisecond::per(Second) as i64,
693                (milliseconds % Millisecond::per(Second) as i64
694                    * Nanosecond::per(Millisecond) as i64) as i32,
695            )
696        }
697    }
698
699    /// Create a new `Duration` with the given number of microseconds.
700    ///
701    /// ```rust
702    /// # use time::{Duration, ext::NumericalDuration};
703    /// assert_eq!(Duration::microseconds(1), 1_000.nanoseconds());
704    /// assert_eq!(Duration::microseconds(-1), (-1_000).nanoseconds());
705    /// ```
706    pub const fn microseconds(microseconds: i64) -> Self {
707        // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
708        unsafe {
709            Self::new_unchecked(
710                microseconds / Microsecond::per(Second) as i64,
711                (microseconds % Microsecond::per(Second) as i64
712                    * Nanosecond::per(Microsecond) as i64) as i32,
713            )
714        }
715    }
716
717    /// Create a new `Duration` with the given number of nanoseconds.
718    ///
719    /// ```rust
720    /// # use time::{Duration, ext::NumericalDuration};
721    /// assert_eq!(Duration::nanoseconds(1), 1.microseconds() / 1_000);
722    /// assert_eq!(Duration::nanoseconds(-1), (-1).microseconds() / 1_000);
723    /// ```
724    pub const fn nanoseconds(nanoseconds: i64) -> Self {
725        // Safety: `nanoseconds` is guaranteed to be in range because of the modulus.
726        unsafe {
727            Self::new_unchecked(
728                nanoseconds / Nanosecond::per(Second) as i64,
729                (nanoseconds % Nanosecond::per(Second) as i64) as i32,
730            )
731        }
732    }
733
734    /// Create a new `Duration` with the given number of nanoseconds.
735    ///
736    /// As the input range cannot be fully mapped to the output, this should only be used where it's
737    /// known to result in a valid value.
738    pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
739        let seconds = nanoseconds / Nanosecond::per(Second) as i128;
740        let nanoseconds = nanoseconds % Nanosecond::per(Second) as i128;
741
742        if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
743            crate::expect_failed("overflow constructing `time::Duration`");
744        }
745
746        // Safety: `nanoseconds` is guaranteed to be in range because of the modulus above.
747        unsafe { Self::new_unchecked(seconds as i64, nanoseconds as i32) }
748    }
749
750    /// Get the number of whole weeks in the duration.
751    ///
752    /// ```rust
753    /// # use time::ext::NumericalDuration;
754    /// assert_eq!(1.weeks().whole_weeks(), 1);
755    /// assert_eq!((-1).weeks().whole_weeks(), -1);
756    /// assert_eq!(6.days().whole_weeks(), 0);
757    /// assert_eq!((-6).days().whole_weeks(), 0);
758    /// ```
759    pub const fn whole_weeks(self) -> i64 {
760        self.whole_seconds() / Second::per(Week) as i64
761    }
762
763    /// Get the number of whole days in the duration.
764    ///
765    /// ```rust
766    /// # use time::ext::NumericalDuration;
767    /// assert_eq!(1.days().whole_days(), 1);
768    /// assert_eq!((-1).days().whole_days(), -1);
769    /// assert_eq!(23.hours().whole_days(), 0);
770    /// assert_eq!((-23).hours().whole_days(), 0);
771    /// ```
772    pub const fn whole_days(self) -> i64 {
773        self.whole_seconds() / Second::per(Day) as i64
774    }
775
776    /// Get the number of whole hours in the duration.
777    ///
778    /// ```rust
779    /// # use time::ext::NumericalDuration;
780    /// assert_eq!(1.hours().whole_hours(), 1);
781    /// assert_eq!((-1).hours().whole_hours(), -1);
782    /// assert_eq!(59.minutes().whole_hours(), 0);
783    /// assert_eq!((-59).minutes().whole_hours(), 0);
784    /// ```
785    pub const fn whole_hours(self) -> i64 {
786        self.whole_seconds() / Second::per(Hour) as i64
787    }
788
789    /// Get the number of whole minutes in the duration.
790    ///
791    /// ```rust
792    /// # use time::ext::NumericalDuration;
793    /// assert_eq!(1.minutes().whole_minutes(), 1);
794    /// assert_eq!((-1).minutes().whole_minutes(), -1);
795    /// assert_eq!(59.seconds().whole_minutes(), 0);
796    /// assert_eq!((-59).seconds().whole_minutes(), 0);
797    /// ```
798    pub const fn whole_minutes(self) -> i64 {
799        self.whole_seconds() / Second::per(Minute) as i64
800    }
801
802    /// Get the number of whole seconds in the duration.
803    ///
804    /// ```rust
805    /// # use time::ext::NumericalDuration;
806    /// assert_eq!(1.seconds().whole_seconds(), 1);
807    /// assert_eq!((-1).seconds().whole_seconds(), -1);
808    /// assert_eq!(1.minutes().whole_seconds(), 60);
809    /// assert_eq!((-1).minutes().whole_seconds(), -60);
810    /// ```
811    pub const fn whole_seconds(self) -> i64 {
812        self.seconds
813    }
814
815    /// Get the number of fractional seconds in the duration.
816    ///
817    /// ```rust
818    /// # use time::ext::NumericalDuration;
819    /// assert_eq!(1.5.seconds().as_seconds_f64(), 1.5);
820    /// assert_eq!((-1.5).seconds().as_seconds_f64(), -1.5);
821    /// ```
822    pub fn as_seconds_f64(self) -> f64 {
823        self.seconds as f64 + self.nanoseconds.get() as f64 / Nanosecond::per(Second) as f64
824    }
825
826    /// Get the number of fractional seconds in the duration.
827    ///
828    /// ```rust
829    /// # use time::ext::NumericalDuration;
830    /// assert_eq!(1.5.seconds().as_seconds_f32(), 1.5);
831    /// assert_eq!((-1.5).seconds().as_seconds_f32(), -1.5);
832    /// ```
833    pub fn as_seconds_f32(self) -> f32 {
834        self.seconds as f32 + self.nanoseconds.get() as f32 / Nanosecond::per(Second) as f32
835    }
836
837    /// Get the number of whole milliseconds in the duration.
838    ///
839    /// ```rust
840    /// # use time::ext::NumericalDuration;
841    /// assert_eq!(1.seconds().whole_milliseconds(), 1_000);
842    /// assert_eq!((-1).seconds().whole_milliseconds(), -1_000);
843    /// assert_eq!(1.milliseconds().whole_milliseconds(), 1);
844    /// assert_eq!((-1).milliseconds().whole_milliseconds(), -1);
845    /// ```
846    pub const fn whole_milliseconds(self) -> i128 {
847        self.seconds as i128 * Millisecond::per(Second) as i128
848            + self.nanoseconds.get() as i128 / Nanosecond::per(Millisecond) as i128
849    }
850
851    /// Get the number of milliseconds past the number of whole seconds.
852    ///
853    /// Always in the range `-999..=999`.
854    ///
855    /// ```rust
856    /// # use time::ext::NumericalDuration;
857    /// assert_eq!(1.4.seconds().subsec_milliseconds(), 400);
858    /// assert_eq!((-1.4).seconds().subsec_milliseconds(), -400);
859    /// ```
860    // Allow the lint, as the value is guaranteed to be less than 1000.
861    pub const fn subsec_milliseconds(self) -> i16 {
862        (self.nanoseconds.get() / Nanosecond::per(Millisecond) as i32) as i16
863    }
864
865    /// Get the number of whole microseconds in the duration.
866    ///
867    /// ```rust
868    /// # use time::ext::NumericalDuration;
869    /// assert_eq!(1.milliseconds().whole_microseconds(), 1_000);
870    /// assert_eq!((-1).milliseconds().whole_microseconds(), -1_000);
871    /// assert_eq!(1.microseconds().whole_microseconds(), 1);
872    /// assert_eq!((-1).microseconds().whole_microseconds(), -1);
873    /// ```
874    pub const fn whole_microseconds(self) -> i128 {
875        self.seconds as i128 * Microsecond::per(Second) as i128
876            + self.nanoseconds.get() as i128 / Nanosecond::per(Microsecond) as i128
877    }
878
879    /// Get the number of microseconds past the number of whole seconds.
880    ///
881    /// Always in the range `-999_999..=999_999`.
882    ///
883    /// ```rust
884    /// # use time::ext::NumericalDuration;
885    /// assert_eq!(1.0004.seconds().subsec_microseconds(), 400);
886    /// assert_eq!((-1.0004).seconds().subsec_microseconds(), -400);
887    /// ```
888    pub const fn subsec_microseconds(self) -> i32 {
889        self.nanoseconds.get() / Nanosecond::per(Microsecond) as i32
890    }
891
892    /// Get the number of nanoseconds in the duration.
893    ///
894    /// ```rust
895    /// # use time::ext::NumericalDuration;
896    /// assert_eq!(1.microseconds().whole_nanoseconds(), 1_000);
897    /// assert_eq!((-1).microseconds().whole_nanoseconds(), -1_000);
898    /// assert_eq!(1.nanoseconds().whole_nanoseconds(), 1);
899    /// assert_eq!((-1).nanoseconds().whole_nanoseconds(), -1);
900    /// ```
901    pub const fn whole_nanoseconds(self) -> i128 {
902        self.seconds as i128 * Nanosecond::per(Second) as i128 + self.nanoseconds.get() as i128
903    }
904
905    /// Get the number of nanoseconds past the number of whole seconds.
906    ///
907    /// The returned value will always be in the range `-999_999_999..=999_999_999`.
908    ///
909    /// ```rust
910    /// # use time::ext::NumericalDuration;
911    /// assert_eq!(1.000_000_400.seconds().subsec_nanoseconds(), 400);
912    /// assert_eq!((-1.000_000_400).seconds().subsec_nanoseconds(), -400);
913    /// ```
914    pub const fn subsec_nanoseconds(self) -> i32 {
915        self.nanoseconds.get()
916    }
917
918    /// Get the number of nanoseconds past the number of whole seconds.
919    #[cfg(feature = "quickcheck")]
920    pub(crate) const fn subsec_nanoseconds_ranged(self) -> Nanoseconds {
921        self.nanoseconds
922    }
923
924    /// Computes `self + rhs`, returning `None` if an overflow occurred.
925    ///
926    /// ```rust
927    /// # use time::{Duration, ext::NumericalDuration};
928    /// assert_eq!(5.seconds().checked_add(5.seconds()), Some(10.seconds()));
929    /// assert_eq!(Duration::MAX.checked_add(1.nanoseconds()), None);
930    /// assert_eq!((-5).seconds().checked_add(5.seconds()), Some(0.seconds()));
931    /// ```
932    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
933        let mut seconds = const_try_opt!(self.seconds.checked_add(rhs.seconds));
934        let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
935
936        if nanoseconds >= Nanosecond::per(Second) as i32 || seconds < 0 && nanoseconds > 0 {
937            nanoseconds -= Nanosecond::per(Second) as i32;
938            seconds = const_try_opt!(seconds.checked_add(1));
939        } else if nanoseconds <= -(Nanosecond::per(Second) as i32) || seconds > 0 && nanoseconds < 0
940        {
941            nanoseconds += Nanosecond::per(Second) as i32;
942            seconds = const_try_opt!(seconds.checked_sub(1));
943        }
944
945        // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
946        unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
947    }
948
949    /// Computes `self - rhs`, returning `None` if an overflow occurred.
950    ///
951    /// ```rust
952    /// # use time::{Duration, ext::NumericalDuration};
953    /// assert_eq!(5.seconds().checked_sub(5.seconds()), Some(Duration::ZERO));
954    /// assert_eq!(Duration::MIN.checked_sub(1.nanoseconds()), None);
955    /// assert_eq!(5.seconds().checked_sub(10.seconds()), Some((-5).seconds()));
956    /// ```
957    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
958        let mut seconds = const_try_opt!(self.seconds.checked_sub(rhs.seconds));
959        let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
960
961        if nanoseconds >= Nanosecond::per(Second) as i32 || seconds < 0 && nanoseconds > 0 {
962            nanoseconds -= Nanosecond::per(Second) as i32;
963            seconds = const_try_opt!(seconds.checked_add(1));
964        } else if nanoseconds <= -(Nanosecond::per(Second) as i32) || seconds > 0 && nanoseconds < 0
965        {
966            nanoseconds += Nanosecond::per(Second) as i32;
967            seconds = const_try_opt!(seconds.checked_sub(1));
968        }
969
970        // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
971        unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
972    }
973
974    /// Computes `self * rhs`, returning `None` if an overflow occurred.
975    ///
976    /// ```rust
977    /// # use time::{Duration, ext::NumericalDuration};
978    /// assert_eq!(5.seconds().checked_mul(2), Some(10.seconds()));
979    /// assert_eq!(5.seconds().checked_mul(-2), Some((-10).seconds()));
980    /// assert_eq!(5.seconds().checked_mul(0), Some(0.seconds()));
981    /// assert_eq!(Duration::MAX.checked_mul(2), None);
982    /// assert_eq!(Duration::MIN.checked_mul(2), None);
983    /// ```
984    pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
985        // Multiply nanoseconds as i64, because it cannot overflow that way.
986        let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
987        let extra_secs = total_nanos / Nanosecond::per(Second) as i64;
988        let nanoseconds = (total_nanos % Nanosecond::per(Second) as i64) as i32;
989        let seconds = const_try_opt!(
990            const_try_opt!(self.seconds.checked_mul(rhs as i64)).checked_add(extra_secs)
991        );
992
993        // Safety: `nanoseconds` is guaranteed to be in range because of the modulus above.
994        unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
995    }
996
997    /// Computes `self / rhs`, returning `None` if `rhs == 0` or if the result would overflow.
998    ///
999    /// ```rust
1000    /// # use time::ext::NumericalDuration;
1001    /// assert_eq!(10.seconds().checked_div(2), Some(5.seconds()));
1002    /// assert_eq!(10.seconds().checked_div(-2), Some((-5).seconds()));
1003    /// assert_eq!(1.seconds().checked_div(0), None);
1004    /// ```
1005    pub const fn checked_div(self, rhs: i32) -> Option<Self> {
1006        let (secs, extra_secs) = (
1007            const_try_opt!(self.seconds.checked_div(rhs as i64)),
1008            self.seconds % (rhs as i64),
1009        );
1010        let (mut nanos, extra_nanos) = (self.nanoseconds.get() / rhs, self.nanoseconds.get() % rhs);
1011        nanos += ((extra_secs * (Nanosecond::per(Second) as i64) + extra_nanos as i64)
1012            / (rhs as i64)) as i32;
1013
1014        // Safety: `nanoseconds` is in range.
1015        unsafe { Some(Self::new_unchecked(secs, nanos)) }
1016    }
1017
1018    /// Computes `-self`, returning `None` if the result would overflow.
1019    ///
1020    /// ```rust
1021    /// # use time::ext::NumericalDuration;
1022    /// # use time::Duration;
1023    /// assert_eq!(5.seconds().checked_neg(), Some((-5).seconds()));
1024    /// assert_eq!(Duration::MIN.checked_neg(), None);
1025    /// ```
1026    pub const fn checked_neg(self) -> Option<Self> {
1027        if self.seconds == i64::MIN {
1028            None
1029        } else {
1030            Some(Self::new_ranged_unchecked(
1031                -self.seconds,
1032                self.nanoseconds.neg(),
1033            ))
1034        }
1035    }
1036
1037    /// Computes `self + rhs`, saturating if an overflow occurred.
1038    ///
1039    /// ```rust
1040    /// # use time::{Duration, ext::NumericalDuration};
1041    /// assert_eq!(5.seconds().saturating_add(5.seconds()), 10.seconds());
1042    /// assert_eq!(Duration::MAX.saturating_add(1.nanoseconds()), Duration::MAX);
1043    /// assert_eq!(
1044    ///     Duration::MIN.saturating_add((-1).nanoseconds()),
1045    ///     Duration::MIN
1046    /// );
1047    /// assert_eq!((-5).seconds().saturating_add(5.seconds()), Duration::ZERO);
1048    /// ```
1049    pub const fn saturating_add(self, rhs: Self) -> Self {
1050        let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
1051        if overflow {
1052            if self.seconds > 0 {
1053                return Self::MAX;
1054            }
1055            return Self::MIN;
1056        }
1057        let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1058
1059        if nanoseconds >= Nanosecond::per(Second) as i32 || seconds < 0 && nanoseconds > 0 {
1060            nanoseconds -= Nanosecond::per(Second) as i32;
1061            seconds = match seconds.checked_add(1) {
1062                Some(seconds) => seconds,
1063                None => return Self::MAX,
1064            };
1065        } else if nanoseconds <= -(Nanosecond::per(Second) as i32) || seconds > 0 && nanoseconds < 0
1066        {
1067            nanoseconds += Nanosecond::per(Second) as i32;
1068            seconds = match seconds.checked_sub(1) {
1069                Some(seconds) => seconds,
1070                None => return Self::MIN,
1071            };
1072        }
1073
1074        // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1075        unsafe { Self::new_unchecked(seconds, nanoseconds) }
1076    }
1077
1078    /// Computes `self - rhs`, saturating if an overflow occurred.
1079    ///
1080    /// ```rust
1081    /// # use time::{Duration, ext::NumericalDuration};
1082    /// assert_eq!(5.seconds().saturating_sub(5.seconds()), Duration::ZERO);
1083    /// assert_eq!(Duration::MIN.saturating_sub(1.nanoseconds()), Duration::MIN);
1084    /// assert_eq!(
1085    ///     Duration::MAX.saturating_sub((-1).nanoseconds()),
1086    ///     Duration::MAX
1087    /// );
1088    /// assert_eq!(5.seconds().saturating_sub(10.seconds()), (-5).seconds());
1089    /// ```
1090    pub const fn saturating_sub(self, rhs: Self) -> Self {
1091        let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
1092        if overflow {
1093            if self.seconds > 0 {
1094                return Self::MAX;
1095            }
1096            return Self::MIN;
1097        }
1098        let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1099
1100        if nanoseconds >= Nanosecond::per(Second) as i32 || seconds < 0 && nanoseconds > 0 {
1101            nanoseconds -= Nanosecond::per(Second) as i32;
1102            seconds = match seconds.checked_add(1) {
1103                Some(seconds) => seconds,
1104                None => return Self::MAX,
1105            };
1106        } else if nanoseconds <= -(Nanosecond::per(Second) as i32) || seconds > 0 && nanoseconds < 0
1107        {
1108            nanoseconds += Nanosecond::per(Second) as i32;
1109            seconds = match seconds.checked_sub(1) {
1110                Some(seconds) => seconds,
1111                None => return Self::MIN,
1112            };
1113        }
1114
1115        // Safety: `nanoseconds` is guaranteed to be in range because of the overflow handling.
1116        unsafe { Self::new_unchecked(seconds, nanoseconds) }
1117    }
1118
1119    /// Computes `self * rhs`, saturating if an overflow occurred.
1120    ///
1121    /// ```rust
1122    /// # use time::{Duration, ext::NumericalDuration};
1123    /// assert_eq!(5.seconds().saturating_mul(2), 10.seconds());
1124    /// assert_eq!(5.seconds().saturating_mul(-2), (-10).seconds());
1125    /// assert_eq!(5.seconds().saturating_mul(0), Duration::ZERO);
1126    /// assert_eq!(Duration::MAX.saturating_mul(2), Duration::MAX);
1127    /// assert_eq!(Duration::MIN.saturating_mul(2), Duration::MIN);
1128    /// assert_eq!(Duration::MAX.saturating_mul(-2), Duration::MIN);
1129    /// assert_eq!(Duration::MIN.saturating_mul(-2), Duration::MAX);
1130    /// ```
1131    pub const fn saturating_mul(self, rhs: i32) -> Self {
1132        // Multiply nanoseconds as i64, because it cannot overflow that way.
1133        let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1134        let extra_secs = total_nanos / Nanosecond::per(Second) as i64;
1135        let nanoseconds = (total_nanos % Nanosecond::per(Second) as i64) as i32;
1136        let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as i64);
1137        if overflow1 {
1138            if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
1139                return Self::MAX;
1140            }
1141            return Self::MIN;
1142        }
1143        let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
1144        if overflow2 {
1145            if self.seconds > 0 && rhs > 0 {
1146                return Self::MAX;
1147            }
1148            return Self::MIN;
1149        }
1150
1151        // Safety: `nanoseconds` is guaranteed to be in range because of to the modulus above.
1152        unsafe { Self::new_unchecked(seconds, nanoseconds) }
1153    }
1154
1155    /// Runs a closure, returning the duration of time it took to run. The return value of the
1156    /// closure is provided in the second part of the tuple.
1157    #[doc(hidden)]
1158    #[cfg(feature = "std")]
1159    #[deprecated(
1160        since = "0.3.32",
1161        note = "extremely limited use case, not intended for benchmarking"
1162    )]
1163    #[allow(deprecated)]
1164    pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
1165        let start = Instant::now();
1166        let return_value = f();
1167        let end = Instant::now();
1168
1169        (end - start, return_value)
1170    }
1171}
1172
1173/// The format returned by this implementation is not stable and must not be relied upon.
1174///
1175/// By default this produces an exact, full-precision printout of the duration.
1176/// For a concise, rounded printout instead, you can use the `.N` format specifier:
1177///
1178/// ```
1179/// # use time::Duration;
1180/// #
1181/// let duration = Duration::new(123456, 789011223);
1182/// println!("{duration:.3}");
1183/// ```
1184///
1185/// For the purposes of this implementation, a day is exactly 24 hours and a minute is exactly 60
1186/// seconds.
1187impl fmt::Display for Duration {
1188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1189        if self.is_negative() {
1190            f.write_str("-")?;
1191        }
1192
1193        if let Some(_precision) = f.precision() {
1194            // Concise, rounded representation.
1195
1196            if self.is_zero() {
1197                // Write a zero value with the requested precision.
1198                return (0.).fmt(f).and_then(|_| f.write_str("s"));
1199            }
1200
1201            /// Format the first item that produces a value greater than 1 and then break.
1202            macro_rules! item {
1203                ($name:literal, $value:expr) => {
1204                    let value = $value;
1205                    if value >= 1.0 {
1206                        return value.fmt(f).and_then(|_| f.write_str($name));
1207                    }
1208                };
1209            }
1210
1211            // Even if this produces a de-normal float, because we're rounding we don't really care.
1212            let seconds = self.unsigned_abs().as_secs_f64();
1213
1214            item!("d", seconds / Second::per(Day) as f64);
1215            item!("h", seconds / Second::per(Hour) as f64);
1216            item!("m", seconds / Second::per(Minute) as f64);
1217            item!("s", seconds);
1218            item!("ms", seconds * Millisecond::per(Second) as f64);
1219            item!("µs", seconds * Microsecond::per(Second) as f64);
1220            item!("ns", seconds * Nanosecond::per(Second) as f64);
1221        } else {
1222            // Precise, but verbose representation.
1223
1224            if self.is_zero() {
1225                return f.write_str("0s");
1226            }
1227
1228            /// Format a single item.
1229            macro_rules! item {
1230                ($name:literal, $value:expr) => {
1231                    match $value {
1232                        0 => Ok(()),
1233                        value => value.fmt(f).and_then(|_| f.write_str($name)),
1234                    }
1235                };
1236            }
1237
1238            let seconds = self.seconds.unsigned_abs();
1239            let nanoseconds = self.nanoseconds.get().unsigned_abs();
1240
1241            item!("d", seconds / Second::per(Day).extend::<u64>())?;
1242            item!(
1243                "h",
1244                seconds / Second::per(Hour).extend::<u64>() % Hour::per(Day).extend::<u64>()
1245            )?;
1246            item!(
1247                "m",
1248                seconds / Second::per(Minute).extend::<u64>() % Minute::per(Hour).extend::<u64>()
1249            )?;
1250            item!("s", seconds % Second::per(Minute).extend::<u64>())?;
1251            item!("ms", nanoseconds / Nanosecond::per(Millisecond))?;
1252            item!(
1253                "µs",
1254                nanoseconds / Nanosecond::per(Microsecond).extend::<u32>()
1255                    % Microsecond::per(Millisecond).extend::<u32>()
1256            )?;
1257            item!(
1258                "ns",
1259                nanoseconds % Nanosecond::per(Microsecond).extend::<u32>()
1260            )?;
1261        }
1262
1263        Ok(())
1264    }
1265}
1266
1267impl TryFrom<StdDuration> for Duration {
1268    type Error = error::ConversionRange;
1269
1270    fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
1271        Ok(Self::new(
1272            original
1273                .as_secs()
1274                .try_into()
1275                .map_err(|_| error::ConversionRange)?,
1276            original.subsec_nanos().cast_signed(),
1277        ))
1278    }
1279}
1280
1281impl TryFrom<Duration> for StdDuration {
1282    type Error = error::ConversionRange;
1283
1284    fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
1285        Ok(Self::new(
1286            duration
1287                .seconds
1288                .try_into()
1289                .map_err(|_| error::ConversionRange)?,
1290            duration
1291                .nanoseconds
1292                .get()
1293                .try_into()
1294                .map_err(|_| error::ConversionRange)?,
1295        ))
1296    }
1297}
1298
1299impl Add for Duration {
1300    type Output = Self;
1301
1302    /// # Panics
1303    ///
1304    /// This may panic if an overflow occurs.
1305    fn add(self, rhs: Self) -> Self::Output {
1306        self.checked_add(rhs)
1307            .expect("overflow when adding durations")
1308    }
1309}
1310
1311impl Add<StdDuration> for Duration {
1312    type Output = Self;
1313
1314    /// # Panics
1315    ///
1316    /// This may panic if an overflow occurs.
1317    fn add(self, std_duration: StdDuration) -> Self::Output {
1318        self + Self::try_from(std_duration)
1319            .expect("overflow converting `std::time::Duration` to `time::Duration`")
1320    }
1321}
1322
1323impl Add<Duration> for StdDuration {
1324    type Output = Duration;
1325
1326    fn add(self, rhs: Duration) -> Self::Output {
1327        rhs + self
1328    }
1329}
1330
1331impl_add_assign!(Duration: Self, StdDuration);
1332
1333impl AddAssign<Duration> for StdDuration {
1334    /// # Panics
1335    ///
1336    /// This may panic if the resulting addition cannot be represented.
1337    fn add_assign(&mut self, rhs: Duration) {
1338        *self = (*self + rhs).try_into().expect(
1339            "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
1340             change the type.",
1341        );
1342    }
1343}
1344
1345impl Neg for Duration {
1346    type Output = Self;
1347
1348    fn neg(self) -> Self::Output {
1349        self.checked_neg().expect("overflow when negating duration")
1350    }
1351}
1352
1353impl Sub for Duration {
1354    type Output = Self;
1355
1356    /// # Panics
1357    ///
1358    /// This may panic if an overflow occurs.
1359    fn sub(self, rhs: Self) -> Self::Output {
1360        self.checked_sub(rhs)
1361            .expect("overflow when subtracting durations")
1362    }
1363}
1364
1365impl Sub<StdDuration> for Duration {
1366    type Output = Self;
1367
1368    /// # Panics
1369    ///
1370    /// This may panic if an overflow occurs.
1371    fn sub(self, rhs: StdDuration) -> Self::Output {
1372        self - Self::try_from(rhs)
1373            .expect("overflow converting `std::time::Duration` to `time::Duration`")
1374    }
1375}
1376
1377impl Sub<Duration> for StdDuration {
1378    type Output = Duration;
1379
1380    /// # Panics
1381    ///
1382    /// This may panic if an overflow occurs.
1383    fn sub(self, rhs: Duration) -> Self::Output {
1384        Duration::try_from(self)
1385            .expect("overflow converting `std::time::Duration` to `time::Duration`")
1386            - rhs
1387    }
1388}
1389
1390impl_sub_assign!(Duration: Self, StdDuration);
1391
1392impl SubAssign<Duration> for StdDuration {
1393    /// # Panics
1394    ///
1395    /// This may panic if the resulting subtraction can not be represented.
1396    fn sub_assign(&mut self, rhs: Duration) {
1397        *self = (*self - rhs).try_into().expect(
1398            "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
1399             change the type.",
1400        );
1401    }
1402}
1403
1404/// Implement `Mul` (reflexively) and `Div` for `Duration` for various types.
1405macro_rules! duration_mul_div_int {
1406    ($($type:ty),+) => {$(
1407        impl Mul<$type> for Duration {
1408            type Output = Self;
1409
1410            fn mul(self, rhs: $type) -> Self::Output {
1411                Self::nanoseconds_i128(
1412                    self.whole_nanoseconds()
1413                        .checked_mul(rhs.cast_signed().extend::<i128>())
1414                        .expect("overflow when multiplying duration")
1415                )
1416            }
1417        }
1418
1419        impl Mul<Duration> for $type {
1420            type Output = Duration;
1421
1422            fn mul(self, rhs: Duration) -> Self::Output {
1423                rhs * self
1424            }
1425        }
1426
1427        impl Div<$type> for Duration {
1428            type Output = Self;
1429
1430            fn div(self, rhs: $type) -> Self::Output {
1431                Self::nanoseconds_i128(
1432                    self.whole_nanoseconds() / rhs.cast_signed().extend::<i128>()
1433                )
1434            }
1435        }
1436    )+};
1437}
1438duration_mul_div_int![i8, i16, i32, u8, u16, u32];
1439
1440impl Mul<f32> for Duration {
1441    type Output = Self;
1442
1443    fn mul(self, rhs: f32) -> Self::Output {
1444        Self::seconds_f32(self.as_seconds_f32() * rhs)
1445    }
1446}
1447
1448impl Mul<Duration> for f32 {
1449    type Output = Duration;
1450
1451    fn mul(self, rhs: Duration) -> Self::Output {
1452        rhs * self
1453    }
1454}
1455
1456impl Mul<f64> for Duration {
1457    type Output = Self;
1458
1459    fn mul(self, rhs: f64) -> Self::Output {
1460        Self::seconds_f64(self.as_seconds_f64() * rhs)
1461    }
1462}
1463
1464impl Mul<Duration> for f64 {
1465    type Output = Duration;
1466
1467    fn mul(self, rhs: Duration) -> Self::Output {
1468        rhs * self
1469    }
1470}
1471
1472impl_mul_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1473
1474impl Div<f32> for Duration {
1475    type Output = Self;
1476
1477    fn div(self, rhs: f32) -> Self::Output {
1478        Self::seconds_f32(self.as_seconds_f32() / rhs)
1479    }
1480}
1481
1482impl Div<f64> for Duration {
1483    type Output = Self;
1484
1485    fn div(self, rhs: f64) -> Self::Output {
1486        Self::seconds_f64(self.as_seconds_f64() / rhs)
1487    }
1488}
1489
1490impl_div_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1491
1492impl Div for Duration {
1493    type Output = f64;
1494
1495    fn div(self, rhs: Self) -> Self::Output {
1496        self.as_seconds_f64() / rhs.as_seconds_f64()
1497    }
1498}
1499
1500impl Div<StdDuration> for Duration {
1501    type Output = f64;
1502
1503    fn div(self, rhs: StdDuration) -> Self::Output {
1504        self.as_seconds_f64() / rhs.as_secs_f64()
1505    }
1506}
1507
1508impl Div<Duration> for StdDuration {
1509    type Output = f64;
1510
1511    fn div(self, rhs: Duration) -> Self::Output {
1512        self.as_secs_f64() / rhs.as_seconds_f64()
1513    }
1514}
1515
1516impl PartialEq<StdDuration> for Duration {
1517    fn eq(&self, rhs: &StdDuration) -> bool {
1518        Ok(*self) == Self::try_from(*rhs)
1519    }
1520}
1521
1522impl PartialEq<Duration> for StdDuration {
1523    fn eq(&self, rhs: &Duration) -> bool {
1524        rhs == self
1525    }
1526}
1527
1528impl PartialOrd<StdDuration> for Duration {
1529    fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1530        if rhs.as_secs() > i64::MAX.cast_unsigned() {
1531            return Some(Ordering::Less);
1532        }
1533
1534        Some(
1535            self.seconds
1536                .cmp(&rhs.as_secs().cast_signed())
1537                .then_with(|| {
1538                    self.nanoseconds
1539                        .get()
1540                        .cmp(&rhs.subsec_nanos().cast_signed())
1541                }),
1542        )
1543    }
1544}
1545
1546impl PartialOrd<Duration> for StdDuration {
1547    fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1548        rhs.partial_cmp(self).map(Ordering::reverse)
1549    }
1550}
1551
1552impl Sum for Duration {
1553    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1554        iter.reduce(|a, b| a + b).unwrap_or_default()
1555    }
1556}
1557
1558impl<'a> Sum<&'a Self> for Duration {
1559    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1560        iter.copied().sum()
1561    }
1562}
1563
1564#[cfg(feature = "std")]
1565impl Add<Duration> for SystemTime {
1566    type Output = Self;
1567
1568    fn add(self, duration: Duration) -> Self::Output {
1569        if duration.is_zero() {
1570            self
1571        } else if duration.is_positive() {
1572            self + duration.unsigned_abs()
1573        } else {
1574            debug_assert!(duration.is_negative());
1575            self - duration.unsigned_abs()
1576        }
1577    }
1578}
1579
1580impl_add_assign!(SystemTime: #[cfg(feature = "std")] Duration);
1581
1582#[cfg(feature = "std")]
1583impl Sub<Duration> for SystemTime {
1584    type Output = Self;
1585
1586    fn sub(self, duration: Duration) -> Self::Output {
1587        if duration.is_zero() {
1588            self
1589        } else if duration.is_positive() {
1590            self - duration.unsigned_abs()
1591        } else {
1592            debug_assert!(duration.is_negative());
1593            self + duration.unsigned_abs()
1594        }
1595    }
1596}
1597
1598impl_sub_assign!(SystemTime: #[cfg(feature = "std")] Duration);