Skip to main content

time/
signed_duration.rs

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