Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/time-0.3.13/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
9
use crate::error;
10
#[cfg(feature = "std")]
11
use crate::Instant;
12
13
/// By explicitly inserting this enum where padding is expected, the compiler is able to better
14
/// perform niche value optimization.
15
#[repr(u32)]
16
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
17
pub(crate) enum Padding {
18
    #[allow(clippy::missing_docs_in_private_items)]
19
    Optimize,
20
}
21
22
impl Default for Padding {
23
0
    fn default() -> Self {
24
0
        Self::Optimize
25
0
    }
26
}
27
28
/// A span of time with nanosecond precision.
29
///
30
/// Each `Duration` is composed of a whole number of seconds and a fractional part represented in
31
/// nanoseconds.
32
///
33
/// This implementation allows for negative durations, unlike [`core::time::Duration`].
34
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
35
pub struct Duration {
36
    /// Number of whole seconds.
37
    seconds: i64,
38
    /// Number of nanoseconds within the second. The sign always matches the `seconds` field.
39
    nanoseconds: i32, // always -10^9 < nanoseconds < 10^9
40
    #[allow(clippy::missing_docs_in_private_items)]
41
    padding: Padding,
42
}
43
44
impl fmt::Debug for Duration {
45
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46
0
        f.debug_struct("Duration")
47
0
            .field("seconds", &self.seconds)
48
0
            .field("nanoseconds", &self.nanoseconds)
49
0
            .finish()
50
0
    }
51
}
52
53
impl Duration {
54
    // region: constants
55
    /// Equivalent to `0.seconds()`.
56
    ///
57
    /// ```rust
58
    /// # use time::{Duration, ext::NumericalDuration};
59
    /// assert_eq!(Duration::ZERO, 0.seconds());
60
    /// ```
61
    pub const ZERO: Self = Self::seconds(0);
62
63
    /// Equivalent to `1.nanoseconds()`.
64
    ///
65
    /// ```rust
66
    /// # use time::{Duration, ext::NumericalDuration};
67
    /// assert_eq!(Duration::NANOSECOND, 1.nanoseconds());
68
    /// ```
69
    pub const NANOSECOND: Self = Self::nanoseconds(1);
70
71
    /// Equivalent to `1.microseconds()`.
72
    ///
73
    /// ```rust
74
    /// # use time::{Duration, ext::NumericalDuration};
75
    /// assert_eq!(Duration::MICROSECOND, 1.microseconds());
76
    /// ```
77
    pub const MICROSECOND: Self = Self::microseconds(1);
78
79
    /// Equivalent to `1.milliseconds()`.
80
    ///
81
    /// ```rust
82
    /// # use time::{Duration, ext::NumericalDuration};
83
    /// assert_eq!(Duration::MILLISECOND, 1.milliseconds());
84
    /// ```
85
    pub const MILLISECOND: Self = Self::milliseconds(1);
86
87
    /// Equivalent to `1.seconds()`.
88
    ///
89
    /// ```rust
90
    /// # use time::{Duration, ext::NumericalDuration};
91
    /// assert_eq!(Duration::SECOND, 1.seconds());
92
    /// ```
93
    pub const SECOND: Self = Self::seconds(1);
94
95
    /// Equivalent to `1.minutes()`.
96
    ///
97
    /// ```rust
98
    /// # use time::{Duration, ext::NumericalDuration};
99
    /// assert_eq!(Duration::MINUTE, 1.minutes());
100
    /// ```
101
    pub const MINUTE: Self = Self::minutes(1);
102
103
    /// Equivalent to `1.hours()`.
104
    ///
105
    /// ```rust
106
    /// # use time::{Duration, ext::NumericalDuration};
107
    /// assert_eq!(Duration::HOUR, 1.hours());
108
    /// ```
109
    pub const HOUR: Self = Self::hours(1);
110
111
    /// Equivalent to `1.days()`.
112
    ///
113
    /// ```rust
114
    /// # use time::{Duration, ext::NumericalDuration};
115
    /// assert_eq!(Duration::DAY, 1.days());
116
    /// ```
117
    pub const DAY: Self = Self::days(1);
118
119
    /// Equivalent to `1.weeks()`.
120
    ///
121
    /// ```rust
122
    /// # use time::{Duration, ext::NumericalDuration};
123
    /// assert_eq!(Duration::WEEK, 1.weeks());
124
    /// ```
125
    pub const WEEK: Self = Self::weeks(1);
126
127
    /// The minimum possible duration. Adding any negative duration to this will cause an overflow.
128
    pub const MIN: Self = Self::new_unchecked(i64::MIN, -999_999_999);
129
130
    /// The maximum possible duration. Adding any positive duration to this will cause an overflow.
131
    pub const MAX: Self = Self::new_unchecked(i64::MAX, 999_999_999);
132
    // endregion constants
133
134
    // region: is_{sign}
135
    /// Check if a duration is exactly zero.
136
    ///
137
    /// ```rust
138
    /// # use time::ext::NumericalDuration;
139
    /// assert!(0.seconds().is_zero());
140
    /// assert!(!1.nanoseconds().is_zero());
141
    /// ```
142
0
    pub const fn is_zero(self) -> bool {
143
0
        self.seconds == 0 && self.nanoseconds == 0
144
0
    }
145
146
    /// Check if a duration is negative.
147
    ///
148
    /// ```rust
149
    /// # use time::ext::NumericalDuration;
150
    /// assert!((-1).seconds().is_negative());
151
    /// assert!(!0.seconds().is_negative());
152
    /// assert!(!1.seconds().is_negative());
153
    /// ```
154
0
    pub const fn is_negative(self) -> bool {
155
0
        self.seconds < 0 || self.nanoseconds < 0
156
0
    }
157
158
    /// Check if a duration is positive.
159
    ///
160
    /// ```rust
161
    /// # use time::ext::NumericalDuration;
162
    /// assert!(1.seconds().is_positive());
163
    /// assert!(!0.seconds().is_positive());
164
    /// assert!(!(-1).seconds().is_positive());
165
    /// ```
166
0
    pub const fn is_positive(self) -> bool {
167
0
        self.seconds > 0 || self.nanoseconds > 0
168
0
    }
169
    // endregion is_{sign}
170
171
    // region: abs
172
    /// Get the absolute value of the duration.
173
    ///
174
    /// This method saturates the returned value if it would otherwise overflow.
175
    ///
176
    /// ```rust
177
    /// # use time::ext::NumericalDuration;
178
    /// assert_eq!(1.seconds().abs(), 1.seconds());
179
    /// assert_eq!(0.seconds().abs(), 0.seconds());
180
    /// assert_eq!((-1).seconds().abs(), 1.seconds());
181
    /// ```
182
0
    pub const fn abs(self) -> Self {
183
0
        Self::new_unchecked(self.seconds.saturating_abs(), self.nanoseconds.abs())
184
0
    }
185
186
    /// Convert the existing `Duration` to a `std::time::Duration` and its sign. This returns a
187
    /// [`std::time::Duration`] and does not saturate the returned value (unlike [`Duration::abs`]).
188
    ///
189
    /// ```rust
190
    /// # use time::ext::{NumericalDuration, NumericalStdDuration};
191
    /// assert_eq!(1.seconds().unsigned_abs(), 1.std_seconds());
192
    /// assert_eq!(0.seconds().unsigned_abs(), 0.std_seconds());
193
    /// assert_eq!((-1).seconds().unsigned_abs(), 1.std_seconds());
194
    /// ```
195
    #[allow(clippy::missing_const_for_fn)] // requires MSRV of 1.58 (2022-07-13)
196
0
    pub fn unsigned_abs(self) -> StdDuration {
197
0
        StdDuration::new(self.seconds.unsigned_abs(), self.nanoseconds.unsigned_abs())
198
0
    }
199
    // endregion abs
200
201
    // region: constructors
202
    /// Create a new `Duration` without checking the validity of the components.
203
0
    pub(crate) const fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
204
0
        if seconds < 0 {
205
0
            debug_assert!(nanoseconds <= 0);
206
0
            debug_assert!(nanoseconds > -1_000_000_000);
207
0
        } else if seconds > 0 {
208
0
            debug_assert!(nanoseconds >= 0);
209
0
            debug_assert!(nanoseconds < 1_000_000_000);
210
        } else {
211
0
            debug_assert!(nanoseconds.unsigned_abs() < 1_000_000_000);
212
        }
213
214
0
        Self {
215
0
            seconds,
216
0
            nanoseconds,
217
0
            padding: Padding::Optimize,
218
0
        }
219
0
    }
