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