Coverage Report

Created: 2025-10-21 06:22

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