220
221
    /// Create a new `Duration` with the provided seconds and nanoseconds. If nanoseconds is at
222
    /// least ±10<sup>9</sup>, it will wrap to the number of seconds.
223
    ///
224
    /// ```rust
225
    /// # use time::{Duration, ext::NumericalDuration};
226
    /// assert_eq!(Duration::new(1, 0), 1.seconds());
227
    /// assert_eq!(Duration::new(-1, 0), (-1).seconds());
228
    /// assert_eq!(Duration::new(1, 2_000_000_000), 3.seconds());
229
    /// ```
230
0
    pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
231
0
        seconds += nanoseconds as i64 / 1_000_000_000;
232
0
        nanoseconds %= 1_000_000_000;
233
234
0
        if seconds > 0 && nanoseconds < 0 {
235
0
            seconds -= 1;
236
0
            nanoseconds += 1_000_000_000;
237
0
        } else if seconds < 0 && nanoseconds > 0 {
238
0
            seconds += 1;
239
0
            nanoseconds -= 1_000_000_000;
240
0
        }
241
242
0
        Self::new_unchecked(seconds, nanoseconds)
243
0
    }
244
245
    /// Create a new `Duration` with the given number of weeks. Equivalent to
246
    /// `Duration::seconds(weeks * 604_800)`.
247
    ///
248
    /// ```rust
249
    /// # use time::{Duration, ext::NumericalDuration};
250
    /// assert_eq!(Duration::weeks(1), 604_800.seconds());
251
    /// ```
252
0
    pub const fn weeks(weeks: i64) -> Self {
253
0
        Self::seconds(weeks * 604_800)
254
0
    }
255
256
    /// Create a new `Duration` with the given number of days. Equivalent to
257
    /// `Duration::seconds(days * 86_400)`.
258
    ///
259
    /// ```rust
260
    /// # use time::{Duration, ext::NumericalDuration};
261
    /// assert_eq!(Duration::days(1), 86_400.seconds());
262
    /// ```
263
0
    pub const fn days(days: i64) -> Self {
264
0
        Self::seconds(days * 86_400)
265
0
    }
266
267
    /// Create a new `Duration` with the given number of hours. Equivalent to
268
    /// `Duration::seconds(hours * 3_600)`.
269
    ///
270
    /// ```rust
271
    /// # use time::{Duration, ext::NumericalDuration};
272
    /// assert_eq!(Duration::hours(1), 3_600.seconds());
273
    /// ```
274
0
    pub const fn hours(hours: i64) -> Self {
275
0
        Self::seconds(hours * 3_600)
276
0
    }
277
278
    /// Create a new `Duration` with the given number of minutes. Equivalent to
279
    /// `Duration::seconds(minutes * 60)`.
280
    ///
281
    /// ```rust
282
    /// # use time::{Duration, ext::NumericalDuration};
