1use core::cmp::Ordering;
4use core::fmt;
5use core::iter::Sum;
6use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
7use core::time::Duration as StdDuration;
8#[cfg(feature = "std")]
9use std::time::SystemTime;
10
11use deranged::RangedI32;
12use num_conv::prelude::*;
13
14use crate::convert::*;
15use crate::error;
16use 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)]
21use crate::Instant;
22
23#[repr(u32)]
26#[derive(#[automatically_derived]
impl ::core::clone::Clone for Padding {
#[inline]
fn clone(&self) -> Padding { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Padding { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Padding {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Optimize")
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Padding {
#[inline]
fn eq(&self, other: &Padding) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Padding {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Padding {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialOrd for Padding {
#[inline]
fn partial_cmp(&self, other: &Padding)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Padding {
#[inline]
fn cmp(&self, other: &Padding) -> ::core::cmp::Ordering {
::core::cmp::Ordering::Equal
}
}Ord)]
27pub(crate) enum Padding {
28 #[allow(clippy::missing_docs_in_private_items)]
29 Optimize,
30}
31
32type Nanoseconds =
34 RangedI32<{ -Nanosecond::per_t::<i32>(Second) + 1 }, { Nanosecond::per_t::<i32>(Second) - 1 }>;
35
36)]
43pub struct Duration {
44 seconds: i64,
46 nanoseconds: Nanoseconds,
49 padding: Padding,
50}
51
52impl fmt::Debug for Duration {
53 #[inline]
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 f.debug_struct("Duration")
56 .field("seconds", &self.seconds)
57 .field("nanoseconds", &self.nanoseconds)
58 .finish()
59 }
60}
61
62impl Default for Duration {
63 #[inline]
64 fn default() -> Self {
65 Self {
66 seconds: 0,
67 nanoseconds: Nanoseconds::new_static::<0>(),
68 padding: Padding::Optimize,
69 }
70 }
71}
72
73#[rustfmt::skip] 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 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 (0u64, 0u32)
107 } else if exp < 0 {
108 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 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 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 let secs = u64::from(mant) << (exp - $mant_bits);
161 (secs, 0)
162 } else if bits == (i64::MIN as $float_ty).to_bits() {
163 break 'value Self::new_ranged_unchecked(i64::MIN, Nanoseconds::new_static::<0>());
169 } else if $secs.is_nan() {
170 $is_nan
173 } else {
174 $is_overflow
175 };
176
177 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 unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
190 }
191 }};
192}
193
194impl Duration {
195 pub const ZERO: Self = Self::seconds(0);
202
203 pub const NANOSECOND: Self = Self::nanoseconds(1);
210
211 pub const MICROSECOND: Self = Self::microseconds(1);
218
219 pub const MILLISECOND: Self = Self::milliseconds(1);
226
227 pub const SECOND: Self = Self::seconds(1);
234
235 pub const MINUTE: Self = Self::minutes(1);
242
243 pub const HOUR: Self = Self::hours(1);
250
251 pub const DAY: Self = Self::days(1);
258
259 pub const WEEK: Self = Self::weeks(1);
266
267 pub const MIN: Self = Self::new_ranged(i64::MIN, Nanoseconds::MIN);
269
270 pub const MAX: Self = Self::new_ranged(i64::MAX, Nanoseconds::MAX);
272
273 #[inline]
281 pub const fn is_zero(self) -> bool {
282 self.seconds == 0 && self.nanoseconds.get() == 0
283 }
284
285 #[inline]
294 pub const fn is_negative(self) -> bool {
295 self.seconds < 0 || self.nanoseconds.get() < 0
296 }
297
298 #[inline]
307 pub const fn is_positive(self) -> bool {
308 self.seconds > 0 || self.nanoseconds.get() > 0
309 }
310
311 #[inline]
322 pub const fn abs(self) -> Self {
323 match self.seconds.checked_abs() {
324 Some(seconds) => Self::new_ranged_unchecked(seconds, self.nanoseconds.abs()),
325 None => Self::MAX,
326 }
327 }
328
329 #[inline]
339 pub const fn unsigned_abs(self) -> StdDuration {
340 StdDuration::new(
341 self.seconds.unsigned_abs(),
342 self.nanoseconds.get().unsigned_abs(),
343 )
344 }
345
346 #[inline]
355 #[track_caller]
356 pub(crate) const unsafe fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
357 Self::new_ranged_unchecked(
358 seconds,
359 unsafe { Nanoseconds::new_unchecked(nanoseconds) },
361 )
362 }
363
364 #[inline]
366 #[track_caller]
367 pub(crate) const fn new_ranged_unchecked(seconds: i64, nanoseconds: Nanoseconds) -> Self {
368 if seconds < 0 {
369 if true {
if !(nanoseconds.get() <= 0) {
::core::panicking::panic("assertion failed: nanoseconds.get() <= 0")
};
};debug_assert!(nanoseconds.get() <= 0);
370 } else if seconds > 0 {
371 if true {
if !(nanoseconds.get() >= 0) {
::core::panicking::panic("assertion failed: nanoseconds.get() >= 0")
};
};debug_assert!(nanoseconds.get() >= 0);
372 }
373
374 Self {
375 seconds,
376 nanoseconds,
377 padding: Padding::Optimize,
378 }
379 }
380
381 #[inline]
395 #[track_caller]
396 pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
397 seconds = match seconds.checked_add(nanoseconds as i64 /
Nanosecond::per_t::<i64>(Second)) {
Some(value) => value,
None => crate::expect_failed("overflow constructing `time::Duration`"),
}expect_opt!(
398 seconds.checked_add(nanoseconds as i64 / Nanosecond::per_t::<i64>(Second)),
399 "overflow constructing `time::Duration`"
400 );
401 nanoseconds %= Nanosecond::per_t::<i32>(Second);
402
403 if seconds > 0 && nanoseconds < 0 {
404 seconds -= 1;
406 nanoseconds += Nanosecond::per_t::<i32>(Second);
407 } else if seconds < 0 && nanoseconds > 0 {
408 seconds += 1;
410 nanoseconds -= Nanosecond::per_t::<i32>(Second);
411 }
412
413 unsafe { Self::new_unchecked(seconds, nanoseconds) }
415 }
416
417 #[inline]
419 pub(crate) const fn new_ranged(mut seconds: i64, mut nanoseconds: Nanoseconds) -> Self {
420 if seconds > 0 && nanoseconds.get() < 0 {
421 seconds -= 1;
423 nanoseconds = unsafe {
426 Nanoseconds::new_unchecked(nanoseconds.get() + Nanosecond::per_t::<i32>(Second))
427 };
428 } else if seconds < 0 && nanoseconds.get() > 0 {
429 seconds += 1;
431 nanoseconds = unsafe {
434 Nanoseconds::new_unchecked(nanoseconds.get() - Nanosecond::per_t::<i32>(Second))
435 };
436 }
437
438 Self::new_ranged_unchecked(seconds, nanoseconds)
439 }
440
441 #[inline]
453 #[track_caller]
454 pub const fn weeks(weeks: i64) -> Self {
455 Self::seconds(match weeks.checked_mul(Second::per_t(Week)) {
Some(value) => value,
None => crate::expect_failed("overflow constructing `time::Duration`"),
}expect_opt!(
456 weeks.checked_mul(Second::per_t(Week)),
457 "overflow constructing `time::Duration`"
458 ))
459 }
460
461 #[inline]
473 #[track_caller]
474 pub const fn days(days: i64) -> Self {
475 Self::seconds(match days.checked_mul(Second::per_t(Day)) {
Some(value) => value,
None => crate::expect_failed("overflow constructing `time::Duration`"),
}expect_opt!(
476 days.checked_mul(Second::per_t(Day)),
477 "overflow constructing `time::Duration`"
478 ))
479 }
480
481 #[inline]
493 #[track_caller]
494 pub const fn hours(hours: i64) -> Self {
495 Self::seconds(match hours.checked_mul(Second::per_t(Hour)) {
Some(value) => value,
None => crate::expect_failed("overflow constructing `time::Duration`"),
}expect_opt!(
496 hours.checked_mul(Second::per_t(Hour)),
497 "overflow constructing `time::Duration`"
498 ))
499 }
500
501 #[inline]
513 #[track_caller]
514 pub const fn minutes(minutes: i64) -> Self {
515 Self::seconds(match minutes.checked_mul(Second::per_t(Minute)) {
Some(value) => value,
None => crate::expect_failed("overflow constructing `time::Duration`"),
}expect_opt!(
516 minutes.checked_mul(Second::per_t(Minute)),
517 "overflow constructing `time::Duration`"
518 ))
519 }
520
521 #[inline]
528 pub const fn seconds(seconds: i64) -> Self {
529 Self::new_ranged_unchecked(seconds, Nanoseconds::new_static::<0>())
530 }
531
532 #[inline]
540 #[track_caller]
541 pub fn seconds_f64(seconds: f64) -> Self {
542 {
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 11) / 2;
const MANT_MASK: u64 = (1 << 52) - 1;
const EXP_MASK: u64 = (1 << 11) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 52) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u128>::from(mant) << (44 + exp);
let nanos_offset = 52 + 44;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 52 {
let secs = u64::from(mant >> (52 - exp));
let t = <u128>::from((mant << exp) & MANT_MASK);
let nanos_offset = 52;
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 52);
(secs, 0)
} else if bits == (i64::MIN as f64).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() {
crate::expect_failed("passed NaN to `time::Duration::seconds_f64`")
} else {
crate::expect_failed("overflow constructing `time::Duration`")
};
let mask = (bits as i64) >> (52 + 11);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
543 secs = seconds,
544 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 is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f64`"),
552 is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
553 )
554 }
555
556 #[inline]
564 #[track_caller]
565 pub fn seconds_f32(seconds: f32) -> Self {
566 {
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 8) / 2;
const MANT_MASK: u32 = (1 << 23) - 1;
const EXP_MASK: u32 = (1 << 8) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 23) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u64>::from(mant) << (41 + exp);
let nanos_offset = 23 + 41;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 23 {
let secs = u64::from(mant >> (23 - exp));
let t = <u64>::from((mant << exp) & MANT_MASK);
let nanos_offset = 23;
let nanos_tmp = Nanosecond::per_t::<u64>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 23);
(secs, 0)
} else if bits == (i64::MIN as f32).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() {
crate::expect_failed("passed NaN to `time::Duration::seconds_f32`")
} else {
crate::expect_failed("overflow constructing `time::Duration`")
};
let mask = (bits as i32) >> (23 + 8);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
567 secs = seconds,
568 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 is_nan = crate::expect_failed("passed NaN to `time::Duration::seconds_f32`"),
576 is_overflow = crate::expect_failed("overflow constructing `time::Duration`"),
577 )
578 }
579
580 #[inline]
603 pub fn saturating_seconds_f64(seconds: f64) -> Self {
604 {
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 11) / 2;
const MANT_MASK: u64 = (1 << 52) - 1;
const EXP_MASK: u64 = (1 << 11) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 52) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u128>::from(mant) << (44 + exp);
let nanos_offset = 52 + 44;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 52 {
let secs = u64::from(mant >> (52 - exp));
let t = <u128>::from((mant << exp) & MANT_MASK);
let nanos_offset = 52;
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 52);
(secs, 0)
} else if bits == (i64::MIN as f64).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() {
return Self::ZERO
} else {
return if seconds < 0.0 { Self::MIN } else { Self::MAX }
};
let mask = (bits as i64) >> (52 + 11);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
605 secs = seconds,
606 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 is_nan = return Self::ZERO,
614 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
615 )
616 }
617
618 #[inline]
641 pub fn saturating_seconds_f32(seconds: f32) -> Self {
642 {
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 8) / 2;
const MANT_MASK: u32 = (1 << 23) - 1;
const EXP_MASK: u32 = (1 << 8) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 23) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u64>::from(mant) << (41 + exp);
let nanos_offset = 23 + 41;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 23 {
let secs = u64::from(mant >> (23 - exp));
let t = <u64>::from((mant << exp) & MANT_MASK);
let nanos_offset = 23;
let nanos_tmp = Nanosecond::per_t::<u64>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 23);
(secs, 0)
} else if bits == (i64::MIN as f32).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() {
return Self::ZERO
} else {
return if seconds < 0.0 { Self::MIN } else { Self::MAX }
};
let mask = (bits as i32) >> (23 + 8);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
643 secs = seconds,
644 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 is_nan = return Self::ZERO,
652 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
653 )
654 }
655
656 #[inline]
669 pub fn checked_seconds_f64(seconds: f64) -> Option<Self> {
670 Some({
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 11) / 2;
const MANT_MASK: u64 = (1 << 52) - 1;
const EXP_MASK: u64 = (1 << 11) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 52) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u128>::from(mant) << (44 + exp);
let nanos_offset = 52 + 44;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 52 {
let secs = u64::from(mant >> (52 - exp));
let t = <u128>::from((mant << exp) & MANT_MASK);
let nanos_offset = 52;
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (52 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 52);
(secs, 0)
} else if bits == (i64::MIN as f64).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() { return None } else { return None };
let mask = (bits as i64) >> (52 + 11);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
671 secs = seconds,
672 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 is_nan = return None,
680 is_overflow = return None,
681 ))
682 }
683
684 #[inline]
697 pub fn checked_seconds_f32(seconds: f32) -> Option<Self> {
698 Some({
'value:
{
const MIN_EXP: i16 = 1 - (1i16 << 8) / 2;
const MANT_MASK: u32 = (1 << 23) - 1;
const EXP_MASK: u32 = (1 << 8) - 1;
let bits = seconds.to_bits();
let mant = (bits & MANT_MASK) | (MANT_MASK + 1);
let exp = ((bits >> 23) & EXP_MASK) as i16 + MIN_EXP;
let (secs, nanos) =
if exp < -31 {
(0u64, 0u32)
} else if exp < 0 {
let t = <u64>::from(mant) << (41 + exp);
let nanos_offset = 23 + 41;
let nanos_tmp =
Nanosecond::per_t::<u128>(Second) * u128::from(t);
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(0, nanos)
} else { (1, 0) }
} else if exp < 23 {
let secs = u64::from(mant >> (23 - exp));
let t = <u64>::from((mant << exp) & MANT_MASK);
let nanos_offset = 23;
let nanos_tmp = Nanosecond::per_t::<u64>(Second) * t;
let nanos = (nanos_tmp >> nanos_offset) as u32;
let rem_mask = (1 << nanos_offset) - 1;
let rem_msb_mask = 1 << (nanos_offset - 1);
let rem = nanos_tmp & rem_mask;
let is_tie = rem == rem_msb_mask;
let is_even = (nanos & 1) == 0;
let rem_msb = nanos_tmp & rem_msb_mask == 0;
let add_ns = !(rem_msb || (is_even && is_tie));
let nanos = nanos + add_ns as u32;
if (23 == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
(secs, nanos)
} else { (secs + 1, 0) }
} else if exp < 63 {
let secs = u64::from(mant) << (exp - 23);
(secs, 0)
} else if bits == (i64::MIN as f32).to_bits() {
break 'value
Self::new_ranged_unchecked(i64::MIN,
Nanoseconds::new_static::<0>());
} else if seconds.is_nan() { return None } else { return None };
let mask = (bits as i32) >> (23 + 8);
#[allow(trivial_numeric_casts)]
let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
#[allow(trivial_numeric_casts)]
let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
}
}try_from_secs!(
699 secs = seconds,
700 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 is_nan = return None,
708 is_overflow = return None,
709 ))
710 }
711
712 #[inline]
720 pub const fn milliseconds(milliseconds: i64) -> Self {
721 unsafe {
723 Self::new_unchecked(
724 milliseconds / Millisecond::per_t::<i64>(Second),
725 (milliseconds % Millisecond::per_t::<i64>(Second)
726 * Nanosecond::per_t::<i64>(Millisecond)) as i32,
727 )
728 }
729 }
730
731 #[inline]
739 pub const fn microseconds(microseconds: i64) -> Self {
740 unsafe {
742 Self::new_unchecked(
743 microseconds / Microsecond::per_t::<i64>(Second),
744 (microseconds % Microsecond::per_t::<i64>(Second)
745 * Nanosecond::per_t::<i64>(Microsecond)) as i32,
746 )
747 }
748 }
749
750 #[inline]
758 pub const fn nanoseconds(nanoseconds: i64) -> Self {
759 unsafe {
761 Self::new_unchecked(
762 nanoseconds / Nanosecond::per_t::<i64>(Second),
763 (nanoseconds % Nanosecond::per_t::<i64>(Second)) as i32,
764 )
765 }
766 }
767
768 #[inline]
773 #[track_caller]
774 pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
775 let seconds = nanoseconds / Nanosecond::per_t::<i128>(Second);
776 let nanoseconds = nanoseconds % Nanosecond::per_t::<i128>(Second);
777
778 if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
779 crate::expect_failed("overflow constructing `time::Duration`");
780 }
781
782 unsafe { Self::new_unchecked(seconds as i64, nanoseconds as i32) }
784 }
785
786 #[inline]
796 pub const fn whole_weeks(self) -> i64 {
797 self.whole_seconds() / Second::per_t::<i64>(Week)
798 }
799
800 #[inline]
810 pub const fn whole_days(self) -> i64 {
811 self.whole_seconds() / Second::per_t::<i64>(Day)
812 }
813
814 #[inline]
824 pub const fn whole_hours(self) -> i64 {
825 self.whole_seconds() / Second::per_t::<i64>(Hour)
826 }
827
828 #[inline]
838 pub const fn whole_minutes(self) -> i64 {
839 self.whole_seconds() / Second::per_t::<i64>(Minute)
840 }
841
842 #[inline]
852 pub const fn whole_seconds(self) -> i64 {
853 self.seconds
854 }
855
856 #[inline]
864 pub fn as_seconds_f64(self) -> f64 {
865 self.seconds as f64 + self.nanoseconds.get() as f64 / Nanosecond::per_t::<f64>(Second)
866 }
867
868 #[inline]
876 pub fn as_seconds_f32(self) -> f32 {
877 self.seconds as f32 + self.nanoseconds.get() as f32 / Nanosecond::per_t::<f32>(Second)
878 }
879
880 #[inline]
890 pub const fn whole_milliseconds(self) -> i128 {
891 self.seconds as i128 * Millisecond::per_t::<i128>(Second)
892 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Millisecond)
893 }
894
895 #[inline]
905 pub const fn subsec_milliseconds(self) -> i16 {
906 (self.nanoseconds.get() / Nanosecond::per_t::<i32>(Millisecond)) as i16
907 }
908
909 #[inline]
919 pub const fn whole_microseconds(self) -> i128 {
920 self.seconds as i128 * Microsecond::per_t::<i128>(Second)
921 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Microsecond)
922 }
923
924 #[inline]
934 pub const fn subsec_microseconds(self) -> i32 {
935 self.nanoseconds.get() / Nanosecond::per_t::<i32>(Microsecond)
936 }
937
938 #[inline]
948 pub const fn whole_nanoseconds(self) -> i128 {
949 self.seconds as i128 * Nanosecond::per_t::<i128>(Second) + self.nanoseconds.get() as i128
950 }
951
952 #[inline]
962 pub const fn subsec_nanoseconds(self) -> i32 {
963 self.nanoseconds.get()
964 }
965
966 #[cfg(feature = "quickcheck")]
968 #[inline]
969 pub(crate) const fn subsec_nanoseconds_ranged(self) -> Nanoseconds {
970 self.nanoseconds
971 }
972
973 #[inline]
982 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
983 let mut seconds = match self.seconds.checked_add(rhs.seconds) {
Some(value) => value,
None => return None,
}const_try_opt!(self.seconds.checked_add(rhs.seconds));
984 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
985
986 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
987 nanoseconds -= Nanosecond::per_t::<i32>(Second);
988 seconds = match seconds.checked_add(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_add(1));
989 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
990 {
991 nanoseconds += Nanosecond::per_t::<i32>(Second);
992 seconds = match seconds.checked_sub(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_sub(1));
993 }
994
995 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
997 }
998
999 #[inline]
1008 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
1009 let mut seconds = match self.seconds.checked_sub(rhs.seconds) {
Some(value) => value,
None => return None,
}const_try_opt!(self.seconds.checked_sub(rhs.seconds));
1010 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1011
1012 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1013 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1014 seconds = match seconds.checked_add(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_add(1));
1015 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1016 {
1017 nanoseconds += Nanosecond::per_t::<i32>(Second);
1018 seconds = match seconds.checked_sub(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_sub(1));
1019 }
1020
1021 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1023 }
1024
1025 #[inline]
1036 pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
1037 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1039 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1040 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1041 let seconds = match match self.seconds.checked_mul(rhs as i64) {
Some(value) => value,
None => return None,
}.checked_add(extra_secs) {
Some(value) => value,
None => return None,
}const_try_opt!(
1042 const_try_opt!(self.seconds.checked_mul(rhs as i64)).checked_add(extra_secs)
1043 );
1044
1045 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1047 }
1048
1049 #[inline]
1058 pub const fn checked_div(self, rhs: i32) -> Option<Self> {
1059 let (secs, extra_secs) = (
1060 match self.seconds.checked_div(rhs as i64) {
Some(value) => value,
None => return None,
}const_try_opt!(self.seconds.checked_div(rhs as i64)),
1061 self.seconds % (rhs as i64),
1062 );
1063 let (mut nanos, extra_nanos) = (self.nanoseconds.get() / rhs, self.nanoseconds.get() % rhs);
1064 nanos += ((extra_secs * (Nanosecond::per_t::<i64>(Second)) + extra_nanos as i64)
1065 / (rhs as i64)) as i32;
1066
1067 unsafe { Some(Self::new_unchecked(secs, nanos)) }
1069 }
1070
1071 #[inline]
1080 pub const fn checked_neg(self) -> Option<Self> {
1081 if self.seconds == i64::MIN {
1082 None
1083 } else {
1084 Some(Self::new_ranged_unchecked(
1085 -self.seconds,
1086 self.nanoseconds.neg(),
1087 ))
1088 }
1089 }
1090
1091 #[inline]
1104 pub const fn saturating_add(self, rhs: Self) -> Self {
1105 let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
1106 if overflow {
1107 if self.seconds > 0 {
1108 return Self::MAX;
1109 }
1110 return Self::MIN;
1111 }
1112 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1113
1114 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1115 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1116 seconds = match seconds.checked_add(1) {
1117 Some(seconds) => seconds,
1118 None => return Self::MAX,
1119 };
1120 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1121 {
1122 nanoseconds += Nanosecond::per_t::<i32>(Second);
1123 seconds = match seconds.checked_sub(1) {
1124 Some(seconds) => seconds,
1125 None => return Self::MIN,
1126 };
1127 }
1128
1129 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1131 }
1132
1133 #[inline]
1146 pub const fn saturating_sub(self, rhs: Self) -> Self {
1147 let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
1148 if overflow {
1149 if self.seconds > 0 {
1150 return Self::MAX;
1151 }
1152 return Self::MIN;
1153 }
1154 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1155
1156 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1157 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1158 seconds = match seconds.checked_add(1) {
1159 Some(seconds) => seconds,
1160 None => return Self::MAX,
1161 };
1162 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1163 {
1164 nanoseconds += Nanosecond::per_t::<i32>(Second);
1165 seconds = match seconds.checked_sub(1) {
1166 Some(seconds) => seconds,
1167 None => return Self::MIN,
1168 };
1169 }
1170
1171 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1173 }
1174
1175 #[inline]
1188 pub const fn saturating_mul(self, rhs: i32) -> Self {
1189 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1191 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1192 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1193 let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as i64);
1194 if overflow1 {
1195 if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
1196 return Self::MAX;
1197 }
1198 return Self::MIN;
1199 }
1200 let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
1201 if overflow2 {
1202 if self.seconds > 0 && rhs > 0 {
1203 return Self::MAX;
1204 }
1205 return Self::MIN;
1206 }
1207
1208 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1210 }
1211
1212 #[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 pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
1224 let start = Instant::now();
1225 let return_value = f();
1226 let end = Instant::now();
1227
1228 (end - start, return_value)
1229 }
1230}
1231
1232impl fmt::Display for Duration {
1247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1248 if self.is_negative() {
1249 f.write_str("-")?;
1250 }
1251
1252 if let Some(_precision) = f.precision() {
1253 if self.is_zero() {
1256 return (0.).fmt(f).and_then(|_| f.write_str("s"));
1258 }
1259
1260 macro_rules! item {
1262 ($name:literal, $value:expr) => {
1263 let value = $value;
1264 if value >= 1.0 {
1265 return value.fmt(f).and_then(|_| f.write_str($name));
1266 }
1267 };
1268 }
1269
1270 let seconds = self.unsigned_abs().as_secs_f64();
1272
1273 let value = seconds / Second::per_t::<f64>(Day);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("d")); };item!("d", seconds / Second::per_t::<f64>(Day));
1274 let value = seconds / Second::per_t::<f64>(Hour);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("h")); };item!("h", seconds / Second::per_t::<f64>(Hour));
1275 let value = seconds / Second::per_t::<f64>(Minute);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("m")); };item!("m", seconds / Second::per_t::<f64>(Minute));
1276 let value = seconds;
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("s")); };item!("s", seconds);
1277 let value = seconds * Millisecond::per_t::<f64>(Second);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("ms")); };item!("ms", seconds * Millisecond::per_t::<f64>(Second));
1278 let value = seconds * Microsecond::per_t::<f64>(Second);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("µs")); };item!("µs", seconds * Microsecond::per_t::<f64>(Second));
1279 let value = seconds * Nanosecond::per_t::<f64>(Second);
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("ns")); };item!("ns", seconds * Nanosecond::per_t::<f64>(Second));
1280 } else {
1281 if self.is_zero() {
1284 return f.write_str("0s");
1285 }
1286
1287 macro_rules! item {
1289 ($name:literal, $value:expr) => {
1290 match $value {
1291 0 => Ok(()),
1292 value => value.fmt(f).and_then(|_| f.write_str($name)),
1293 }
1294 };
1295 }
1296
1297 let seconds = self.seconds.unsigned_abs();
1298 let nanoseconds = self.nanoseconds.get().unsigned_abs();
1299
1300 match seconds / Second::per_t::<u64>(Day) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("d")),
}item!("d", seconds / Second::per_t::<u64>(Day))?;
1301 match seconds / Second::per_t::<u64>(Hour) % Hour::per_t::<u64>(Day) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("h")),
}item!(
1302 "h",
1303 seconds / Second::per_t::<u64>(Hour) % Hour::per_t::<u64>(Day)
1304 )?;
1305 match seconds / Second::per_t::<u64>(Minute) % Minute::per_t::<u64>(Hour) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("m")),
}item!(
1306 "m",
1307 seconds / Second::per_t::<u64>(Minute) % Minute::per_t::<u64>(Hour)
1308 )?;
1309 match seconds % Second::per_t::<u64>(Minute) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("s")),
}item!("s", seconds % Second::per_t::<u64>(Minute))?;
1310 match nanoseconds / Nanosecond::per_t::<u32>(Millisecond) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("ms")),
}item!("ms", nanoseconds / Nanosecond::per_t::<u32>(Millisecond))?;
1311 match nanoseconds / Nanosecond::per_t::<u32>(Microsecond) %
Microsecond::per_t::<u32>(Millisecond) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("µs")),
}item!(
1312 "µs",
1313 nanoseconds / Nanosecond::per_t::<u32>(Microsecond)
1314 % Microsecond::per_t::<u32>(Millisecond)
1315 )?;
1316 match nanoseconds % Nanosecond::per_t::<u32>(Microsecond) {
0 => Ok(()),
value => value.fmt(f).and_then(|_| f.write_str("ns")),
}item!("ns", nanoseconds % Nanosecond::per_t::<u32>(Microsecond))?;
1317 }
1318
1319 Ok(())
1320 }
1321}
1322
1323impl TryFrom<StdDuration> for Duration {
1324 type Error = error::ConversionRange;
1325
1326 #[inline]
1327 fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
1328 Ok(Self::new(
1329 original
1330 .as_secs()
1331 .try_into()
1332 .map_err(|_| error::ConversionRange)?,
1333 original.subsec_nanos().cast_signed(),
1334 ))
1335 }
1336}
1337
1338impl TryFrom<Duration> for StdDuration {
1339 type Error = error::ConversionRange;
1340
1341 #[inline]
1342 fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
1343 Ok(Self::new(
1344 duration
1345 .seconds
1346 .try_into()
1347 .map_err(|_| error::ConversionRange)?,
1348 duration
1349 .nanoseconds
1350 .get()
1351 .try_into()
1352 .map_err(|_| error::ConversionRange)?,
1353 ))
1354 }
1355}
1356
1357impl Add for Duration {
1358 type Output = Self;
1359
1360 #[inline]
1364 #[track_caller]
1365 fn add(self, rhs: Self) -> Self::Output {
1366 self.checked_add(rhs)
1367 .expect("overflow when adding durations")
1368 }
1369}
1370
1371impl Add<StdDuration> for Duration {
1372 type Output = Self;
1373
1374 #[inline]
1378 #[track_caller]
1379 fn add(self, std_duration: StdDuration) -> Self::Output {
1380 self + Self::try_from(std_duration)
1381 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1382 }
1383}
1384
1385impl Add<Duration> for StdDuration {
1386 type Output = Duration;
1387
1388 #[inline]
1389 #[track_caller]
1390 fn add(self, rhs: Duration) -> Self::Output {
1391 rhs + self
1392 }
1393}
1394
1395#[allow(unused_qualifications)]
impl core::ops::AddAssign<StdDuration> for Duration {
#[inline]
fn add_assign(&mut self, rhs: StdDuration) { *self = *self + rhs; }
}impl_add_assign!(Duration: Self, StdDuration);
1396
1397impl AddAssign<Duration> for StdDuration {
1398 #[inline]
1402 #[track_caller]
1403 fn add_assign(&mut self, rhs: Duration) {
1404 *self = (*self + rhs).try_into().expect(
1405 "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
1406 change the type.",
1407 );
1408 }
1409}
1410
1411impl Neg for Duration {
1412 type Output = Self;
1413
1414 #[inline]
1415 #[track_caller]
1416 fn neg(self) -> Self::Output {
1417 self.checked_neg().expect("overflow when negating duration")
1418 }
1419}
1420
1421impl Sub for Duration {
1422 type Output = Self;
1423
1424 #[inline]
1428 #[track_caller]
1429 fn sub(self, rhs: Self) -> Self::Output {
1430 self.checked_sub(rhs)
1431 .expect("overflow when subtracting durations")
1432 }
1433}
1434
1435impl Sub<StdDuration> for Duration {
1436 type Output = Self;
1437
1438 #[inline]
1442 #[track_caller]
1443 fn sub(self, rhs: StdDuration) -> Self::Output {
1444 self - Self::try_from(rhs)
1445 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1446 }
1447}
1448
1449impl Sub<Duration> for StdDuration {
1450 type Output = Duration;
1451
1452 #[inline]
1456 #[track_caller]
1457 fn sub(self, rhs: Duration) -> Self::Output {
1458 Duration::try_from(self)
1459 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1460 - rhs
1461 }
1462}
1463
1464#[allow(unused_qualifications)]
impl core::ops::SubAssign<StdDuration> for Duration {
#[inline]
fn sub_assign(&mut self, rhs: StdDuration) { *self = *self - rhs; }
}impl_sub_assign!(Duration: Self, StdDuration);
1465
1466impl SubAssign<Duration> for StdDuration {
1467 #[inline]
1471 #[track_caller]
1472 fn sub_assign(&mut self, rhs: Duration) {
1473 *self = (*self - rhs).try_into().expect(
1474 "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
1475 change the type.",
1476 );
1477 }
1478}
1479
1480macro_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 fn mul(self, rhs: $type) -> Self::Output {
1489 Self::nanoseconds_i128(
1490 self.whole_nanoseconds()
1491 .checked_mul(rhs.cast_signed().extend::<i128>())
1492 .expect("overflow when multiplying duration")
1493 )
1494 }
1495 }
1496
1497 impl Mul<Duration> for $type {
1498 type Output = Duration;
1499
1500 #[inline]
1501 #[track_caller]
1502 fn mul(self, rhs: Duration) -> Self::Output {
1503 rhs * self
1504 }
1505 }
1506
1507 impl Div<$type> for Duration {
1508 type Output = Self;
1509
1510 #[inline]
1511 #[track_caller]
1512 fn div(self, rhs: $type) -> Self::Output {
1513 Self::nanoseconds_i128(
1514 self.whole_nanoseconds() / rhs.cast_signed().extend::<i128>()
1515 )
1516 }
1517 }
1518 )+};
1519}
1520impl Mul<u32> for Duration {
type Output = Self;
#[inline]
#[track_caller]
fn mul(self, rhs: u32) -> Self::Output {
Self::nanoseconds_i128(self.whole_nanoseconds().checked_mul(rhs.cast_signed().extend::<i128>()).expect("overflow when multiplying duration"))
}
}
impl Mul<Duration> for u32 {
type Output = Duration;
#[inline]
#[track_caller]
fn mul(self, rhs: Duration) -> Self::Output { rhs * self }
}
impl Div<u32> for Duration {
type Output = Self;
#[inline]
#[track_caller]
fn div(self, rhs: u32) -> Self::Output {
Self::nanoseconds_i128(self.whole_nanoseconds() /
rhs.cast_signed().extend::<i128>())
}
}duration_mul_div_int![i8, i16, i32, u8, u16, u32];
1521
1522impl Mul<f32> for Duration {
1523 type Output = Self;
1524
1525 #[inline]
1526 #[track_caller]
1527 fn mul(self, rhs: f32) -> Self::Output {
1528 Self::seconds_f32(self.as_seconds_f32() * rhs)
1529 }
1530}
1531
1532impl Mul<Duration> for f32 {
1533 type Output = Duration;
1534
1535 #[inline]
1536 #[track_caller]
1537 fn mul(self, rhs: Duration) -> Self::Output {
1538 rhs * self
1539 }
1540}
1541
1542impl Mul<f64> for Duration {
1543 type Output = Self;
1544
1545 #[inline]
1546 #[track_caller]
1547 fn mul(self, rhs: f64) -> Self::Output {
1548 Self::seconds_f64(self.as_seconds_f64() * rhs)
1549 }
1550}
1551
1552impl Mul<Duration> for f64 {
1553 type Output = Duration;
1554
1555 #[inline]
1556 #[track_caller]
1557 fn mul(self, rhs: Duration) -> Self::Output {
1558 rhs * self
1559 }
1560}
1561
1562#[allow(unused_qualifications)]
impl core::ops::MulAssign<f64> for Duration {
#[inline]
fn mul_assign(&mut self, rhs: f64) { *self = *self * rhs; }
}impl_mul_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1563
1564impl Div<f32> for Duration {
1565 type Output = Self;
1566
1567 #[inline]
1568 #[track_caller]
1569 fn div(self, rhs: f32) -> Self::Output {
1570 Self::seconds_f32(self.as_seconds_f32() / rhs)
1571 }
1572}
1573
1574impl Div<f64> for Duration {
1575 type Output = Self;
1576
1577 #[inline]
1578 #[track_caller]
1579 fn div(self, rhs: f64) -> Self::Output {
1580 Self::seconds_f64(self.as_seconds_f64() / rhs)
1581 }
1582}
1583
1584#[allow(unused_qualifications)]
impl core::ops::DivAssign<f64> for Duration {
#[inline]
fn div_assign(&mut self, rhs: f64) { *self = *self / rhs; }
}impl_div_assign!(Duration: i8, i16, i32, u8, u16, u32, f32, f64);
1585
1586impl Div for Duration {
1587 type Output = f64;
1588
1589 #[inline]
1590 #[track_caller]
1591 fn div(self, rhs: Self) -> Self::Output {
1592 self.as_seconds_f64() / rhs.as_seconds_f64()
1593 }
1594}
1595
1596impl Div<StdDuration> for Duration {
1597 type Output = f64;
1598
1599 #[inline]
1600 #[track_caller]
1601 fn div(self, rhs: StdDuration) -> Self::Output {
1602 self.as_seconds_f64() / rhs.as_secs_f64()
1603 }
1604}
1605
1606impl Div<Duration> for StdDuration {
1607 type Output = f64;
1608
1609 #[inline]
1610 #[track_caller]
1611 fn div(self, rhs: Duration) -> Self::Output {
1612 self.as_secs_f64() / rhs.as_seconds_f64()
1613 }
1614}
1615
1616impl PartialEq<StdDuration> for Duration {
1617 #[inline]
1618 fn eq(&self, rhs: &StdDuration) -> bool {
1619 Ok(*self) == Self::try_from(*rhs)
1620 }
1621}
1622
1623impl PartialEq<Duration> for StdDuration {
1624 #[inline]
1625 fn eq(&self, rhs: &Duration) -> bool {
1626 rhs == self
1627 }
1628}
1629
1630impl PartialOrd<StdDuration> for Duration {
1631 #[inline]
1632 fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1633 if rhs.as_secs() > i64::MAX.cast_unsigned() {
1634 return Some(Ordering::Less);
1635 }
1636
1637 Some(
1638 self.seconds
1639 .cmp(&rhs.as_secs().cast_signed())
1640 .then_with(|| {
1641 self.nanoseconds
1642 .get()
1643 .cmp(&rhs.subsec_nanos().cast_signed())
1644 }),
1645 )
1646 }
1647}
1648
1649impl PartialOrd<Duration> for StdDuration {
1650 #[inline]
1651 fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1652 rhs.partial_cmp(self).map(Ordering::reverse)
1653 }
1654}
1655
1656impl Sum for Duration {
1657 #[inline]
1658 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1659 iter.reduce(|a, b| a + b).unwrap_or_default()
1660 }
1661}
1662
1663impl<'a> Sum<&'a Self> for Duration {
1664 #[inline]
1665 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1666 iter.copied().sum()
1667 }
1668}
1669
1670#[cfg(feature = "std")]
1671impl Add<Duration> for SystemTime {
1672 type Output = Self;
1673
1674 #[inline]
1675 #[track_caller]
1676 fn add(self, duration: Duration) -> Self::Output {
1677 if duration.is_zero() {
1678 self
1679 } else if duration.is_positive() {
1680 self + duration.unsigned_abs()
1681 } else {
1682 if true {
if !duration.is_negative() {
::core::panicking::panic("assertion failed: duration.is_negative()")
};
};debug_assert!(duration.is_negative());
1683 self - duration.unsigned_abs()
1684 }
1685 }
1686}
1687
1688#[allow(unused_qualifications)]
impl core::ops::AddAssign<Duration> for SystemTime {
#[inline]
fn add_assign(&mut self, rhs: Duration) { *self = *self + rhs; }
}impl_add_assign!(SystemTime: #[cfg(feature = "std")] Duration);
1689
1690#[cfg(feature = "std")]
1691impl Sub<Duration> for SystemTime {
1692 type Output = Self;
1693
1694 #[inline]
1695 #[track_caller]
1696 fn sub(self, duration: Duration) -> Self::Output {
1697 if duration.is_zero() {
1698 self
1699 } else if duration.is_positive() {
1700 self - duration.unsigned_abs()
1701 } else {
1702 if true {
if !duration.is_negative() {
::core::panicking::panic("assertion failed: duration.is_negative()")
};
};debug_assert!(duration.is_negative());
1703 self + duration.unsigned_abs()
1704 }
1705 }
1706}
1707
1708#[allow(unused_qualifications)]
impl core::ops::SubAssign<Duration> for SystemTime {
#[inline]
fn sub_assign(&mut self, rhs: Duration) { *self = *self - rhs; }
}impl_sub_assign!(SystemTime: #[cfg(feature = "std")] Duration);