Skip to main content

time/
duration.rs

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