283
    /// assert_eq!(Duration::minutes(1), 60.seconds());
284
    /// ```
285
0
    pub const fn minutes(minutes: i64) -> Self {
286
0
        Self::seconds(minutes * 60)
287
0
    }
288
289
    /// Create a new `Duration` with the given number of seconds.
290
    ///
291
    /// ```rust
292
    /// # use time::{Duration, ext::NumericalDuration};
293
    /// assert_eq!(Duration::seconds(1), 1_000.milliseconds());
294
    /// ```
295
0
    pub const fn seconds(seconds: i64) -> Self {
296
0
        Self::new_unchecked(seconds, 0)
297
0
    }
298
299
    /// Creates a new `Duration` from the specified number of seconds represented as `f64`.
300
    ///
301
    /// ```rust
302
    /// # use time::{Duration, ext::NumericalDuration};
303
    /// assert_eq!(Duration::seconds_f64(0.5), 0.5.seconds());
304
    /// assert_eq!(Duration::seconds_f64(-0.5), -0.5.seconds());
305
    /// ```
306
0
    pub fn seconds_f64(seconds: f64) -> Self {
307
0
        Self::new_unchecked(seconds as _, ((seconds % 1.) * 1_000_000_000.) as _)
308
0
    }
309
310
    /// Creates a new `Duration` from the specified number of seconds represented as `f32`.
311
    ///
312
    /// ```rust
313
    /// # use time::{Duration, ext::NumericalDuration};
314
    /// assert_eq!(Duration::seconds_f32(0.5), 0.5.seconds());
315
    /// assert_eq!(Duration::seconds_f32(-0.5), (-0.5).seconds());
316
    /// ```
317
0
    pub fn seconds_f32(seconds: f32) -> Self {
318
0
        Self::new_unchecked(seconds as _, ((seconds % 1.) * 1_000_000_000.) as _)
319
0
    }
320
321
    /// Create a new `Duration` with the given number of milliseconds.
322
    ///
323
    /// ```rust
324
    /// # use time::{Duration, ext::NumericalDuration};
325
    /// assert_eq!(Duration::milliseconds(1), 1_000.microseconds());
326
    /// assert_eq!(Duration::milliseconds(-1), (-1_000).microseconds());
327
    /// ```
328
0
    pub const fn milliseconds(milliseconds: i64) -> Self {
329
0
        Self::new_unchecked(
330
0
            milliseconds / 1_000,
331
0
            ((milliseconds % 1_000) * 1_000_000) as _,
332
        )
333
0
    }
334
335
    /// Create a new `Duration` with the given number of microseconds.
336
    ///
337
    /// ```rust
338
    /// # use time::{Duration, ext::NumericalDuration};
339
    /// assert_eq!(Duration::microseconds(1), 1_000.nanoseconds());
340
    /// assert_eq!(Duration::microseconds(-1), (-1_000).nanoseconds());
341
    /// ```
342
0
    pub const fn microseconds(microseconds: i64) -> Self {
343
0
        Self::new_unchecked(
344
0
            microseconds / 1_000_000,
345
0
            ((microseconds % 1_000_000) * 1_000) as _,
346
        )
347
0
    }
348
349
    /// Create a new `Duration` with the given number of nanoseconds.
350
    ///
351
    /// ```rust
352
    /// # use time::{Duration, ext::NumericalDuration};
353
    /// assert_eq!(Duration::nanoseconds(1), 1.microseconds() / 1_000);
354
    /// assert_eq!(Duration::nanoseconds(-1), (-1).microseconds() / 1_000);
355
    /// ```
356
0
    pub const fn nanoseconds(nanoseconds: i64) -> Self {
357
0
        Self::new_unchecked(
358
0
            nanoseconds / 1_000_000_000,
359
0
            (nanoseconds % 1_000_000_000) as _,
360
        )
361
0
    }
362
363
    /// Create a new `Duration` with the given number of nanoseconds.
364
    ///
365
    /// As the input range cannot be fully mapped to the output, this should only be used where it's
366
    /// known to result in a valid value.
367
0
    pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
368
0
        Self::new_unchecked(
369
0
            (nanoseconds / 1_000_000_000) as _,
370
0
            (nanoseconds % 1_000_000_000) as _,
371
        )
372
0
    }
373
    // endregion constructors
374
375
    // region: getters
376
    /// Get the number of whole weeks in the duration.
377
    ///
378
    /// ```rust
379
    /// # use time::ext::NumericalDuration;
380
    /// assert_eq!(1.weeks().whole_weeks(), 1);
381
    /// assert_eq!((-1).weeks().whole_weeks(), -1);
382
    /// assert_eq!(6.days().whole_weeks(), 0);
383
    /// assert_eq!((-6).days().whole_weeks(), 0);
384
    /// ```
385
0
    pub const fn whole_weeks(self) -> i64 {
386
0
        self.whole_seconds() / 604_800
387
0
    }
388
389
    /// Get the number of whole days in the duration.
390
    ///
391
    /// ```rust
392
    /// # use time::ext::NumericalDuration;
393
    /// assert_eq!(1.days().whole_days(), 1);
394
    /// assert_eq!((-1).days().whole_days(), -1);
395
    /// assert_eq!(23.hours().whole_days(), 0);
396
    /// assert_eq!((-23).hours().whole_days(), 0);
397
    /// ```
398
0
    pub const fn whole_days(self) -> i64 {
399
0
        self.whole_seconds() / 86_400
400
0
    }
401
402
    /// Get the number of whole hours in the duration.
403
    ///
404
    /// ```rust
405
    /// # use time::ext::NumericalDuration;
406
    /// assert_eq!(1.hours().whole_hours(), 1);
