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, 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#[derive(#[automatically_derived]
impl ::core::clone::Clone for Duration {
#[inline]
fn clone(&self) -> Duration {
let _: ::core::clone::AssertParamIsClone<i64>;
let _: ::core::clone::AssertParamIsClone<Nanoseconds>;
let _: ::core::clone::AssertParamIsClone<Padding>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Duration { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Duration {
#[inline]
fn eq(&self, other: &Duration) -> bool {
self.seconds == other.seconds && self.nanoseconds == other.nanoseconds
&& self.padding == other.padding
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Duration {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i64>;
let _: ::core::cmp::AssertParamIsEq<Nanoseconds>;
let _: ::core::cmp::AssertParamIsEq<Padding>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Duration {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.seconds, state);
::core::hash::Hash::hash(&self.nanoseconds, state);
::core::hash::Hash::hash(&self.padding, state)
}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialOrd for Duration {
#[inline]
fn partial_cmp(&self, other: &Duration)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.seconds,
&other.seconds) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self.nanoseconds,
&other.nanoseconds) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&self.padding,
&other.padding),
cmp => cmp,
},
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Duration {
#[inline]
fn cmp(&self, other: &Duration) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.seconds, &other.seconds) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.nanoseconds,
&other.nanoseconds) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.padding, &other.padding),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord)]
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 = (mant as $double_ty) << ($offset + exp);
110 let nanos_offset = $mant_bits + $offset;
111 #[allow(trivial_numeric_casts)]
112 let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
113 let nanos = (nanos_tmp >> nanos_offset) as u32;
114
115 let rem_mask = (1 << nanos_offset) - 1;
116 let rem_msb_mask = 1 << (nanos_offset - 1);
117 let rem = nanos_tmp & rem_mask;
118 let is_tie = rem == rem_msb_mask;
119 let is_even = (nanos & 1) == 0;
120 let rem_msb = nanos_tmp & rem_msb_mask == 0;
121 let add_ns = !(rem_msb || (is_even && is_tie));
122
123 let nanos = nanos + add_ns as u32;
126 if ($mant_bits == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
127 (0, nanos)
128 } else {
129 (1, 0)
130 }
131 } else if exp < $mant_bits {
132 #[allow(trivial_numeric_casts)]
133 let secs = (mant >> ($mant_bits - exp)) as u64;
134 let t = ((mant << exp) & MANT_MASK) as $double_ty;
135 let nanos_offset = $mant_bits;
136 let nanos_tmp = Nanosecond::per_t::<$double_ty>(Second) * t;
137 let nanos = (nanos_tmp >> nanos_offset) as u32;
138
139 let rem_mask = (1 << nanos_offset) - 1;
140 let rem_msb_mask = 1 << (nanos_offset - 1);
141 let rem = nanos_tmp & rem_mask;
142 let is_tie = rem == rem_msb_mask;
143 let is_even = (nanos & 1) == 0;
144 let rem_msb = nanos_tmp & rem_msb_mask == 0;
145 let add_ns = !(rem_msb || (is_even && is_tie));
146
147 let nanos = nanos + add_ns as u32;
152 if ($mant_bits == 23) || (nanos != Nanosecond::per_t::<u32>(Second)) {
153 (secs, nanos)
154 } else {
155 (secs + 1, 0)
156 }
157 } else if exp < 63 {
158 #[allow(trivial_numeric_casts)]
163 let secs = (mant as u64) << (exp - $mant_bits);
164 (secs, 0)
165 } else if bits == (i64::MIN as $float_ty).to_bits() {
166 break 'value Self::new_ranged_unchecked(i64::MIN, Nanoseconds::new_static::<0>());
172 } else if $secs.is_nan() {
173 $is_nan
176 } else {
177 $is_overflow
178 };
179
180 let mask = (bits as $bits_ty_signed) >> ($mant_bits + $exp_bits);
187 #[allow(trivial_numeric_casts)]
188 let secs_signed = ((secs as i64) ^ (mask as i64)) - (mask as i64);
189 #[allow(trivial_numeric_casts)]
190 let nanos_signed = ((nanos as i32) ^ (mask as i32)) - (mask as i32);
191 unsafe { Self::new_unchecked(secs_signed, nanos_signed) }
193 }
194 }};
195}
196
197impl Duration {
198 pub const ZERO: Self = Self::seconds(0);
205
206 pub const NANOSECOND: Self = Self::nanoseconds(1);
213
214 pub const MICROSECOND: Self = Self::microseconds(1);
221
222 pub const MILLISECOND: Self = Self::milliseconds(1);
229
230 pub const SECOND: Self = Self::seconds(1);
237
238 pub const MINUTE: Self = Self::minutes(1);
245
246 pub const HOUR: Self = Self::hours(1);
253
254 pub const DAY: Self = Self::days(1);
261
262 pub const WEEK: Self = Self::weeks(1);
269
270 pub const MIN: Self = Self::new_ranged(i64::MIN, Nanoseconds::MIN);
272
273 pub const MAX: Self = Self::new_ranged(i64::MAX, Nanoseconds::MAX);
275
276 #[inline]
284 pub const fn is_zero(self) -> bool {
285 self.seconds == 0 && self.nanoseconds.get() == 0
286 }
287
288 #[inline]
297 pub const fn is_negative(self) -> bool {
298 self.seconds < 0 || self.nanoseconds.get() < 0
299 }
300
301 #[inline]
310 pub const fn is_positive(self) -> bool {
311 self.seconds > 0 || self.nanoseconds.get() > 0
312 }
313
314 #[inline]
325 pub const fn abs(self) -> Self {
326 match self.seconds.checked_abs() {
327 Some(seconds) => Self::new_ranged_unchecked(seconds, self.nanoseconds.abs()),
328 None => Self::MAX,
329 }
330 }
331
332 #[inline]
342 pub const fn unsigned_abs(self) -> StdDuration {
343 StdDuration::new(
344 self.seconds.unsigned_abs(),
345 self.nanoseconds.get().unsigned_abs(),
346 )
347 }
348
349 #[inline]
358 #[track_caller]
359 pub(crate) const unsafe fn new_unchecked(seconds: i64, nanoseconds: i32) -> Self {
360 Self::new_ranged_unchecked(
361 seconds,
362 unsafe { Nanoseconds::new_unchecked(nanoseconds) },
364 )
365 }
366
367 #[inline]
369 #[track_caller]
370 pub(crate) const fn new_ranged_unchecked(seconds: i64, nanoseconds: Nanoseconds) -> Self {
371 if seconds < 0 {
372 if true {
if !(nanoseconds.get() <= 0) {
::core::panicking::panic("assertion failed: nanoseconds.get() <= 0")
};
};debug_assert!(nanoseconds.get() <= 0);
373 } else if seconds > 0 {
374 if true {
if !(nanoseconds.get() >= 0) {
::core::panicking::panic("assertion failed: nanoseconds.get() >= 0")
};
};debug_assert!(nanoseconds.get() >= 0);
375 }
376
377 Self {
378 seconds,
379 nanoseconds,
380 padding: Padding::Optimize,
381 }
382 }
383
384 #[inline]
398 #[track_caller]
399 pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
400 seconds = seconds
401 .checked_add(nanoseconds as i64 / Nanosecond::per_t::<i64>(Second))
402 .expect("overflow constructing `time::Duration`");
403 nanoseconds %= Nanosecond::per_t::<i32>(Second);
404
405 if seconds > 0 && nanoseconds < 0 {
406 seconds -= 1;
408 nanoseconds += Nanosecond::per_t::<i32>(Second);
409 } else if seconds < 0 && nanoseconds > 0 {
410 seconds += 1;
412 nanoseconds -= Nanosecond::per_t::<i32>(Second);
413 }
414
415 unsafe { Self::new_unchecked(seconds, nanoseconds) }
417 }
418
419 #[inline]
421 pub(crate) const fn new_ranged(mut seconds: i64, mut nanoseconds: Nanoseconds) -> Self {
422 if seconds > 0 && nanoseconds.get() < 0 {
423 seconds -= 1;
425 nanoseconds = unsafe {
428 Nanoseconds::new_unchecked(nanoseconds.get() + Nanosecond::per_t::<i32>(Second))
429 };
430 } else if seconds < 0 && nanoseconds.get() > 0 {
431 seconds += 1;
433 nanoseconds = unsafe {
436 Nanoseconds::new_unchecked(nanoseconds.get() - Nanosecond::per_t::<i32>(Second))
437 };
438 }
439
440 Self::new_ranged_unchecked(seconds, nanoseconds)
441 }
442
443 #[inline]
455 #[track_caller]
456 pub const fn weeks(weeks: i64) -> Self {
457 Self::seconds(
458 weeks
459 .checked_mul(Second::per_t(Week))
460 .expect("overflow constructing `time::Duration`"),
461 )
462 }
463
464 #[inline]
476 #[track_caller]
477 pub const fn days(days: i64) -> Self {
478 Self::seconds(
479 days.checked_mul(Second::per_t(Day))
480 .expect("overflow constructing `time::Duration`"),
481 )
482 }
483
484 #[inline]
496 #[track_caller]
497 pub const fn hours(hours: i64) -> Self {
498 Self::seconds(
499 hours
500 .checked_mul(Second::per_t(Hour))
501 .expect("overflow constructing `time::Duration`"),
502 )
503 }
504
505 #[inline]
517 #[track_caller]
518 pub const fn minutes(minutes: i64) -> Self {
519 Self::seconds(
520 minutes
521 .checked_mul(Second::per_t(Minute))
522 .expect("overflow constructing `time::Duration`"),
523 )
524 }
525
526 #[inline]
533 pub const fn seconds(seconds: i64) -> Self {
534 Self::new_ranged_unchecked(seconds, Nanoseconds::new_static::<0>())
535 }
536
537 #[inline]
545 #[track_caller]
546 pub const fn seconds_f64(seconds: f64) -> Self {
547 {
'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 = (mant as u128) << (44 + exp);
let nanos_offset = 52 + 44;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (52 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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::panic("passed NaN to `time::Duration::seconds_f64`")
} else { crate::panic("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!(
548 secs = seconds,
549 mantissa_bits = 52,
550 exponent_bits = 11,
551 offset = 44,
552 bits_ty = u64,
553 bits_ty_signed = i64,
554 double_ty = u128,
555 float_ty = f64,
556 is_nan = crate::panic("passed NaN to `time::Duration::seconds_f64`"),
557 is_overflow = crate::panic("overflow constructing `time::Duration`"),
558 )
559 }
560
561 #[inline]
569 #[track_caller]
570 pub const fn seconds_f32(seconds: f32) -> Self {
571 {
'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 = (mant as u64) << (41 + exp);
let nanos_offset = 23 + 41;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (23 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u64;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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::panic("passed NaN to `time::Duration::seconds_f32`")
} else { crate::panic("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!(
572 secs = seconds,
573 mantissa_bits = 23,
574 exponent_bits = 8,
575 offset = 41,
576 bits_ty = u32,
577 bits_ty_signed = i32,
578 double_ty = u64,
579 float_ty = f32,
580 is_nan = crate::panic("passed NaN to `time::Duration::seconds_f32`"),
581 is_overflow = crate::panic("overflow constructing `time::Duration`"),
582 )
583 }
584
585 #[inline]
608 pub const fn saturating_seconds_f64(seconds: f64) -> Self {
609 {
'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 = (mant as u128) << (44 + exp);
let nanos_offset = 52 + 44;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (52 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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!(
610 secs = seconds,
611 mantissa_bits = 52,
612 exponent_bits = 11,
613 offset = 44,
614 bits_ty = u64,
615 bits_ty_signed = i64,
616 double_ty = u128,
617 float_ty = f64,
618 is_nan = return Self::ZERO,
619 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
620 )
621 }
622
623 #[inline]
646 pub const fn saturating_seconds_f32(seconds: f32) -> Self {
647 {
'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 = (mant as u64) << (41 + exp);
let nanos_offset = 23 + 41;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (23 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u64;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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!(
648 secs = seconds,
649 mantissa_bits = 23,
650 exponent_bits = 8,
651 offset = 41,
652 bits_ty = u32,
653 bits_ty_signed = i32,
654 double_ty = u64,
655 float_ty = f32,
656 is_nan = return Self::ZERO,
657 is_overflow = return if seconds < 0.0 { Self::MIN } else { Self::MAX },
658 )
659 }
660
661 #[inline]
674 pub const fn checked_seconds_f64(seconds: f64) -> Option<Self> {
675 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 = (mant as u128) << (44 + exp);
let nanos_offset = 52 + 44;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (52 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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!(
676 secs = seconds,
677 mantissa_bits = 52,
678 exponent_bits = 11,
679 offset = 44,
680 bits_ty = u64,
681 bits_ty_signed = i64,
682 double_ty = u128,
683 float_ty = f64,
684 is_nan = return None,
685 is_overflow = return None,
686 ))
687 }
688
689 #[inline]
702 pub const fn checked_seconds_f32(seconds: f32) -> Option<Self> {
703 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 = (mant as u64) << (41 + exp);
let nanos_offset = 23 + 41;
#[allow(trivial_numeric_casts)]
let nanos_tmp = Nanosecond::per_t::<u128>(Second) * t as u128;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant >> (23 - exp)) as u64;
let t = ((mant << exp) & MANT_MASK) as u64;
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 {
#[allow(trivial_numeric_casts)]
let secs = (mant as u64) << (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!(
704 secs = seconds,
705 mantissa_bits = 23,
706 exponent_bits = 8,
707 offset = 41,
708 bits_ty = u32,
709 bits_ty_signed = i32,
710 double_ty = u64,
711 float_ty = f32,
712 is_nan = return None,
713 is_overflow = return None,
714 ))
715 }
716
717 #[inline]
725 pub const fn milliseconds(milliseconds: i64) -> Self {
726 unsafe {
728 Self::new_unchecked(
729 milliseconds / Millisecond::per_t::<i64>(Second),
730 (milliseconds % Millisecond::per_t::<i64>(Second)
731 * Nanosecond::per_t::<i64>(Millisecond)) as i32,
732 )
733 }
734 }
735
736 #[inline]
744 pub const fn microseconds(microseconds: i64) -> Self {
745 unsafe {
747 Self::new_unchecked(
748 microseconds / Microsecond::per_t::<i64>(Second),
749 (microseconds % Microsecond::per_t::<i64>(Second)
750 * Nanosecond::per_t::<i64>(Microsecond)) as i32,
751 )
752 }
753 }
754
755 #[inline]
763 pub const fn nanoseconds(nanoseconds: i64) -> Self {
764 unsafe {
766 Self::new_unchecked(
767 nanoseconds / Nanosecond::per_t::<i64>(Second),
768 (nanoseconds % Nanosecond::per_t::<i64>(Second)) as i32,
769 )
770 }
771 }
772
773 #[inline]
778 #[track_caller]
779 pub(crate) const fn nanoseconds_i128(nanoseconds: i128) -> Self {
780 let seconds = nanoseconds / Nanosecond::per_t::<i128>(Second);
781 let nanoseconds = nanoseconds % Nanosecond::per_t::<i128>(Second);
782
783 if seconds > i64::MAX as i128 || seconds < i64::MIN as i128 {
784 crate::panic("overflow constructing `time::Duration`");
785 }
786
787 unsafe { Self::new_unchecked(seconds as i64, nanoseconds as i32) }
789 }
790
791 #[inline]
801 pub const fn whole_weeks(self) -> i64 {
802 self.whole_seconds() / Second::per_t::<i64>(Week)
803 }
804
805 #[inline]
815 pub const fn whole_days(self) -> i64 {
816 self.whole_seconds() / Second::per_t::<i64>(Day)
817 }
818
819 #[inline]
829 pub const fn whole_hours(self) -> i64 {
830 self.whole_seconds() / Second::per_t::<i64>(Hour)
831 }
832
833 #[inline]
843 pub const fn whole_minutes(self) -> i64 {
844 self.whole_seconds() / Second::per_t::<i64>(Minute)
845 }
846
847 #[inline]
857 pub const fn whole_seconds(self) -> i64 {
858 self.seconds
859 }
860
861 #[inline]
869 pub const fn as_seconds_f64(self) -> f64 {
870 self.seconds as f64 + self.nanoseconds.get() as f64 / Nanosecond::per_t::<f64>(Second)
871 }
872
873 #[inline]
881 pub const fn as_seconds_f32(self) -> f32 {
882 self.seconds as f32 + self.nanoseconds.get() as f32 / Nanosecond::per_t::<f32>(Second)
883 }
884
885 #[inline]
895 pub const fn whole_milliseconds(self) -> i128 {
896 self.seconds as i128 * Millisecond::per_t::<i128>(Second)
897 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Millisecond)
898 }
899
900 #[inline]
910 pub const fn subsec_milliseconds(self) -> i16 {
911 (self.nanoseconds.get() / Nanosecond::per_t::<i32>(Millisecond)) as i16
912 }
913
914 #[inline]
924 pub const fn whole_microseconds(self) -> i128 {
925 self.seconds as i128 * Microsecond::per_t::<i128>(Second)
926 + self.nanoseconds.get() as i128 / Nanosecond::per_t::<i128>(Microsecond)
927 }
928
929 #[inline]
939 pub const fn subsec_microseconds(self) -> i32 {
940 self.nanoseconds.get() / Nanosecond::per_t::<i32>(Microsecond)
941 }
942
943 #[inline]
953 pub const fn whole_nanoseconds(self) -> i128 {
954 self.seconds as i128 * Nanosecond::per_t::<i128>(Second) + self.nanoseconds.get() as i128
955 }
956
957 #[inline]
967 pub const fn subsec_nanoseconds(self) -> i32 {
968 self.nanoseconds.get()
969 }
970
971 #[cfg(feature = "quickcheck")]
973 #[inline]
974 pub(crate) const fn subsec_nanoseconds_ranged(self) -> Nanoseconds {
975 self.nanoseconds
976 }
977
978 #[inline]
987 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
988 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));
989 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
990
991 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
992 nanoseconds -= Nanosecond::per_t::<i32>(Second);
993 seconds = match seconds.checked_add(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_add(1));
994 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
995 {
996 nanoseconds += Nanosecond::per_t::<i32>(Second);
997 seconds = match seconds.checked_sub(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_sub(1));
998 }
999
1000 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1002 }
1003
1004 #[inline]
1013 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
1014 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));
1015 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1016
1017 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1018 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1019 seconds = match seconds.checked_add(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_add(1));
1020 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1021 {
1022 nanoseconds += Nanosecond::per_t::<i32>(Second);
1023 seconds = match seconds.checked_sub(1) { Some(value) => value, None => return None, }const_try_opt!(seconds.checked_sub(1));
1024 }
1025
1026 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1028 }
1029
1030 #[inline]
1041 pub const fn checked_mul(self, rhs: i32) -> Option<Self> {
1042 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1044 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1045 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1046 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!(
1047 const_try_opt!(self.seconds.checked_mul(rhs as i64)).checked_add(extra_secs)
1048 );
1049
1050 unsafe { Some(Self::new_unchecked(seconds, nanoseconds)) }
1052 }
1053
1054 #[inline]
1063 pub const fn checked_div(self, rhs: i32) -> Option<Self> {
1064 let (secs, extra_secs) = (
1065 match self.seconds.checked_div(rhs as i64) {
Some(value) => value,
None => return None,
}const_try_opt!(self.seconds.checked_div(rhs as i64)),
1066 self.seconds % (rhs as i64),
1067 );
1068 let (mut nanos, extra_nanos) = (self.nanoseconds.get() / rhs, self.nanoseconds.get() % rhs);
1069 nanos += ((extra_secs * (Nanosecond::per_t::<i64>(Second)) + extra_nanos as i64)
1070 / (rhs as i64)) as i32;
1071
1072 unsafe { Some(Self::new_unchecked(secs, nanos)) }
1074 }
1075
1076 #[inline]
1085 pub const fn checked_neg(self) -> Option<Self> {
1086 if self.seconds == i64::MIN {
1087 None
1088 } else {
1089 Some(Self::new_ranged_unchecked(
1090 -self.seconds,
1091 self.nanoseconds.neg(),
1092 ))
1093 }
1094 }
1095
1096 #[inline]
1109 pub const fn saturating_add(self, rhs: Self) -> Self {
1110 let (mut seconds, overflow) = self.seconds.overflowing_add(rhs.seconds);
1111 if overflow {
1112 if self.seconds > 0 {
1113 return Self::MAX;
1114 }
1115 return Self::MIN;
1116 }
1117 let mut nanoseconds = self.nanoseconds.get() + rhs.nanoseconds.get();
1118
1119 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1120 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1121 seconds = match seconds.checked_add(1) {
1122 Some(seconds) => seconds,
1123 None => return Self::MAX,
1124 };
1125 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1126 {
1127 nanoseconds += Nanosecond::per_t::<i32>(Second);
1128 seconds = match seconds.checked_sub(1) {
1129 Some(seconds) => seconds,
1130 None => return Self::MIN,
1131 };
1132 }
1133
1134 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1136 }
1137
1138 #[inline]
1151 pub const fn saturating_sub(self, rhs: Self) -> Self {
1152 let (mut seconds, overflow) = self.seconds.overflowing_sub(rhs.seconds);
1153 if overflow {
1154 if self.seconds > 0 {
1155 return Self::MAX;
1156 }
1157 return Self::MIN;
1158 }
1159 let mut nanoseconds = self.nanoseconds.get() - rhs.nanoseconds.get();
1160
1161 if nanoseconds >= Nanosecond::per_t(Second) || seconds < 0 && nanoseconds > 0 {
1162 nanoseconds -= Nanosecond::per_t::<i32>(Second);
1163 seconds = match seconds.checked_add(1) {
1164 Some(seconds) => seconds,
1165 None => return Self::MAX,
1166 };
1167 } else if nanoseconds <= -Nanosecond::per_t::<i32>(Second) || seconds > 0 && nanoseconds < 0
1168 {
1169 nanoseconds += Nanosecond::per_t::<i32>(Second);
1170 seconds = match seconds.checked_sub(1) {
1171 Some(seconds) => seconds,
1172 None => return Self::MIN,
1173 };
1174 }
1175
1176 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1178 }
1179
1180 #[inline]
1193 pub const fn saturating_mul(self, rhs: i32) -> Self {
1194 let total_nanos = self.nanoseconds.get() as i64 * rhs as i64;
1196 let extra_secs = total_nanos / Nanosecond::per_t::<i64>(Second);
1197 let nanoseconds = (total_nanos % Nanosecond::per_t::<i64>(Second)) as i32;
1198 let (seconds, overflow1) = self.seconds.overflowing_mul(rhs as i64);
1199 if overflow1 {
1200 if self.seconds > 0 && rhs > 0 || self.seconds < 0 && rhs < 0 {
1201 return Self::MAX;
1202 }
1203 return Self::MIN;
1204 }
1205 let (seconds, overflow2) = seconds.overflowing_add(extra_secs);
1206 if overflow2 {
1207 if self.seconds > 0 && rhs > 0 {
1208 return Self::MAX;
1209 }
1210 return Self::MIN;
1211 }
1212
1213 unsafe { Self::new_unchecked(seconds, nanoseconds) }
1215 }
1216
1217 #[cfg(feature = "std")]
1220 #[doc(hidden)]
1221 #[inline]
1222 #[track_caller]
1223 #[deprecated(
1224 since = "0.3.32",
1225 note = "extremely limited use case, not intended for benchmarking"
1226 )]
1227 #[expect(deprecated)]
1228 pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
1229 let start = Instant::now();
1230 let return_value = f();
1231 let end = Instant::now();
1232
1233 (end - start, return_value)
1234 }
1235}
1236
1237impl fmt::Display for Duration {
1252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1253 if self.is_negative() {
1254 f.write_str("-")?;
1255 }
1256
1257 if let Some(_precision) = f.precision() {
1258 if self.is_zero() {
1261 return (0.).fmt(f).and_then(|_| f.write_str("s"));
1263 }
1264
1265 macro_rules! item {
1267 ($name:literal, $value:expr) => {
1268 let value = $value;
1269 if value >= 1.0 {
1270 return value.fmt(f).and_then(|_| f.write_str($name));
1271 }
1272 };
1273 }
1274
1275 let seconds = self.unsigned_abs().as_secs_f64();
1277
1278 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));
1279 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));
1280 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));
1281 let value = seconds;
if value >= 1.0 { return value.fmt(f).and_then(|_| f.write_str("s")); };item!("s", seconds);
1282 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));
1283 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));
1284 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));
1285 } else {
1286 if self.is_zero() {
1289 return f.write_str("0s");
1290 }
1291
1292 macro_rules! item {
1294 ($name:literal, $value:expr) => {
1295 match $value {
1296 0 => Ok(()),
1297 value => value.fmt(f).and_then(|_| f.write_str($name)),
1298 }
1299 };
1300 }
1301
1302 let seconds = self.seconds.unsigned_abs();
1303 let nanoseconds = self.nanoseconds.get().unsigned_abs();
1304
1305 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))?;
1306 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!(
1307 "h",
1308 seconds / Second::per_t::<u64>(Hour) % Hour::per_t::<u64>(Day)
1309 )?;
1310 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!(
1311 "m",
1312 seconds / Second::per_t::<u64>(Minute) % Minute::per_t::<u64>(Hour)
1313 )?;
1314 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))?;
1315 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))?;
1316 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!(
1317 "µs",
1318 nanoseconds / Nanosecond::per_t::<u32>(Microsecond)
1319 % Microsecond::per_t::<u32>(Millisecond)
1320 )?;
1321 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))?;
1322 }
1323
1324 Ok(())
1325 }
1326}
1327
1328impl TryFrom<StdDuration> for Duration {
1329 type Error = error::ConversionRange;
1330
1331 #[inline]
1332 fn try_from(original: StdDuration) -> Result<Self, error::ConversionRange> {
1333 Ok(Self::new(
1334 original
1335 .as_secs()
1336 .try_into()
1337 .map_err(|_| error::ConversionRange)?,
1338 original.subsec_nanos().cast_signed(),
1339 ))
1340 }
1341}
1342
1343impl TryFrom<Duration> for StdDuration {
1344 type Error = error::ConversionRange;
1345
1346 #[inline]
1347 fn try_from(duration: Duration) -> Result<Self, error::ConversionRange> {
1348 Ok(Self::new(
1349 duration
1350 .seconds
1351 .try_into()
1352 .map_err(|_| error::ConversionRange)?,
1353 duration
1354 .nanoseconds
1355 .get()
1356 .try_into()
1357 .map_err(|_| error::ConversionRange)?,
1358 ))
1359 }
1360}
1361
1362impl Add for Duration {
1363 type Output = Self;
1364
1365 #[inline]
1369 #[track_caller]
1370 fn add(self, rhs: Self) -> Self::Output {
1371 self.checked_add(rhs)
1372 .expect("overflow when adding durations")
1373 }
1374}
1375
1376impl Add<StdDuration> for Duration {
1377 type Output = Self;
1378
1379 #[inline]
1383 #[track_caller]
1384 fn add(self, std_duration: StdDuration) -> Self::Output {
1385 self + Self::try_from(std_duration)
1386 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1387 }
1388}
1389
1390impl Add<Duration> for StdDuration {
1391 type Output = Duration;
1392
1393 #[inline]
1394 #[track_caller]
1395 fn add(self, rhs: Duration) -> Self::Output {
1396 rhs + self
1397 }
1398}
1399
1400#[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);
1401
1402impl AddAssign<Duration> for StdDuration {
1403 #[inline]
1407 #[track_caller]
1408 fn add_assign(&mut self, rhs: Duration) {
1409 *self = (*self + rhs).try_into().expect(
1410 "Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
1411 change the type.",
1412 );
1413 }
1414}
1415
1416impl Neg for Duration {
1417 type Output = Self;
1418
1419 #[inline]
1420 #[track_caller]
1421 fn neg(self) -> Self::Output {
1422 self.checked_neg().expect("overflow when negating duration")
1423 }
1424}
1425
1426impl Sub for Duration {
1427 type Output = Self;
1428
1429 #[inline]
1433 #[track_caller]
1434 fn sub(self, rhs: Self) -> Self::Output {
1435 self.checked_sub(rhs)
1436 .expect("overflow when subtracting durations")
1437 }
1438}
1439
1440impl Sub<StdDuration> for Duration {
1441 type Output = Self;
1442
1443 #[inline]
1447 #[track_caller]
1448 fn sub(self, rhs: StdDuration) -> Self::Output {
1449 self - Self::try_from(rhs)
1450 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1451 }
1452}
1453
1454impl Sub<Duration> for StdDuration {
1455 type Output = Duration;
1456
1457 #[inline]
1461 #[track_caller]
1462 fn sub(self, rhs: Duration) -> Self::Output {
1463 Duration::try_from(self)
1464 .expect("overflow converting `std::time::Duration` to `time::Duration`")
1465 - rhs
1466 }
1467}
1468
1469#[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);
1470
1471impl SubAssign<Duration> for StdDuration {
1472 #[inline]
1476 #[track_caller]
1477 fn sub_assign(&mut self, rhs: Duration) {
1478 *self = (*self - rhs).try_into().expect(
1479 "Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
1480 change the type.",
1481 );
1482 }
1483}
1484
1485macro_rules! duration_mul_div_int {
1487 ($($type:ty),+) => {$(
1488 impl Mul<$type> for Duration {
1489 type Output = Self;
1490
1491 #[inline]
1492 #[track_caller]
1493 fn mul(self, rhs: $type) -> Self::Output {
1494 Self::nanoseconds_i128(
1495 self.whole_nanoseconds()
1496 .checked_mul(rhs.cast_signed().extend::<i128>())
1497 .expect("overflow when multiplying duration")
1498 )
1499 }
1500 }
1501
1502 impl Mul<Duration> for $type {
1503 type Output = Duration;
1504
1505 #[inline]
1506 #[track_caller]
1507 fn mul(self, rhs: Duration) -> Self::Output {
1508 rhs * self
1509 }
1510 }
1511
1512 impl Div<$type> for Duration {
1513 type Output = Self;
1514
1515 #[inline]
1516 #[track_caller]
1517 fn div(self, rhs: $type) -> Self::Output {
1518 Self::nanoseconds_i128(
1519 self.whole_nanoseconds() / rhs.cast_signed().extend::<i128>()
1520 )
1521 }
1522 }
1523 )+};
1524}
1525impl 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];
1526
1527impl Mul<f32> for Duration {
1528 type Output = Self;
1529
1530 #[inline]
1531 #[track_caller]
1532 fn mul(self, rhs: f32) -> Self::Output {
1533 Self::seconds_f32(self.as_seconds_f32() * rhs)
1534 }
1535}
1536
1537impl Mul<Duration> for f32 {
1538 type Output = Duration;
1539
1540 #[inline]
1541 #[track_caller]
1542 fn mul(self, rhs: Duration) -> Self::Output {
1543 rhs * self
1544 }
1545}
1546
1547impl Mul<f64> for Duration {
1548 type Output = Self;
1549
1550 #[inline]
1551 #[track_caller]
1552 fn mul(self, rhs: f64) -> Self::Output {
1553 Self::seconds_f64(self.as_seconds_f64() * rhs)
1554 }
1555}
1556
1557impl Mul<Duration> for f64 {
1558 type Output = Duration;
1559
1560 #[inline]
1561 #[track_caller]
1562 fn mul(self, rhs: Duration) -> Self::Output {
1563 rhs * self
1564 }
1565}
1566
1567#[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);
1568
1569impl Div<f32> for Duration {
1570 type Output = Self;
1571
1572 #[inline]
1573 #[track_caller]
1574 fn div(self, rhs: f32) -> Self::Output {
1575 Self::seconds_f32(self.as_seconds_f32() / rhs)
1576 }
1577}
1578
1579impl Div<f64> for Duration {
1580 type Output = Self;
1581
1582 #[inline]
1583 #[track_caller]
1584 fn div(self, rhs: f64) -> Self::Output {
1585 Self::seconds_f64(self.as_seconds_f64() / rhs)
1586 }
1587}
1588
1589#[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);
1590
1591impl Div for Duration {
1592 type Output = f64;
1593
1594 #[inline]
1595 #[track_caller]
1596 fn div(self, rhs: Self) -> Self::Output {
1597 self.as_seconds_f64() / rhs.as_seconds_f64()
1598 }
1599}
1600
1601impl Div<StdDuration> for Duration {
1602 type Output = f64;
1603
1604 #[inline]
1605 #[track_caller]
1606 fn div(self, rhs: StdDuration) -> Self::Output {
1607 self.as_seconds_f64() / rhs.as_secs_f64()
1608 }
1609}
1610
1611impl Div<Duration> for StdDuration {
1612 type Output = f64;
1613
1614 #[inline]
1615 #[track_caller]
1616 fn div(self, rhs: Duration) -> Self::Output {
1617 self.as_secs_f64() / rhs.as_seconds_f64()
1618 }
1619}
1620
1621impl PartialEq<StdDuration> for Duration {
1622 #[inline]
1623 fn eq(&self, rhs: &StdDuration) -> bool {
1624 Ok(*self) == Self::try_from(*rhs)
1625 }
1626}
1627
1628impl PartialEq<Duration> for StdDuration {
1629 #[inline]
1630 fn eq(&self, rhs: &Duration) -> bool {
1631 rhs == self
1632 }
1633}
1634
1635impl PartialOrd<StdDuration> for Duration {
1636 #[inline]
1637 fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
1638 if rhs.as_secs() > i64::MAX.cast_unsigned() {
1639 return Some(Ordering::Less);
1640 }
1641
1642 Some(
1643 self.seconds
1644 .cmp(&rhs.as_secs().cast_signed())
1645 .then_with(|| {
1646 self.nanoseconds
1647 .get()
1648 .cmp(&rhs.subsec_nanos().cast_signed())
1649 }),
1650 )
1651 }
1652}
1653
1654impl PartialOrd<Duration> for StdDuration {
1655 #[inline]
1656 fn partial_cmp(&self, rhs: &Duration) -> Option<Ordering> {
1657 rhs.partial_cmp(self).map(Ordering::reverse)
1658 }
1659}
1660
1661impl Sum for Duration {
1662 #[inline]
1663 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1664 iter.reduce(|a, b| a + b).unwrap_or_default()
1665 }
1666}
1667
1668impl<'a> Sum<&'a Self> for Duration {
1669 #[inline]
1670 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1671 iter.copied().sum()
1672 }
1673}
1674
1675#[cfg(feature = "std")]
1676impl Add<Duration> for SystemTime {
1677 type Output = Self;
1678
1679 #[inline]
1680 #[track_caller]
1681 fn add(self, duration: Duration) -> Self::Output {
1682 if duration.is_zero() {
1683 self
1684 } else if duration.is_positive() {
1685 self + duration.unsigned_abs()
1686 } else {
1687 if true {
if !duration.is_negative() {
::core::panicking::panic("assertion failed: duration.is_negative()")
};
};debug_assert!(duration.is_negative());
1688 self - duration.unsigned_abs()
1689 }
1690 }
1691}
1692
1693#[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);
1694
1695#[cfg(feature = "std")]
1696impl Sub<Duration> for SystemTime {
1697 type Output = Self;
1698
1699 #[inline]
1700 #[track_caller]
1701 fn sub(self, duration: Duration) -> Self::Output {
1702 if duration.is_zero() {
1703 self
1704 } else if duration.is_positive() {
1705 self - duration.unsigned_abs()
1706 } else {
1707 if true {
if !duration.is_negative() {
::core::panicking::panic("assertion failed: duration.is_negative()")
};
};debug_assert!(duration.is_negative());
1708 self + duration.unsigned_abs()
1709 }
1710 }
1711}
1712
1713#[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);