1use core::fmt;
14use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
15use core::time::Duration;
16#[cfg(feature = "std")]
17use std::error::Error;
18
19use crate::{expect, try_opt};
20
21#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
22use rkyv::{Archive, Deserialize, Serialize};
23
24const NANOS_PER_MICRO: i32 = 1000;
26const NANOS_PER_MILLI: i32 = 1_000_000;
28pub(crate) const NANOS_PER_SEC: i32 = 1_000_000_000;
30const MICROS_PER_SEC: i64 = 1_000_000;
32const MILLIS_PER_SEC: i64 = 1000;
34const SECS_PER_MINUTE: i64 = 60;
36const SECS_PER_HOUR: i64 = 3600;
38const SECS_PER_DAY: i64 = 86_400;
40const SECS_PER_WEEK: i64 = 604_800;
42
43#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
53#[cfg_attr(
54 any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
55 derive(Archive, Deserialize, Serialize),
56 archive(compare(PartialEq, PartialOrd)),
57 archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
58)]
59#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
60pub struct TimeDelta {
61 secs: i64,
62 nanos: i32, }
64
65pub(crate) const MIN: TimeDelta = TimeDelta {
67 secs: -i64::MAX / MILLIS_PER_SEC - 1,
68 nanos: NANOS_PER_SEC + (-i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
69};
70
71pub(crate) const MAX: TimeDelta = TimeDelta {
73 secs: i64::MAX / MILLIS_PER_SEC,
74 nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
75};
76
77impl TimeDelta {
78 pub const fn new(secs: i64, nanos: u32) -> Option<TimeDelta> {
84 if secs < MIN.secs
85 || secs > MAX.secs
86 || nanos >= 1_000_000_000
87 || (secs == MAX.secs && nanos > MAX.nanos as u32)
88 || (secs == MIN.secs && nanos < MIN.nanos as u32)
89 {
90 return None;
91 }
92 Some(TimeDelta { secs, nanos: nanos as i32 })
93 }
94
95 #[inline]
104 #[must_use]
105 pub const fn weeks(weeks: i64) -> TimeDelta {
106 expect(TimeDelta::try_weeks(weeks), "TimeDelta::weeks out of bounds")
107 }
108
109 #[inline]
118 pub const fn try_weeks(weeks: i64) -> Option<TimeDelta> {
119 TimeDelta::try_seconds(try_opt!(weeks.checked_mul(SECS_PER_WEEK)))
120 }
121
122 #[inline]
131 #[must_use]
132 pub const fn days(days: i64) -> TimeDelta {
133 expect(TimeDelta::try_days(days), "TimeDelta::days out of bounds")
134 }
135
136 #[inline]
145 pub const fn try_days(days: i64) -> Option<TimeDelta> {
146 TimeDelta::try_seconds(try_opt!(days.checked_mul(SECS_PER_DAY)))
147 }
148
149 #[inline]
157 #[must_use]
158 pub const fn hours(hours: i64) -> TimeDelta {
159 expect(TimeDelta::try_hours(hours), "TimeDelta::hours out of bounds")
160 }
161
162 #[inline]
170 pub const fn try_hours(hours: i64) -> Option<TimeDelta> {
171 TimeDelta::try_seconds(try_opt!(hours.checked_mul(SECS_PER_HOUR)))
172 }
173
174 #[inline]
182 #[must_use]
183 pub const fn minutes(minutes: i64) -> TimeDelta {
184 expect(TimeDelta::try_minutes(minutes), "TimeDelta::minutes out of bounds")
185 }
186
187 #[inline]
195 pub const fn try_minutes(minutes: i64) -> Option<TimeDelta> {
196 TimeDelta::try_seconds(try_opt!(minutes.checked_mul(SECS_PER_MINUTE)))
197 }
198
199 #[inline]
206 #[must_use]
207 pub const fn seconds(seconds: i64) -> TimeDelta {
208 expect(TimeDelta::try_seconds(seconds), "TimeDelta::seconds out of bounds")
209 }
210
211 #[inline]
219 pub const fn try_seconds(seconds: i64) -> Option<TimeDelta> {
220 TimeDelta::new(seconds, 0)
221 }
222
223 #[inline]
230 pub const fn milliseconds(milliseconds: i64) -> TimeDelta {
231 expect(TimeDelta::try_milliseconds(milliseconds), "TimeDelta::milliseconds out of bounds")
232 }
233
234 #[inline]
241 pub const fn try_milliseconds(milliseconds: i64) -> Option<TimeDelta> {
242 if milliseconds < -i64::MAX {
245 return None;
246 }
247 let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
248 let d = TimeDelta { secs, nanos: millis as i32 * NANOS_PER_MILLI };
249 Some(d)
250 }
251
252 #[inline]
259 pub const fn microseconds(microseconds: i64) -> TimeDelta {
260 let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
261 let nanos = micros as i32 * NANOS_PER_MICRO;
262 TimeDelta { secs, nanos }
263 }
264
265 #[inline]
272 pub const fn nanoseconds(nanos: i64) -> TimeDelta {
273 let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
274 TimeDelta { secs, nanos: nanos as i32 }
275 }
276
277 #[inline]
279 pub const fn num_weeks(&self) -> i64 {
280 self.num_days() / 7
281 }
282
283 #[inline]
285 pub const fn num_days(&self) -> i64 {
286 self.num_seconds() / SECS_PER_DAY
287 }
288
289 #[inline]
291 pub const fn num_hours(&self) -> i64 {
292 self.num_seconds() / SECS_PER_HOUR
293 }
294
295 #[inline]
297 pub const fn num_minutes(&self) -> i64 {
298 self.num_seconds() / SECS_PER_MINUTE
299 }
300
301 pub const fn num_seconds(&self) -> i64 {
303 if self.secs < 0 && self.nanos > 0 {
305 self.secs + 1
306 } else {
307 self.secs
308 }
309 }
310
311 pub const fn subsec_nanos(&self) -> i32 {
315 if self.secs < 0 && self.nanos > 0 {
316 self.nanos - NANOS_PER_SEC
317 } else {
318 self.nanos
319 }
320 }
321
322 pub const fn num_milliseconds(&self) -> i64 {
324 let secs_part = self.num_seconds() * MILLIS_PER_SEC;
328 let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
329 secs_part + nanos_part as i64
330 }
331
332 pub const fn num_microseconds(&self) -> Option<i64> {
335 let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
336 let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
337 secs_part.checked_add(nanos_part as i64)
338 }
339
340 pub const fn num_nanoseconds(&self) -> Option<i64> {
343 let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
344 let nanos_part = self.subsec_nanos();
345 secs_part.checked_add(nanos_part as i64)
346 }
347
348 #[must_use]
350 pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
351 let mut secs = self.secs + rhs.secs;
354 let mut nanos = self.nanos + rhs.nanos;
355 if nanos >= NANOS_PER_SEC {
356 nanos -= NANOS_PER_SEC;
357 secs += 1;
358 }
359 TimeDelta::new(secs, nanos as u32)
360 }
361
362 #[must_use]
364 pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
365 let mut secs = self.secs - rhs.secs;
368 let mut nanos = self.nanos - rhs.nanos;
369 if nanos < 0 {
370 nanos += NANOS_PER_SEC;
371 secs -= 1;
372 }
373 TimeDelta::new(secs, nanos as u32)
374 }
375
376 #[must_use]
378 pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
379 let total_nanos = self.nanos as i64 * rhs as i64;
381 let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
382 let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
384 if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
385 return None;
386 };
387 Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
388 }
389
390 #[must_use]
392 pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
393 if rhs == 0 {
394 return None;
395 }
396 let secs = self.secs / rhs as i64;
397 let carry = self.secs % rhs as i64;
398 let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
399 let nanos = self.nanos / rhs + extra_nanos as i32;
400
401 let (secs, nanos) = match nanos {
402 i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
403 NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
404 _ => (secs, nanos),
405 };
406
407 Some(TimeDelta { secs, nanos })
408 }
409
410 #[inline]
412 pub const fn abs(&self) -> TimeDelta {
413 if self.secs < 0 && self.nanos != 0 {
414 TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
415 } else {
416 TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
417 }
418 }
419
420 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
422 #[inline]
423 pub const fn min_value() -> TimeDelta {
424 MIN
425 }
426
427 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
429 #[inline]
430 pub const fn max_value() -> TimeDelta {
431 MAX
432 }
433
434 #[inline]
436 pub const fn zero() -> TimeDelta {
437 TimeDelta { secs: 0, nanos: 0 }
438 }
439
440 #[inline]
442 pub const fn is_zero(&self) -> bool {
443 self.secs == 0 && self.nanos == 0
444 }
445
446 pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
451 if duration.as_secs() > MAX.secs as u64 {
453 return Err(OutOfRangeError(()));
454 }
455 match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
456 Some(d) => Ok(d),
457 None => Err(OutOfRangeError(())),
458 }
459 }
460
461 pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
466 if self.secs < 0 {
467 return Err(OutOfRangeError(()));
468 }
469 Ok(Duration::new(self.secs as u64, self.nanos as u32))
470 }
471
472 pub(crate) const fn neg(self) -> TimeDelta {
474 let (secs_diff, nanos) = match self.nanos {
475 0 => (0, 0),
476 nanos => (1, NANOS_PER_SEC - nanos),
477 };
478 TimeDelta { secs: -self.secs - secs_diff, nanos }
479 }
480
481 pub const MIN: Self = MIN;
483
484 pub const MAX: Self = MAX;
486}
487
488impl Neg for TimeDelta {
489 type Output = TimeDelta;
490
491 #[inline]
492 fn neg(self) -> TimeDelta {
493 let (secs_diff, nanos) = match self.nanos {
494 0 => (0, 0),
495 nanos => (1, NANOS_PER_SEC - nanos),
496 };
497 TimeDelta { secs: -self.secs - secs_diff, nanos }
498 }
499}
500
501impl Add for TimeDelta {
502 type Output = TimeDelta;
503
504 fn add(self, rhs: TimeDelta) -> TimeDelta {
505 self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
506 }
507}
508
509impl Sub for TimeDelta {
510 type Output = TimeDelta;
511
512 fn sub(self, rhs: TimeDelta) -> TimeDelta {
513 self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
514 }
515}
516
517impl AddAssign for TimeDelta {
518 fn add_assign(&mut self, rhs: TimeDelta) {
519 let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
520 *self = new;
521 }
522}
523
524impl SubAssign for TimeDelta {
525 fn sub_assign(&mut self, rhs: TimeDelta) {
526 let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
527 *self = new;
528 }
529}
530
531impl Mul<i32> for TimeDelta {
532 type Output = TimeDelta;
533
534 fn mul(self, rhs: i32) -> TimeDelta {
535 self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
536 }
537}
538
539impl Div<i32> for TimeDelta {
540 type Output = TimeDelta;
541
542 fn div(self, rhs: i32) -> TimeDelta {
543 self.checked_div(rhs).expect("`i32` is zero")
544 }
545}
546
547impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
548 fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
549 iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
550 }
551}
552
553impl core::iter::Sum<TimeDelta> for TimeDelta {
554 fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
555 iter.fold(TimeDelta::zero(), |acc, x| acc + x)
556 }
557}
558
559impl fmt::Display for TimeDelta {
560 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
564 let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
567
568 write!(f, "{}P", sign)?;
569 if abs.secs == 0 && abs.nanos == 0 {
571 return f.write_str("0D");
572 }
573
574 f.write_fmt(format_args!("T{}", abs.secs))?;
575
576 if abs.nanos > 0 {
577 let mut figures = 9usize;
579 let mut fraction_digits = abs.nanos;
580 loop {
581 let div = fraction_digits / 10;
582 let last_digit = fraction_digits % 10;
583 if last_digit != 0 {
584 break;
585 }
586 fraction_digits = div;
587 figures -= 1;
588 }
589 f.write_fmt(format_args!(".{:01$}", fraction_digits, figures))?;
590 }
591 f.write_str("S")?;
592 Ok(())
593 }
594}
595
596#[derive(Debug, Clone, Copy, PartialEq, Eq)]
603pub struct OutOfRangeError(());
604
605impl fmt::Display for OutOfRangeError {
606 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
607 write!(f, "Source duration value is out of range for the target type")
608 }
609}
610
611#[cfg(feature = "std")]
612impl Error for OutOfRangeError {
613 #[allow(deprecated)]
614 fn description(&self) -> &str {
615 "out of range error"
616 }
617}
618
619#[inline]
620const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
621 (this.div_euclid(other), this.rem_euclid(other))
622}
623
624#[cfg(all(feature = "arbitrary", feature = "std"))]
625impl arbitrary::Arbitrary<'_> for TimeDelta {
626 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
627 const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
628 const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
629
630 let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
631 let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
632 let duration = TimeDelta { secs, nanos };
633
634 if duration < MIN || duration > MAX {
635 Err(arbitrary::Error::IncorrectFormat)
636 } else {
637 Ok(duration)
638 }
639 }
640}
641
642#[cfg(feature = "serde")]
643mod serde {
644 use super::TimeDelta;
645 use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
646
647 impl Serialize for TimeDelta {
648 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
649 <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
650 }
651 }
652
653 impl<'de> Deserialize<'de> for TimeDelta {
654 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
655 let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
656 TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
657 }
658 }
659
660 #[cfg(test)]
661 mod tests {
662 use super::{super::MAX, TimeDelta};
663
664 #[test]
665 fn test_serde() {
666 let duration = TimeDelta::new(123, 456).unwrap();
667 assert_eq!(
668 serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
669 .unwrap(),
670 duration
671 );
672 }
673
674 #[test]
675 #[should_panic(expected = "TimeDelta out of bounds")]
676 fn test_serde_oob_panic() {
677 let _ =
678 serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
679 }
680 }
681}
682
683#[cfg(test)]
684mod tests {
685 use super::OutOfRangeError;
686 use super::{TimeDelta, MAX, MIN};
687 use crate::expect;
688 use core::time::Duration;
689
690 #[test]
691 fn test_duration() {
692 let days = |d| TimeDelta::try_days(d).unwrap();
693 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
694
695 assert!(seconds(1) != TimeDelta::zero());
696 assert_eq!(seconds(1) + seconds(2), seconds(3));
697 assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
698 assert_eq!(days(10) - seconds(1000), seconds(863_000));
699 assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
700 assert_eq!(
701 days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
702 days(3) + TimeDelta::nanoseconds(234_567_890)
703 );
704 assert_eq!(-days(3), days(-3));
705 assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
706
707 let mut d = TimeDelta::default();
708 d += TimeDelta::try_minutes(1).unwrap();
709 d -= seconds(30);
710 assert_eq!(d, seconds(30));
711 }
712
713 #[test]
714 fn test_duration_num_days() {
715 assert_eq!(TimeDelta::zero().num_days(), 0);
716 assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
717 assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
718 assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
719 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().num_days(), 1);
720 assert_eq!(TimeDelta::try_seconds(-86_399).unwrap().num_days(), 0);
721 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().num_days(), -1);
722 assert_eq!(TimeDelta::try_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
723 assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
724 }
725
726 #[test]
727 fn test_duration_num_seconds() {
728 assert_eq!(TimeDelta::zero().num_seconds(), 0);
729 assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
730 assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
731 assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
732 assert_eq!(TimeDelta::try_milliseconds(1001).unwrap().num_seconds(), 1);
733 assert_eq!(TimeDelta::try_milliseconds(-999).unwrap().num_seconds(), 0);
734 assert_eq!(TimeDelta::try_milliseconds(-1001).unwrap().num_seconds(), -1);
735 }
736
737 #[test]
738 fn test_duration_seconds_max_allowed() {
739 let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
740 assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
741 assert_eq!(
742 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
743 i64::MAX as i128 / 1_000 * 1_000_000_000
744 );
745 }
746
747 #[test]
748 fn test_duration_seconds_max_overflow() {
749 assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
750 }
751
752 #[test]
753 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
754 fn test_duration_seconds_max_overflow_panic() {
755 let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
756 }
757
758 #[test]
759 fn test_duration_seconds_min_allowed() {
760 let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); assert_eq!(duration.num_seconds(), i64::MIN / 1_000); assert_eq!(
763 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
764 -i64::MAX as i128 / 1_000 * 1_000_000_000
765 );
766 }
767
768 #[test]
769 fn test_duration_seconds_min_underflow() {
770 assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
771 }
772
773 #[test]
774 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
775 fn test_duration_seconds_min_underflow_panic() {
776 let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
777 }
778
779 #[test]
780 fn test_duration_num_milliseconds() {
781 assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
782 assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
783 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
784 assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
785 assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
786 assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
787 assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
788 }
789
790 #[test]
791 fn test_duration_milliseconds_max_allowed() {
792 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
795 assert_eq!(duration.num_milliseconds(), i64::MAX);
796 assert_eq!(
797 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
798 i64::MAX as i128 * 1_000_000
799 );
800 }
801
802 #[test]
803 fn test_duration_milliseconds_max_overflow() {
804 assert!(TimeDelta::try_milliseconds(i64::MAX)
807 .unwrap()
808 .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
809 .is_none());
810 }
811
812 #[test]
813 fn test_duration_milliseconds_min_allowed() {
814 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
818 assert_eq!(duration.num_milliseconds(), -i64::MAX);
819 assert_eq!(
820 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
821 -i64::MAX as i128 * 1_000_000
822 );
823 }
824
825 #[test]
826 fn test_duration_milliseconds_min_underflow() {
827 assert!(TimeDelta::try_milliseconds(-i64::MAX)
830 .unwrap()
831 .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
832 .is_none());
833 }
834
835 #[test]
836 #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
837 fn test_duration_milliseconds_min_underflow_panic() {
838 let _ = TimeDelta::milliseconds(i64::MIN); }
844
845 #[test]
846 fn test_duration_num_microseconds() {
847 assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
848 assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
849 assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
850 assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
851 assert_eq!(TimeDelta::nanoseconds(1001).num_microseconds(), Some(1));
852 assert_eq!(TimeDelta::nanoseconds(-999).num_microseconds(), Some(0));
853 assert_eq!(TimeDelta::nanoseconds(-1001).num_microseconds(), Some(-1));
854
855 const MICROS_PER_DAY: i64 = 86_400_000_000;
857 assert_eq!(
858 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
859 Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
860 );
861 assert_eq!(
862 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
863 Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
864 );
865 assert_eq!(
866 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
867 None
868 );
869 assert_eq!(
870 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
871 None
872 );
873 }
874 #[test]
875 fn test_duration_microseconds_max_allowed() {
876 let duration = TimeDelta::microseconds(i64::MAX);
880 assert_eq!(duration.num_microseconds(), Some(i64::MAX));
881 assert_eq!(
882 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
883 i64::MAX as i128 * 1_000
884 );
885 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
890 assert!(duration.num_microseconds().is_none());
891 assert_eq!(
892 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
893 i64::MAX as i128 * 1_000_000
894 );
895 }
896 #[test]
897 fn test_duration_microseconds_max_overflow() {
898 let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
901 assert!(duration.num_microseconds().is_none());
902 assert_eq!(
903 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
904 (i64::MAX as i128 + 1) * 1_000
905 );
906 assert!(TimeDelta::try_milliseconds(i64::MAX)
909 .unwrap()
910 .checked_add(&TimeDelta::microseconds(1))
911 .is_none());
912 }
913 #[test]
914 fn test_duration_microseconds_min_allowed() {
915 let duration = TimeDelta::microseconds(i64::MIN);
919 assert_eq!(duration.num_microseconds(), Some(i64::MIN));
920 assert_eq!(
921 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
922 i64::MIN as i128 * 1_000
923 );
924 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
929 assert!(duration.num_microseconds().is_none());
930 assert_eq!(
931 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
932 -i64::MAX as i128 * 1_000_000
933 );
934 }
935 #[test]
936 fn test_duration_microseconds_min_underflow() {
937 let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
940 assert!(duration.num_microseconds().is_none());
941 assert_eq!(
942 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
943 (i64::MIN as i128 - 1) * 1_000
944 );
945 assert!(TimeDelta::try_milliseconds(-i64::MAX)
948 .unwrap()
949 .checked_sub(&TimeDelta::microseconds(1))
950 .is_none());
951 }
952
953 #[test]
954 fn test_duration_num_nanoseconds() {
955 assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
956 assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
957 assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
958
959 const NANOS_PER_DAY: i64 = 86_400_000_000_000;
961 assert_eq!(
962 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
963 Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
964 );
965 assert_eq!(
966 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
967 Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
968 );
969 assert_eq!(
970 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
971 None
972 );
973 assert_eq!(
974 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
975 None
976 );
977 }
978 #[test]
979 fn test_duration_nanoseconds_max_allowed() {
980 let duration = TimeDelta::nanoseconds(i64::MAX);
984 assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
985 assert_eq!(
986 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
987 i64::MAX as i128
988 );
989 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
993 assert!(duration.num_nanoseconds().is_none());
994 assert_eq!(
995 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
996 i64::MAX as i128 * 1_000_000
997 );
998 }
999
1000 #[test]
1001 fn test_duration_nanoseconds_max_overflow() {
1002 let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1005 assert!(duration.num_nanoseconds().is_none());
1006 assert_eq!(
1007 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1008 i64::MAX as i128 + 1
1009 );
1010 assert!(TimeDelta::try_milliseconds(i64::MAX)
1013 .unwrap()
1014 .checked_add(&TimeDelta::nanoseconds(1))
1015 .is_none());
1016 }
1017
1018 #[test]
1019 fn test_duration_nanoseconds_min_allowed() {
1020 let duration = TimeDelta::nanoseconds(i64::MIN);
1024 assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1025 assert_eq!(
1026 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1027 i64::MIN as i128
1028 );
1029 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1033 assert!(duration.num_nanoseconds().is_none());
1034 assert_eq!(
1035 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1036 -i64::MAX as i128 * 1_000_000
1037 );
1038 }
1039
1040 #[test]
1041 fn test_duration_nanoseconds_min_underflow() {
1042 let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1045 assert!(duration.num_nanoseconds().is_none());
1046 assert_eq!(
1047 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1048 i64::MIN as i128 - 1
1049 );
1050 assert!(TimeDelta::try_milliseconds(-i64::MAX)
1053 .unwrap()
1054 .checked_sub(&TimeDelta::nanoseconds(1))
1055 .is_none());
1056 }
1057
1058 #[test]
1059 fn test_max() {
1060 assert_eq!(
1061 MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1062 i64::MAX as i128 * 1_000_000
1063 );
1064 assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1065 assert_eq!(MAX.num_milliseconds(), i64::MAX);
1066 assert_eq!(MAX.num_microseconds(), None);
1067 assert_eq!(MAX.num_nanoseconds(), None);
1068 }
1069
1070 #[test]
1071 fn test_min() {
1072 assert_eq!(
1073 MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1074 -i64::MAX as i128 * 1_000_000
1075 );
1076 assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1077 assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1078 assert_eq!(MIN.num_microseconds(), None);
1079 assert_eq!(MIN.num_nanoseconds(), None);
1080 }
1081
1082 #[test]
1083 fn test_duration_ord() {
1084 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1085
1086 assert!(milliseconds(1) < milliseconds(2));
1087 assert!(milliseconds(2) > milliseconds(1));
1088 assert!(milliseconds(-1) > milliseconds(-2));
1089 assert!(milliseconds(-2) < milliseconds(-1));
1090 assert!(milliseconds(-1) < milliseconds(1));
1091 assert!(milliseconds(1) > milliseconds(-1));
1092 assert!(milliseconds(0) < milliseconds(1));
1093 assert!(milliseconds(0) > milliseconds(-1));
1094 assert!(milliseconds(1_001) < milliseconds(1_002));
1095 assert!(milliseconds(-1_001) > milliseconds(-1_002));
1096 assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1097 assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1098 assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1099 assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1100 }
1101
1102 #[test]
1103 fn test_duration_checked_ops() {
1104 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1105 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1106
1107 assert_eq!(
1108 milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1109 Some(milliseconds(i64::MAX))
1110 );
1111 assert_eq!(
1112 milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1113 Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1114 );
1115 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1116 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1117
1118 assert_eq!(
1119 milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1120 Some(milliseconds(-i64::MAX))
1121 );
1122 assert_eq!(
1123 milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1124 Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1125 );
1126 assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1127 assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1128
1129 assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1130 assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1131 assert!(seconds(1).checked_div(0).is_none());
1132 }
1133
1134 #[test]
1135 fn test_duration_abs() {
1136 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1137
1138 assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1139 assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1140 assert_eq!(milliseconds(300).abs(), milliseconds(300));
1141 assert_eq!(milliseconds(0).abs(), milliseconds(0));
1142 assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1143 assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1144 assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1145 assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1146 assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1147 assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1148 }
1149
1150 #[test]
1151 #[allow(clippy::erasing_op)]
1152 fn test_duration_mul() {
1153 assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1154 assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1155 assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1156 assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1157 assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1158 assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1159 assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1160 assert_eq!(
1161 TimeDelta::nanoseconds(30) * 333_333_333,
1162 TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1163 );
1164 assert_eq!(
1165 (TimeDelta::nanoseconds(1)
1166 + TimeDelta::try_seconds(1).unwrap()
1167 + TimeDelta::try_days(1).unwrap())
1168 * 3,
1169 TimeDelta::nanoseconds(3)
1170 + TimeDelta::try_seconds(3).unwrap()
1171 + TimeDelta::try_days(3).unwrap()
1172 );
1173 assert_eq!(
1174 TimeDelta::try_milliseconds(1500).unwrap() * -2,
1175 TimeDelta::try_seconds(-3).unwrap()
1176 );
1177 assert_eq!(
1178 TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1179 TimeDelta::try_seconds(-3).unwrap()
1180 );
1181 }
1182
1183 #[test]
1184 fn test_duration_div() {
1185 assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1186 assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1187 assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1188 assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
1189 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / -1, TimeDelta::nanoseconds(123_456_789));
1190 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / 1, -TimeDelta::nanoseconds(123_456_789));
1191 assert_eq!(TimeDelta::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1192 assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1193 assert_eq!(
1194 TimeDelta::try_seconds(-1).unwrap() / 2,
1195 TimeDelta::try_milliseconds(-500).unwrap()
1196 );
1197 assert_eq!(
1198 TimeDelta::try_seconds(1).unwrap() / -2,
1199 TimeDelta::try_milliseconds(-500).unwrap()
1200 );
1201 assert_eq!(
1202 TimeDelta::try_seconds(-1).unwrap() / -2,
1203 TimeDelta::try_milliseconds(500).unwrap()
1204 );
1205 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1206 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1207 }
1208
1209 #[test]
1210 fn test_duration_sum() {
1211 let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1212 let sum_1: TimeDelta = duration_list_1.iter().sum();
1213 assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1214
1215 let duration_list_2 = [
1216 TimeDelta::zero(),
1217 TimeDelta::try_seconds(1).unwrap(),
1218 TimeDelta::try_seconds(6).unwrap(),
1219 TimeDelta::try_seconds(10).unwrap(),
1220 ];
1221 let sum_2: TimeDelta = duration_list_2.iter().sum();
1222 assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1223
1224 let duration_arr = [
1225 TimeDelta::zero(),
1226 TimeDelta::try_seconds(1).unwrap(),
1227 TimeDelta::try_seconds(6).unwrap(),
1228 TimeDelta::try_seconds(10).unwrap(),
1229 ];
1230 let sum_3: TimeDelta = duration_arr.into_iter().sum();
1231 assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1232 }
1233
1234 #[test]
1235 fn test_duration_fmt() {
1236 assert_eq!(TimeDelta::zero().to_string(), "P0D");
1237 assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1238 assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1239 assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1240 assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1241 assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1242 assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1243 assert_eq!(
1244 (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1245 .to_string(),
1246 "PT604806.543S"
1247 );
1248 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1249 assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1250
1251 assert_eq!(
1253 format!(
1254 "{:30}",
1255 TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1256 ),
1257 "PT86402.345S"
1258 );
1259 }
1260
1261 #[test]
1262 fn test_to_std() {
1263 assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1264 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1265 assert_eq!(
1266 TimeDelta::try_milliseconds(123).unwrap().to_std(),
1267 Ok(Duration::new(0, 123_000_000))
1268 );
1269 assert_eq!(
1270 TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1271 Ok(Duration::new(123, 765_000_000))
1272 );
1273 assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1274 assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1275 assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1276 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1277 }
1278
1279 #[test]
1280 fn test_from_std() {
1281 assert_eq!(
1282 Ok(TimeDelta::try_seconds(1).unwrap()),
1283 TimeDelta::from_std(Duration::new(1, 0))
1284 );
1285 assert_eq!(
1286 Ok(TimeDelta::try_seconds(86_401).unwrap()),
1287 TimeDelta::from_std(Duration::new(86_401, 0))
1288 );
1289 assert_eq!(
1290 Ok(TimeDelta::try_milliseconds(123).unwrap()),
1291 TimeDelta::from_std(Duration::new(0, 123_000_000))
1292 );
1293 assert_eq!(
1294 Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1295 TimeDelta::from_std(Duration::new(123, 765_000_000))
1296 );
1297 assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1298 assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1299 assert_eq!(
1300 TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1301 Err(OutOfRangeError(()))
1302 );
1303 assert_eq!(
1304 TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1305 Err(OutOfRangeError(()))
1306 );
1307 }
1308
1309 #[test]
1310 fn test_duration_const() {
1311 const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1312 const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1313 const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1314 const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1315 const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1316 const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1317 const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1318 const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1319 let combo: TimeDelta = ONE_WEEK
1320 + ONE_DAY
1321 + ONE_HOUR
1322 + ONE_MINUTE
1323 + ONE_SECOND
1324 + ONE_MILLI
1325 + ONE_MICRO
1326 + ONE_NANO;
1327
1328 assert!(ONE_WEEK != TimeDelta::zero());
1329 assert!(ONE_DAY != TimeDelta::zero());
1330 assert!(ONE_HOUR != TimeDelta::zero());
1331 assert!(ONE_MINUTE != TimeDelta::zero());
1332 assert!(ONE_SECOND != TimeDelta::zero());
1333 assert!(ONE_MILLI != TimeDelta::zero());
1334 assert!(ONE_MICRO != TimeDelta::zero());
1335 assert!(ONE_NANO != TimeDelta::zero());
1336 assert_eq!(
1337 combo,
1338 TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1339 + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1340 );
1341 }
1342
1343 #[test]
1344 #[cfg(feature = "rkyv-validation")]
1345 fn test_rkyv_validation() {
1346 let duration = TimeDelta::try_seconds(1).unwrap();
1347 let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1348 assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1349 }
1350}