407
    /// assert_eq!((-1).hours().whole_hours(), -1);
408
    /// assert_eq!(59.minutes().whole_hours(), 0);
409
    /// assert_eq!((-59).minutes().whole_hours(), 0);
410
    /// ```
411
0
    pub const fn whole_hours(self) -> i64 {
412
0
        self.whole_seconds() / 3_600
413
0
    }
414
415
    /// Get the number of whole minutes in the duration.
416
    ///
417
    /// ```rust
418
    /// # use time::ext::NumericalDuration;
419
    /// assert_eq!(1.minutes().whole_minutes(), 1);
420
    /// assert_eq!((-1).minutes().whole_minutes(), -1);
421
    /// assert_eq!(59.seconds().whole_minutes(), 0);
422
    /// assert_eq!((-59).seconds().whole_minutes(), 0);
423
    /// ```
424
0
    pub const fn whole_minutes(self) -> i64 {
425
0
        self.whole_seconds() / 60
426
0
    }
427
428
    /// Get the number of whole seconds in the duration.
429
    ///
430
    /// ```rust
431
    /// # use time::ext::NumericalDuration;
432
    /// assert_eq!(1.seconds().whole_seconds(), 1);
433
    /// assert_eq!((-1).seconds().whole_seconds(), -1);
434
    /// assert_eq!(1.minutes().whole_seconds(), 60);
435
    /// assert_eq!((-1).minutes().whole_seconds(), -60);
436
    /// ```
437
0
    pub const fn whole_seconds(self) -> i64 {
438
0
        self.seconds
439
0
    }
440
441
    /// Get the number of fractional seconds in the duration.
442
    ///
443
    /// ```rust
444
    /// # use time::ext::NumericalDuration;
445
    /// assert_eq!(1.5.seconds().as_seconds_f64(), 1.5);
446
    /// assert_eq!((-1.5).seconds().as_seconds_f64(), -1.5);
447
    /// ```
448
0
    pub fn as_seconds_f64(self) -> f64 {
449
0
        self.seconds as f64 + self.nanoseconds as f64 / 1_000_000_000.
450
0
    }
451
452
    /// Get the number of fractional seconds in the duration.
453
    ///
454
    /// ```rust
455
    /// # use time::ext::NumericalDuration;
456
    /// assert_eq!(1.5.seconds().as_seconds_f32(), 1.5);
457
    /// assert_eq!((-1.5).seconds().as_seconds_f32(), -1.5);
458
    /// ```
459
0
    pub fn as_seconds_f32(self) -> f32 {
460
0
        self.seconds as f32 + self.nanoseconds as f32 / 1_000_000_000.
461
0
    }
462
463
    /// Get the number of whole milliseconds in the duration.
464
    ///
465
    /// ```rust
466
    /// # use time::ext::NumericalDuration;
467
    /// assert_eq!(1.seconds().whole_milliseconds(), 1_000);
468
    /// assert_eq!((-1).seconds().whole_milliseconds(), -1_000);
469
    /// assert_eq!(1.milliseconds().whole_milliseconds(), 1);
470
    /// assert_eq!((-1).milliseconds().whole_milliseconds(), -1);
471
    /// ```
472
0
    pub const fn whole_milliseconds(self) -> i128 {
473
0
        self.seconds as i128 * 1_000 + self.nanoseconds as i128 / 1_000_000
474
0
    }
475
476
    /// Get the number of milliseconds past the number of whole seconds.
477
    ///
478
    /// Always in the range `-1_000..1_000`.
479
    ///
480
    /// ```rust
481
    /// # use time::ext::NumericalDuration;
482
    /// assert_eq!(1.4.seconds().subsec_milliseconds(), 400);
483
    /// assert_eq!((-1.4).seconds().subsec_milliseconds(), -400);
484
    /// ```
485
    // Allow the lint, as the value is guaranteed to be less than 1000.
486
0
    pub const fn subsec_milliseconds(self) -> i16 {
487
0
        (self.nanoseconds / 1_000_000) as _
488
0
    }
489
490
    /// Get the number of whole microseconds in the duration.
491
    ///
492
    /// ```rust
493
    /// # use time::ext::NumericalDuration;
494
    /// assert_eq!(1.milliseconds().whole_microseconds(), 1_000);
495
    /// assert_eq!((-1).milliseconds().whole_microseconds(), -1_000);
496
    /// assert_eq!(1.microseconds().whole_microseconds(), 1);
497
    /// assert_eq!((-1).microseconds().whole_microseconds(), -1);
498
    /// ```
499
0
    pub const fn whole_microseconds(self) -> i128 {
500
0
        self.seconds as i128 * 1_000_000 + self.nanoseconds as i128 / 1_000
501
0
    }
502
503
    /// Get the number of microseconds past the number of whole seconds.
504
    ///
505
    /// Always in the range `-1_000_000..1_000_000`.
506
    ///
507
    /// ```rust
508
    /// # use time::ext::NumericalDuration;
509
    /// assert_eq!(1.0004.seconds().subsec_microseconds(), 400);
510
    /// assert_eq!((-1.0004).seconds().subsec_microseconds(), -400);
511
    /// ```
512
0
    pub const fn subsec_microseconds(self) -> i32 {
513
0
        self.nanoseconds / 1_000
514
0
    }
515
516
    /// Get the number of nanoseconds in the duration.
517
    ///
518
    /// ```rust
519
    /// # use time::ext::NumericalDuration;
520
    /// assert_eq!(1.microseconds().whole_nanoseconds(), 1_000);
521
    /// assert_eq!((-1).microseconds().whole_nanoseconds(), -1_000);
522
    /// assert_eq!(1.nanoseconds().whole_nanoseconds(), 1);
523
    /// assert_eq!((-1).nanoseconds().whole_nanoseconds(), -1);
524
    /// ```
525
0
    pub const fn whole_nanoseconds(self) -> i128 {
526
0
        self.seconds as i128 * 1_000_000_000 + self.nanoseconds as i128
527
0
    }
528
529
    /// Get the number of nanoseconds past the number of whole seconds.
530
    ///
531
    /// The returned value will always be in the range `-1_000_000_000..1_000_000_000`.
532
    ///
533
    /// ```rust
534
    /// # use time::ext::NumericalDuration;
535
    /// assert_eq!(1.000_000_400.seconds().subsec_nanoseconds(), 400);
536
    /// assert_eq!((-1.000_000_400).seconds().subsec_nanoseconds(), -400);
537
    /// ```
538
0
    pub const fn subsec_nanoseconds(self) -> i32 {
539
0
        self.nanoseconds
540
0
    }
541
    // endregion getters
542
543
    // region: checked arithmetic
544
    /// Computes `self + rhs`, returning `None` if an overflow occurred.
545
    ///
546
    /// ```rust
547
    /// # use time::{Duration, ext::NumericalDuration};
548
    /// assert_eq!(5.seconds().checked_add(5.seconds()), Some(10.seconds()));
549
    /// assert_eq!(Duration::MAX.checked_add(1.nanoseconds()), None);
550
    /// assert_eq!((-5).seconds().checked_add(5.seconds()), Some(0.seconds()));
551
    /// ```
552
0
    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
553
0
        let mut seconds = const_try_opt!(self.seconds.checked_add(rhs.seconds));
554
0
        let mut nanoseconds = self.nanoseconds + rhs.nanoseconds;
555
556
0
        if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
557
0
            nanoseconds -= 1_000_000_000;
558
0
            seconds = const_try_opt!(seconds.checked_add(1));
559
0
        } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
560
0
            nanoseconds += 1_000_000_000;
561
0
            seconds = const_try_opt!(seconds.checked_sub(1));
562
0
        }
563
564
0
        Some(Self::new_unchecked(seconds, nanoseconds))
565
0
    }
566
567
    /// Computes `self - rhs`, returning `None` if an overflow occurred.
568
    ///
569
    /// ```rust
570
    /// # use time::{Duration, ext::NumericalDuration};
571
    /// assert_eq!(5.seconds().checked_sub(5.seconds()), Some(Duration::ZERO));
572
    /// assert_eq!(Duration::MIN.checked_sub(1.nanoseconds()), None);
573
    /// assert_eq!(5.seconds().checked_sub(10.seconds()), Some((-5).seconds()));
574
    /// ```
575
0
    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
576
0
        let mut seconds = const_try_opt!(self.seconds.checked_sub(rhs.seconds));
577
0
        let mut nanoseconds = self.nanoseconds - rhs.nanoseconds;
578
579
0
        if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
580
0
            nanoseconds -= 1_000_000_000;
581
0
            seconds = const_try_opt!(seconds.checked_add(1));
582
0
        } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
583
0
            nanoseconds += 1_000_000_000;
584
0
            seconds = const_try_opt!(seconds.checked_sub(1));
585
0
        }
586
587
0
        Some(Self::new_unchecked(seconds, nanoseconds))
588
0
    }
589
590
    /// Computes `self * rhs`, returning `None` if an overflow occurred.
591
    ///
592
    /// ```rust
593
    /// # use time::{Duration, ext::NumericalDuration};
594
    /// assert_eq!(5.seconds().checked_mul(2), Some(10.seconds()));
595
    /// assert_eq!(5.seconds().checked_mul(-2), Some((-10).seconds()));
596
    /// assert_eq!(5.seconds().checked_mul(0), Some(0.seconds()));
597
    /// assert_eq!(Duration::MAX.checked_mul(2), None);
598
    /// assert_eq!(Duration::MIN.checked_mul(2), None);
599
    /// ```
600
0
    pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
601
        // Multiply nanoseconds as i64, because it cannot overflow that way.
602
0
        let total_nanos = self.nanoseconds as i64 * rhs as i64;
603
0
        let extra_secs = total_nanos / 1_000_000_000;
604
0
        let nanoseconds = (total_nanos % 1_000_000_000) as _;
605
0
        let seconds = const_try_opt!(
606
0
            const_try_opt!(self.seconds.checked_mul(rhs as _)).checked_add(extra_secs)
607
        );
608
609
0
        Some(Self::new_unchecked(seconds, nanoseconds))
610
0
    }
611
612
    /// Computes `self / rhs`, returning `None` if `rhs == 0` or if the result would overflow.
613
    ///
614
    /// ```rust
615
    /// # use time::ext::NumericalDuration;
616
    /// assert_eq!(10.seconds().checked_div(2), Some(5.seconds()));
617
    /// assert_eq!(10.seconds().checked_div(-2), Some((-5).seconds()));
618
    /// assert_eq!(1.seconds().checked_div(0), None);
619
    /// ```
620
0
    pub const fn checked_div(self, rhs: i32) -> Option<Self> {
621
0
        let seconds = const_try_opt!(self.seconds.checked_div(rhs as i64));
622
0
        let carry = self.seconds - seconds * (rhs as i64);
623
0
        let extra_nanos = const_try_opt!((carry * 1_000_000_000).checked_div(rhs as i64));
624
0
        let nanoseconds = const_try_opt!(self.nanoseconds.checked_div(rhs)) + (extra_nanos as i32);
625
626
0
        Some(Self::new_unchecked(seconds, nanoseconds))
627
0
    }
628
    // endregion checked arithmetic
629
630
    // region: saturating arithmetic
631
    /// Computes `self + rhs`, saturating if an overflow occurred.
632
    ///
633
    /// ```rust
634
    /// # use time::{Duration, ext::NumericalDuration};
635
    /// assert_eq!(5.seconds().saturating_add(5.seconds()), 10.seconds());
636
    /// assert_eq!(Duration::MAX.saturating_add(1.nanoseconds()), Duration::MAX);
637
    /// assert_eq!(
638
    ///     Duration::MIN.saturating_add((-1).nanoseconds()),
639
    ///     Duration::MIN
640
    /// );
641
    /// assert_eq!((-5).seconds().saturating_add(5.seconds()), Duration::ZERO);
642
    /// ```
643
0
    pub const fn saturating_add(self, rhs: Self) -> Self {
644
0
        let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
645
0
        if overflow {
646
0
            if self.seconds > 0 {
647
0
                return Self::MAX;
648
0
            }
649
0
            return Self::MIN;
650
0
        }
651
0
        let mut nanoseconds = self.nanoseconds + rhs.nanoseconds;
652
653
0
        if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
654
0
            nanoseconds -= 1_000_000_000;
655
0
            seconds = match seconds.checked_add(1) {
656
0
                Some(seconds) => seconds,
657
0
                None => return Self::MAX,
658
            };
659
0
        } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
660
0
            nanoseconds += 1_000_000_000;
661
0
            seconds = match seconds.checked_sub(1) {
662
0
                Some(seconds) => seconds,
663
0
                None => return Self::MIN,
664
            };
665
0
        }
666
667
0
        Self::new_unchecked(seconds, nanoseconds)
668
0
    }
669
670
    /// Computes `self - rhs`, saturating if an overflow occurred.
671
    ///
672
    /// ```rust
673
    /// # use time::{Duration, ext::NumericalDuration};
674
    /// assert_eq!(5.seconds().saturating_sub(5.seconds()), Duration::ZERO);
675
    /// assert_eq!(Duration::MIN.saturating_sub(1.nanoseconds()), Duration::MIN);
676
    /// assert_eq!(
677
    ///     Duration::MAX.saturating_sub((-1).nanoseconds()),
678
    ///     Duration::MAX
679
    /// );
680
    /// assert_eq!(5.seconds().saturating_sub(10.seconds()), (-5).seconds());
681
    /// ```
682
0
    pub const fn saturating_sub(self, rhs: Self) -> Self {
683
0
        let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
684
0
        if overflow {
685
0
            if self.seconds > 0 {
686
0
                return Self::MAX;
687
0
            }
688
0
            return Self::MIN;
689
0
        }
690
0
        let mut nanoseconds = self.nanoseconds - rhs.nanoseconds;
691
692
0
        if nanoseconds >= 1_000_000_000 || seconds < 0 && nanoseconds > 0 {
693
0
            nanoseconds -= 1_000_000_000;
694
0
            seconds = match seconds.checked_add(1) {
695
0
                Some(seconds) => seconds,
696
0
                None => return Self::MAX,
697
            };
698
0
        } else if nanoseconds <= -1_000_000_000 || seconds > 0 && nanoseconds < 0 {
699
0
            nanoseconds += 1_000_000_000;
700
0
            seconds = match seconds.checked_sub(1) {
701
0
                Some(seconds) => seconds,
702
0
                None => return Self::MIN,
703
            };
704
0
        }
705
706
0
        Self::new_unchecked(seconds, nanoseconds)
707
0
    }
708
709
    /// Computes `self * rhs`, saturating if an overflow occurred.
710
    ///
711
    /// ```rust
712
    /// # use time::{Duration, ext::NumericalDuration};
713
    /// assert_eq!(5.seconds().saturating_mul(2), 10.seconds());
714
    /// assert_eq!(5.seconds().saturating_mul(-2), (-10).seconds());
715
    /// assert_eq!(5.seconds().saturating_mul(0), Duration::ZERO);
716
    /// assert_eq!(Duration::MAX.saturating_mul(2), Duration::MAX);
717
    /// assert_eq!(Duration::MIN.saturating_mul(2), Duration::MIN);
718
    /// assert_eq!(Duration::MAX.saturating_mul(-2), Duration::MIN);
719
    /// assert_eq!(Duration::MIN.saturating_mul(-2), Duration::MAX);
720
    /// ```
721
0
    pub const fn saturating_mul(self, rhs: i32) -> Self {
722
        // Multiply nanoseconds as i64, because it cannot overflow that way.
723
0
        let total_nanos = self.nanoseconds as i64 * rhs as i64;
724
0
        let extra_secs = total_nanos / 1_000_000_000;
725
0
        let nanoseconds = (total_nanos % 1_000_000_000) as _;
726
0
        let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as _);
727
0
        if overflow1 {
728
0
            if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
729
0
                return Self::MAX;
730
0
            }
731
0
            return Self::MIN;
732
0
        }
733
0
        let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
734
0
        if overflow2 {
735
0
            if self.seconds > 0 && rhs > 0 {
736
0
                return Self::MAX;
737
0
            }
738
0
            return Self::MIN;
739
0
        }
740
741
0
        Self::new_unchecked(seconds, nanoseconds)
742
0
    }
743
    // endregion saturating arithmetic
744
745
    /// Runs a closure, returning the duration of time it took to run. The return value of the
746
    /// closure is provided in the second part of the tuple.
747
    #[cfg(feature = "std")]
748
0
    pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
749
0
        let start = Instant::now();
750
0
        let return_value = f();
751
0
        let end = Instant::now();
752
753
0
        (end - start, return_value)
754
0
    }
755
}
756
757
// region: trait impls
758
/// The format returned by this implementation is not stable and must not be relied upon.
759
///
760
/// By default this produces an exact, full-precision printout of the duration.
761
/// For a concise, rounded printout instead, you can use the `.N` format specifier:
762
///
763
/// ```
764
/// # use time::Duration;
765
/// #
766
/// let duration = Duration::new(123456, 789011223);
767
/// println!("{:.3}", duration);
768
/// ```
769
///
770
/// For the purposes of this implementation, a day is exactly 24 hours and a minute is exactly 60
771
/// seconds.
772
impl fmt::Display for Duration {
773
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
774
0
        if self.is_negative() {
775
0
            f.write_str("-")?;
776
0
        }
777
778
0
        if let Some(_precision) = f.precision() {
779
            // Concise, rounded representation.
780
781
0
            if self.is_zero() {
782
                // Write a zero value with the requested precision.
783
0
                return (0.).fmt(f).and_then(|_| f.write_str("s"));
784
0
            }
785
786
            /// Format the first item that produces a value greater than 1 and then break.
787
            macro_rules! item {
788
                ($name:literal, $value:expr) => {
789
                    let value = $value;
790
                    if value >= 1.0 {
791
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}
792
                    }
793
                };
794
            }
795
796
            // Even if this produces a de-normal float, because we're rounding we don't really care.
797
0
            let seconds = self.unsigned_abs().as_secs_f64();
798
799
0
            item!("d", seconds / 86_400.);
800
0
            item!("h", seconds / 3_600.);
801
0
            item!("m", seconds / 60.);
802
0
            item!("s", seconds);
803
0
            item!("ms", seconds * 1_000.);
804
0
            item!("µs", seconds * 1_000_000.);
805
0
            item!("ns", seconds * 1_000_000_000.);
806
        } else {
807
            // Precise, but verbose representation.
808
809
0
            if self.is_zero() {
810
0
                return f.write_str("0s");
811
0
            }
812
813
            /// Format a single item.
814
            macro_rules! item {
815
                ($name:literal, $value:expr) => {
816
                    match $value {
817
                        0 => Ok(()),
818
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}
819
                    }
820
                };
821
            }
822
823
0
            let seconds = self.seconds.unsigned_abs();
824
0
            let nanoseconds = self.nanoseconds.unsigned_abs();
825
826
0
            item!("d", seconds / 86_400)?;
827
0
            item!("h", seconds / 3_600 % 24)?;
828
0
            item!("m", seconds / 60 % 60)?;
829
0
            item!("s", seconds % 60)?;
830
0
            item!("ms", nanoseconds / 1_000_000)?;
831
0
            item!("µs", nanoseconds / 1_000 % 1_000)?;
832
0
            item!("ns", nanoseconds % 1_000)?;
833
        }
834
835
0
        Ok(())
836
0
    }
837
}
838
839
impl TryFrom<StdDuration> for Duration {
840
    type Error = error::ConversionRange;
841
842
0
    fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
843
0
        Ok(Self::new(
844
0
            original
845
0
                .as_secs()
846
0
                .try_into()
847
0
                .map_err(|_| error::ConversionRange)?,
848
0
            original.subsec_nanos() as _,
849
        ))
850
0
    }
851
}
852
853
impl TryFrom<Duration> for StdDuration {
854
    type Error = error::ConversionRange;
855
856
0
    fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
857
0
        Ok(Self::new(
858
0
            duration
859
0
                .seconds
860
0
                .try_into()
861
0
                .map_err(|_| error::ConversionRange)?,
862
0
            duration
863
0
                .nanoseconds
864
0
                .try_into()
865
0
                .map_err(|_| error::ConversionRange)?,
866
        ))
867
0
    }
868
}
869
870
impl Add for Duration {
871
    type Output = Self;
872
873
0
    fn add(self, rhs: Self) -> Self::Output {
874
0
        self.checked_add(rhs)
875
0
            .expect("overflow when adding durations")
876
0
    }
877
}
878
879
impl Add<StdDuration> for Duration {
880
    type Output = Self;
881
882
0
    fn add(self, std_duration: StdDuration) -> Self::Output {
883
0
        self + Self::try_from(std_duration)
884
0
            .expect("overflow converting `std::time::Duration` to `time::Duration`")
885
0
    }
886
}
887
888
impl Add<Duration> for StdDuration {
889
    type Output = Duration;
890
891
0
    fn add(self, rhs: Duration) -> Self::Output {
892
0
        rhs + self
893
0
    }
894
}
895
896
impl_add_assign!(Duration: Self, StdDuration);
897
898
impl AddAssign<Duration> for StdDuration {
899
0
    fn add_assign(&mut self, rhs: Duration) {
900
0
        *self = (*self + rhs).try_into().expect(
901
0
            "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
902
0
             change the type.",
903
0
        );
904
0
    }
905
}
906
907
impl Neg for Duration {
908
    type Output = Self;
909
910
0
    fn neg(self) -> Self::Output {
911
0
        Self::new_unchecked(-self.seconds, -self.nanoseconds)
912
0
    }
913
}
914
915
impl Sub for Duration {
916
    type Output = Self;
917
918
0
    fn sub(self, rhs: Self) -> Self::Output {
919
0
        self.checked_sub(rhs)
920
0
            .expect("overflow when subtracting durations")
921
0
    }
922
}
923
924
impl Sub<StdDuration> for Duration {
925
    type Output = Self;
926
927
0
    fn sub(self, rhs: StdDuration) -> Self::Output {
928
0
        self - Self::try_from(rhs)
929
0
            .expect("overflow converting `std::time::Duration` to `time::Duration`")
930
0
    }
931
}
932
933
impl Sub<Duration> for StdDuration {
934
    type Output = Duration;
935
936
0
    fn sub(self, rhs: Duration) -> Self::Output {
937
0
        Duration::try_from(self)
938
0
            .expect("overflow converting `std::time::Duration` to `time::Duration`")
939
0
            - rhs
940
0
    }
941
}
942
943
impl_sub_assign!(Duration: Self, StdDuration);
944
945
impl SubAssign<Duration> for StdDuration {
946
0
    fn sub_assign(&mut self, rhs: Duration) {
947
0
        *self = (*self - rhs).try_into().expect(
948
0
            "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
949
0
             change the type.",
950
0
        );
951
0
    }
952
}
953
954
/// Implement `Mul` (reflexively) and `Div` for `Duration` for various types.
955
macro_rules! duration_mul_div_int {
956
    ($($type:ty),+) => {$(
957
        impl Mul<$type> for Duration {
958
            type Output = Self;
959
960
0
            fn mul(self, rhs: $type) -> Self::Output {
961
0
                Self::nanoseconds_i128(
962
0
                    self.whole_nanoseconds()
963
0
                        .checked_mul(rhs as _)
964
0
                        .expect("overflow when multiplying duration")
965
                )
966
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
967
        }
968
969
        impl Mul<Duration> for $type {
970
            type Output = Duration;
971
972
0
            fn mul(self, rhs: Duration) -> Self::Output {
973
0
                rhs * self
974
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
975
        }
976
977
        impl Div<$type> for Duration {
978
            type Output = Self;
979
980
0
            fn div(self, rhs: $type) -> Self::Output {
981
0
                Self::nanoseconds_i128(self.whole_nanoseconds() / rhs as i128)
982
0
            }
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
Unexecuted instantiation: <time::duration::Duration as core::ops::arith::Div<u8>>::div
983
        }
984
    )+};
985
}
986
duration_mul_div_int![i8, i16, i32, u8, u16, u32];
987
988
impl Mul<f32> for Duration {
989
    type Output = Self;
990
991
0
    fn mul(self, rhs: f32) -> Self::Output {
992
0
        Self::seconds_f32(self.as_seconds_f32() * rhs)
993
0
    }
994
}
995
996
impl Mul<Duration> for f32 {
997
    type Output = Duration;
998
999
0
    fn mul(self, rhs: Duration) -> Self::Output {
1000
0
        rhs * self
1001
0
    }
1002
}
1003
1004
impl Mul<f64> for Duration {
1005
    type Output = Self;
1006
1007
0
    fn mul(self, rhs: f64) -> Self::Output {
1008
0
        Self::seconds_f64(self.as_seconds_f64() * rhs)
1009
0
    }
1010
}
1011
1012
impl Mul<Duration> for f64 {
1013
    type Output = Duration;
1014
1015
0
    fn mul(self, rhs: Duration) -> Self::Output {
1016
0
        rhs * self
1017
0
    }
1018
}
1019
1020
impl_mul_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1021
1022
impl Div<f32> for Duration {
1023
    type Output = Self;
1024
1025
0
    fn div(self, rhs: f32) -> Self::Output {
1026
0
        Self::seconds_f32(self.as_seconds_f32() / rhs)
1027
0
    }
1028
}
1029
1030
impl Div<f64> for Duration {
1031
    type Output = Self;
1032
1033
0
    fn div(self, rhs: f64) -> Self::Output {
1034
0
        Self::seconds_f64(self.as_seconds_f64() / rhs)
1035
0
    }
1036
}
1037
1038
impl_div_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1039
1040
impl Div for Duration {
1041
    type Output = f64;
1042
1043
0
    fn div(self, rhs: Self) -> Self::Output {
1044
0
        self.as_seconds_f64() / rhs.as_seconds_f64()
1045
0
    }
1046
}
1047
1048
impl Div<StdDuration> for Duration {
1049
    type Output = f64;
1050
1051
0
    fn div(self, rhs: StdDuration) -> Self::Output {
1052
0
        self.as_seconds_f64() / rhs.as_secs_f64()
1053
0
    }
1054
}
1055
1056
impl Div<Duration> for StdDuration {
1057
    type Output = f64;
1058
1059
0
    fn div(self, rhs: Duration) -> Self::Output {
1060
0
        self.as_secs_f64() / rhs.as_seconds_f64()
1061
0
    }
1062
}
1063
1064
impl PartialEq<StdDuration> for Duration {
1065
0
    fn eq(&self, rhs: &StdDuration) -> bool {
1066
0
        Ok(*self) == Self::try_from(*rhs)
1067
0
    }
1068
}
1069
1070
impl PartialEq<Duration> for StdDuration {
1071
0
    fn eq(&self, rhs: &Duration) -> bool {
1072
0
        rhs == self
1073
0
    }
1074
}
1075
1076
impl PartialOrd<StdDuration> for Duration {
1077
0
    fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1078
0
        if rhs.as_secs() > i64::MAX as _ {
1079
0
            return Some(Ordering::Less);
1080
0
        }
1081
1082
        Some(
1083
0
            self.seconds
1084
0
                .cmp(&(rhs.as_secs() as _))
1085
0
                .then_with(|| self.nanoseconds.cmp(&(rhs.subsec_nanos() as _))),
1086
        )
1087
0
    }
1088
}
1089
1090
impl PartialOrd<Duration> for StdDuration {
1091
0
    fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1092
0
        rhs.partial_cmp(self).map(Ordering::reverse)
1093
0
    }
1094
}
1095
1096
impl Sum for Duration {
1097
0
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1098
0
        iter.reduce(|a, b| a + b).unwrap_or_default()
1099
0
    }
1100
}
1101
1102
impl<'a> Sum<&'a Self> for Duration {
1103
0
    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1104
0
        iter.copied().sum()
1105
0
    }
1106
}
1107
// endregion trait impls