1#[cfg(all(not(feature = "std"), feature = "core-error"))]
14use core::error::Error;
15use core::fmt;
16use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
17use core::time::Duration;
18#[cfg(feature = "std")]
19use std::error::Error;
20
21use crate::{expect, try_opt};
22
23#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
24use rkyv::{Archive, Deserialize, Serialize};
25
26const NANOS_PER_MICRO: i32 = 1000;
28const NANOS_PER_MILLI: i32 = 1_000_000;
30pub(crate) const NANOS_PER_SEC: i32 = 1_000_000_000;
32const MICROS_PER_SEC: i64 = 1_000_000;
34const MILLIS_PER_SEC: i64 = 1000;
36const SECS_PER_MINUTE: i64 = 60;
38const SECS_PER_HOUR: i64 = 3600;
40const SECS_PER_DAY: i64 = 86_400;
42const SECS_PER_WEEK: i64 = 604_800;
44
45#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
55#[cfg_attr(
56 any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
57 derive(Archive, Deserialize, Serialize),
58 archive(compare(PartialEq, PartialOrd)),
59 archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
60)]
61#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub struct TimeDelta {
64 secs: i64,
65 nanos: i32, }
67
68pub(crate) const MIN: TimeDelta = TimeDelta {
70 secs: -i64::MAX / MILLIS_PER_SEC - 1,
71 nanos: NANOS_PER_SEC + (-i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
72};
73
74pub(crate) const MAX: TimeDelta = TimeDelta {
76 secs: i64::MAX / MILLIS_PER_SEC,
77 nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
78};
79
80impl TimeDelta {
81 pub const fn new(secs: i64, nanos: u32) -> Option<TimeDelta> {
87 if secs < MIN.secs
88 || secs > MAX.secs
89 || nanos >= 1_000_000_000
90 || (secs == MAX.secs && nanos > MAX.nanos as u32)
91 || (secs == MIN.secs && nanos < MIN.nanos as u32)
92 {
93 return None;
94 }
95 Some(TimeDelta { secs, nanos: nanos as i32 })
96 }
97
98 #[inline]
107 #[must_use]
108 #[track_caller]
109 pub const fn weeks(weeks: i64) -> TimeDelta {
110 expect(TimeDelta::try_weeks(weeks), "TimeDelta::weeks out of bounds")
111 }
112
113 #[inline]
122 pub const fn try_weeks(weeks: i64) -> Option<TimeDelta> {
123 TimeDelta::try_seconds(try_opt!(weeks.checked_mul(SECS_PER_WEEK)))
124 }
125
126 #[inline]
135 #[must_use]
136 #[track_caller]
137 pub const fn days(days: i64) -> TimeDelta {
138 expect(TimeDelta::try_days(days), "TimeDelta::days out of bounds")
139 }
140
141 #[inline]
150 pub const fn try_days(days: i64) -> Option<TimeDelta> {
151 TimeDelta::try_seconds(try_opt!(days.checked_mul(SECS_PER_DAY)))
152 }
153
154 #[inline]
162 #[must_use]
163 #[track_caller]
164 pub const fn hours(hours: i64) -> TimeDelta {
165 expect(TimeDelta::try_hours(hours), "TimeDelta::hours out of bounds")
166 }
167
168 #[inline]
176 pub const fn try_hours(hours: i64) -> Option<TimeDelta> {
177 TimeDelta::try_seconds(try_opt!(hours.checked_mul(SECS_PER_HOUR)))
178 }
179
180 #[inline]
188 #[must_use]
189 #[track_caller]
190 pub const fn minutes(minutes: i64) -> TimeDelta {
191 expect(TimeDelta::try_minutes(minutes), "TimeDelta::minutes out of bounds")
192 }
193
194 #[inline]
202 pub const fn try_minutes(minutes: i64) -> Option<TimeDelta> {
203 TimeDelta::try_seconds(try_opt!(minutes.checked_mul(SECS_PER_MINUTE)))
204 }
205
206 #[inline]
213 #[must_use]
214 #[track_caller]
215 pub const fn seconds(seconds: i64) -> TimeDelta {
216 expect(TimeDelta::try_seconds(seconds), "TimeDelta::seconds out of bounds")
217 }
218
219 #[inline]
227 pub const fn try_seconds(seconds: i64) -> Option<TimeDelta> {
228 TimeDelta::new(seconds, 0)
229 }
230
231 #[inline]
238 #[track_caller]
239 pub const fn milliseconds(milliseconds: i64) -> TimeDelta {
240 expect(TimeDelta::try_milliseconds(milliseconds), "TimeDelta::milliseconds out of bounds")
241 }
242
243 #[inline]
250 pub const fn try_milliseconds(milliseconds: i64) -> Option<TimeDelta> {
251 if milliseconds < -i64::MAX {
254 return None;
255 }
256 let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
257 let d = TimeDelta { secs, nanos: millis as i32 * NANOS_PER_MILLI };
258 Some(d)
259 }
260
261 #[inline]
268 pub const fn microseconds(microseconds: i64) -> TimeDelta {
269 let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
270 let nanos = micros as i32 * NANOS_PER_MICRO;
271 TimeDelta { secs, nanos }
272 }
273
274 #[inline]
281 pub const fn nanoseconds(nanos: i64) -> TimeDelta {
282 let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
283 TimeDelta { secs, nanos: nanos as i32 }
284 }
285
286 #[inline]
288 pub const fn num_weeks(&self) -> i64 {
289 self.num_days() / 7
290 }
291
292 #[inline]
294 pub const fn num_days(&self) -> i64 {
295 self.num_seconds() / SECS_PER_DAY
296 }
297
298 #[inline]
300 pub const fn num_hours(&self) -> i64 {
301 self.num_seconds() / SECS_PER_HOUR
302 }
303
304 #[inline]
306 pub const fn num_minutes(&self) -> i64 {
307 self.num_seconds() / SECS_PER_MINUTE
308 }
309
310 pub const fn num_seconds(&self) -> i64 {
312 if self.secs < 0 && self.nanos > 0 { self.secs + 1 } else { self.secs }
314 }
315
316 pub fn as_seconds_f64(self) -> f64 {
318 self.secs as f64 + self.nanos as f64 / NANOS_PER_SEC as f64
319 }
320
321 pub fn as_seconds_f32(self) -> f32 {
323 self.secs as f32 + self.nanos as f32 / NANOS_PER_SEC as f32
324 }
325
326 pub const fn num_milliseconds(&self) -> i64 {
328 let secs_part = self.num_seconds() * MILLIS_PER_SEC;
332 let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
333 secs_part + nanos_part as i64
334 }
335
336 pub const fn subsec_millis(&self) -> i32 {
342 self.subsec_nanos() / NANOS_PER_MILLI
343 }
344
345 pub const fn num_microseconds(&self) -> Option<i64> {
348 let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
349 let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
350 secs_part.checked_add(nanos_part as i64)
351 }
352
353 pub const fn subsec_micros(&self) -> i32 {
359 self.subsec_nanos() / NANOS_PER_MICRO
360 }
361
362 pub const fn num_nanoseconds(&self) -> Option<i64> {
365 let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
366 let nanos_part = self.subsec_nanos();
367 secs_part.checked_add(nanos_part as i64)
368 }
369
370 pub const fn subsec_nanos(&self) -> i32 {
376 if self.secs < 0 && self.nanos > 0 { self.nanos - NANOS_PER_SEC } else { self.nanos }
377 }
378
379 #[must_use]
381 pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
382 let mut secs = self.secs + rhs.secs;
385 let mut nanos = self.nanos + rhs.nanos;
386 if nanos >= NANOS_PER_SEC {
387 nanos -= NANOS_PER_SEC;
388 secs += 1;
389 }
390 TimeDelta::new(secs, nanos as u32)
391 }
392
393 #[must_use]
395 pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
396 let mut secs = self.secs - rhs.secs;
399 let mut nanos = self.nanos - rhs.nanos;
400 if nanos < 0 {
401 nanos += NANOS_PER_SEC;
402 secs -= 1;
403 }
404 TimeDelta::new(secs, nanos as u32)
405 }
406
407 #[must_use]
409 pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
410 let total_nanos = self.nanos as i64 * rhs as i64;
412 let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
413 let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
415 if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
416 return None;
417 };
418 Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
419 }
420
421 #[must_use]
423 pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
424 if rhs == 0 {
425 return None;
426 }
427 let secs = self.secs / rhs as i64;
428 let carry = self.secs % rhs as i64;
429 let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
430 let nanos = self.nanos / rhs + extra_nanos as i32;
431
432 let (secs, nanos) = match nanos {
433 i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
434 NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
435 _ => (secs, nanos),
436 };
437
438 Some(TimeDelta { secs, nanos })
439 }
440
441 #[inline]
443 pub const fn abs(&self) -> TimeDelta {
444 if self.secs < 0 && self.nanos != 0 {
445 TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
446 } else {
447 TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
448 }
449 }
450
451 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
453 #[inline]
454 pub const fn min_value() -> TimeDelta {
455 MIN
456 }
457
458 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
460 #[inline]
461 pub const fn max_value() -> TimeDelta {
462 MAX
463 }
464
465 #[inline]
467 pub const fn zero() -> TimeDelta {
468 TimeDelta { secs: 0, nanos: 0 }
469 }
470
471 #[inline]
473 pub const fn is_zero(&self) -> bool {
474 self.secs == 0 && self.nanos == 0
475 }
476
477 pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
482 if duration.as_secs() > MAX.secs as u64 {
484 return Err(OutOfRangeError(()));
485 }
486 match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
487 Some(d) => Ok(d),
488 None => Err(OutOfRangeError(())),
489 }
490 }
491
492 pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
497 if self.secs < 0 {
498 return Err(OutOfRangeError(()));
499 }
500 Ok(Duration::new(self.secs as u64, self.nanos as u32))
501 }
502
503 pub(crate) const fn neg(self) -> TimeDelta {
505 let (secs_diff, nanos) = match self.nanos {
506 0 => (0, 0),
507 nanos => (1, NANOS_PER_SEC - nanos),
508 };
509 TimeDelta { secs: -self.secs - secs_diff, nanos }
510 }
511
512 pub const MIN: Self = MIN;
514
515 pub const MAX: Self = MAX;
517}
518
519impl Neg for TimeDelta {
520 type Output = TimeDelta;
521
522 #[inline]
523 #[track_caller]
524 fn neg(self) -> TimeDelta {
525 let (secs_diff, nanos) = match self.nanos {
526 0 => (0, 0),
527 nanos => (1, NANOS_PER_SEC - nanos),
528 };
529 TimeDelta { secs: -self.secs - secs_diff, nanos }
530 }
531}
532
533impl Add for TimeDelta {
534 type Output = TimeDelta;
535
536 #[track_caller]
537 fn add(self, rhs: TimeDelta) -> TimeDelta {
538 self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
539 }
540}
541
542impl Sub for TimeDelta {
543 type Output = TimeDelta;
544
545 #[track_caller]
546 fn sub(self, rhs: TimeDelta) -> TimeDelta {
547 self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
548 }
549}
550
551impl AddAssign for TimeDelta {
552 #[track_caller]
553 fn add_assign(&mut self, rhs: TimeDelta) {
554 let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
555 *self = new;
556 }
557}
558
559impl SubAssign for TimeDelta {
560 #[track_caller]
561 fn sub_assign(&mut self, rhs: TimeDelta) {
562 let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
563 *self = new;
564 }
565}
566
567impl Mul<i32> for TimeDelta {
568 type Output = TimeDelta;
569
570 #[track_caller]
571 fn mul(self, rhs: i32) -> TimeDelta {
572 self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
573 }
574}
575
576impl Div<i32> for TimeDelta {
577 type Output = TimeDelta;
578
579 #[track_caller]
580 fn div(self, rhs: i32) -> TimeDelta {
581 self.checked_div(rhs).expect("`i32` is zero")
582 }
583}
584
585impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
586 fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
587 iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
588 }
589}
590
591impl core::iter::Sum<TimeDelta> for TimeDelta {
592 fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
593 iter.fold(TimeDelta::zero(), |acc, x| acc + x)
594 }
595}
596
597impl fmt::Display for TimeDelta {
598 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
602 let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
605
606 write!(f, "{sign}P")?;
607 if abs.secs == 0 && abs.nanos == 0 {
609 return f.write_str("0D");
610 }
611
612 f.write_fmt(format_args!("T{}", abs.secs))?;
613
614 if abs.nanos > 0 {
615 let mut figures = 9usize;
617 let mut fraction_digits = abs.nanos;
618 loop {
619 let div = fraction_digits / 10;
620 let last_digit = fraction_digits % 10;
621 if last_digit != 0 {
622 break;
623 }
624 fraction_digits = div;
625 figures -= 1;
626 }
627 f.write_fmt(format_args!(".{fraction_digits:0figures$}"))?;
628 }
629 f.write_str("S")?;
630 Ok(())
631 }
632}
633
634#[derive(Debug, Clone, Copy, PartialEq, Eq)]
641#[cfg_attr(feature = "defmt", derive(defmt::Format))]
642pub struct OutOfRangeError(());
643
644impl fmt::Display for OutOfRangeError {
645 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
646 write!(f, "Source duration value is out of range for the target type")
647 }
648}
649
650#[cfg(any(feature = "std", feature = "core-error"))]
651impl Error for OutOfRangeError {
652 #[allow(deprecated)]
653 fn description(&self) -> &str {
654 "out of range error"
655 }
656}
657
658#[inline]
659const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
660 (this.div_euclid(other), this.rem_euclid(other))
661}
662
663#[cfg(all(feature = "arbitrary", feature = "std"))]
664impl arbitrary::Arbitrary<'_> for TimeDelta {
665 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
666 const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
667 const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
668
669 let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
670 let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
671 let duration = TimeDelta { secs, nanos };
672
673 if duration < MIN || duration > MAX {
674 Err(arbitrary::Error::IncorrectFormat)
675 } else {
676 Ok(duration)
677 }
678 }
679}
680
681#[cfg(feature = "serde")]
682mod serde {
683 use super::TimeDelta;
684 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
685
686 impl Serialize for TimeDelta {
687 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
688 <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
689 }
690 }
691
692 impl<'de> Deserialize<'de> for TimeDelta {
693 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
694 let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
695 TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
696 }
697 }
698
699 #[cfg(test)]
700 mod tests {
701 use super::{super::MAX, TimeDelta};
702
703 #[test]
704 fn test_serde() {
705 let duration = TimeDelta::new(123, 456).unwrap();
706 assert_eq!(
707 serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
708 .unwrap(),
709 duration
710 );
711 }
712
713 #[test]
714 #[should_panic(expected = "TimeDelta out of bounds")]
715 fn test_serde_oob_panic() {
716 let _ =
717 serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
718 }
719 }
720}
721
722#[cfg(test)]
723mod tests {
724 use super::OutOfRangeError;
725 use super::{MAX, MIN, TimeDelta};
726 use crate::expect;
727 use core::time::Duration;
728
729 #[test]
730 fn test_duration() {
731 let days = |d| TimeDelta::try_days(d).unwrap();
732 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
733
734 assert!(seconds(1) != TimeDelta::zero());
735 assert_eq!(seconds(1) + seconds(2), seconds(3));
736 assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
737 assert_eq!(days(10) - seconds(1000), seconds(863_000));
738 assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
739 assert_eq!(
740 days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
741 days(3) + TimeDelta::nanoseconds(234_567_890)
742 );
743 assert_eq!(-days(3), days(-3));
744 assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
745
746 let mut d = TimeDelta::default();
747 d += TimeDelta::try_minutes(1).unwrap();
748 d -= seconds(30);
749 assert_eq!(d, seconds(30));
750 }
751
752 #[test]
753 fn test_duration_num_days() {
754 assert_eq!(TimeDelta::zero().num_days(), 0);
755 assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
756 assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
757 assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
758 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().num_days(), 1);
759 assert_eq!(TimeDelta::try_seconds(-86_399).unwrap().num_days(), 0);
760 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().num_days(), -1);
761 assert_eq!(TimeDelta::try_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
762 assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
763 }
764
765 #[test]
766 fn test_duration_num_seconds() {
767 assert_eq!(TimeDelta::zero().num_seconds(), 0);
768 assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
769 assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
770 assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
771 assert_eq!(TimeDelta::try_milliseconds(1001).unwrap().num_seconds(), 1);
772 assert_eq!(TimeDelta::try_milliseconds(-999).unwrap().num_seconds(), 0);
773 assert_eq!(TimeDelta::try_milliseconds(-1001).unwrap().num_seconds(), -1);
774 }
775
776 #[test]
777 fn test_duration_seconds_max_allowed() {
778 let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
779 assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
780 assert_eq!(
781 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
782 i64::MAX as i128 / 1_000 * 1_000_000_000
783 );
784 }
785
786 #[test]
787 fn test_duration_seconds_max_overflow() {
788 assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
789 }
790
791 #[test]
792 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
793 fn test_duration_seconds_max_overflow_panic() {
794 let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
795 }
796
797 #[test]
798 fn test_duration_seconds_min_allowed() {
799 let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); assert_eq!(duration.num_seconds(), i64::MIN / 1_000); assert_eq!(
802 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
803 -i64::MAX as i128 / 1_000 * 1_000_000_000
804 );
805 }
806
807 #[test]
808 fn test_duration_seconds_min_underflow() {
809 assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
810 }
811
812 #[test]
813 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
814 fn test_duration_seconds_min_underflow_panic() {
815 let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
816 }
817
818 #[test]
819 fn test_duration_as_seconds_f64() {
820 assert_eq!(TimeDelta::seconds(1).as_seconds_f64(), 1.0);
821 assert_eq!(TimeDelta::seconds(-1).as_seconds_f64(), -1.0);
822 assert_eq!(TimeDelta::seconds(100).as_seconds_f64(), 100.0);
823 assert_eq!(TimeDelta::seconds(-100).as_seconds_f64(), -100.0);
824
825 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f64(), 0.5);
826 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f64(), -0.5);
827 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f64(), 1.5);
828 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f64(), -1.5);
829 }
830
831 #[test]
832 fn test_duration_as_seconds_f32() {
833 assert_eq!(TimeDelta::seconds(1).as_seconds_f32(), 1.0);
834 assert_eq!(TimeDelta::seconds(-1).as_seconds_f32(), -1.0);
835 assert_eq!(TimeDelta::seconds(100).as_seconds_f32(), 100.0);
836 assert_eq!(TimeDelta::seconds(-100).as_seconds_f32(), -100.0);
837
838 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f32(), 0.5);
839 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f32(), -0.5);
840 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f32(), 1.5);
841 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f32(), -1.5);
842 }
843
844 #[test]
845 fn test_duration_subsec_nanos() {
846 assert_eq!(TimeDelta::zero().subsec_nanos(), 0);
847 assert_eq!(TimeDelta::nanoseconds(1).subsec_nanos(), 1);
848 assert_eq!(TimeDelta::nanoseconds(-1).subsec_nanos(), -1);
849 assert_eq!(TimeDelta::seconds(1).subsec_nanos(), 0);
850 assert_eq!(TimeDelta::nanoseconds(1_000_000_001).subsec_nanos(), 1);
851 }
852
853 #[test]
854 fn test_duration_subsec_micros() {
855 assert_eq!(TimeDelta::zero().subsec_micros(), 0);
856 assert_eq!(TimeDelta::microseconds(1).subsec_micros(), 1);
857 assert_eq!(TimeDelta::microseconds(-1).subsec_micros(), -1);
858 assert_eq!(TimeDelta::seconds(1).subsec_micros(), 0);
859 assert_eq!(TimeDelta::microseconds(1_000_001).subsec_micros(), 1);
860 assert_eq!(TimeDelta::nanoseconds(1_000_001_999).subsec_micros(), 1);
861 }
862
863 #[test]
864 fn test_duration_subsec_millis() {
865 assert_eq!(TimeDelta::zero().subsec_millis(), 0);
866 assert_eq!(TimeDelta::milliseconds(1).subsec_millis(), 1);
867 assert_eq!(TimeDelta::milliseconds(-1).subsec_millis(), -1);
868 assert_eq!(TimeDelta::seconds(1).subsec_millis(), 0);
869 assert_eq!(TimeDelta::milliseconds(1_001).subsec_millis(), 1);
870 assert_eq!(TimeDelta::microseconds(1_001_999).subsec_millis(), 1);
871 }
872
873 #[test]
874 fn test_duration_num_milliseconds() {
875 assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
876 assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
877 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
878 assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
879 assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
880 assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
881 assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
882 }
883
884 #[test]
885 fn test_duration_milliseconds_max_allowed() {
886 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
889 assert_eq!(duration.num_milliseconds(), i64::MAX);
890 assert_eq!(
891 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
892 i64::MAX as i128 * 1_000_000
893 );
894 }
895
896 #[test]
897 fn test_duration_milliseconds_max_overflow() {
898 assert!(
901 TimeDelta::try_milliseconds(i64::MAX)
902 .unwrap()
903 .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
904 .is_none()
905 );
906 }
907
908 #[test]
909 fn test_duration_milliseconds_min_allowed() {
910 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
914 assert_eq!(duration.num_milliseconds(), -i64::MAX);
915 assert_eq!(
916 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
917 -i64::MAX as i128 * 1_000_000
918 );
919 }
920
921 #[test]
922 fn test_duration_milliseconds_min_underflow() {
923 assert!(
926 TimeDelta::try_milliseconds(-i64::MAX)
927 .unwrap()
928 .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
929 .is_none()
930 );
931 }
932
933 #[test]
934 #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
935 fn test_duration_milliseconds_min_underflow_panic() {
936 let _ = TimeDelta::milliseconds(i64::MIN); }
942
943 #[test]
944 fn test_duration_num_microseconds() {
945 assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
946 assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
947 assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
948 assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
949 assert_eq!(TimeDelta::nanoseconds(1001).num_microseconds(), Some(1));
950 assert_eq!(TimeDelta::nanoseconds(-999).num_microseconds(), Some(0));
951 assert_eq!(TimeDelta::nanoseconds(-1001).num_microseconds(), Some(-1));
952
953 const MICROS_PER_DAY: i64 = 86_400_000_000;
955 assert_eq!(
956 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
957 Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
958 );
959 assert_eq!(
960 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
961 Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
962 );
963 assert_eq!(
964 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
965 None
966 );
967 assert_eq!(
968 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
969 None
970 );
971 }
972 #[test]
973 fn test_duration_microseconds_max_allowed() {
974 let duration = TimeDelta::microseconds(i64::MAX);
978 assert_eq!(duration.num_microseconds(), Some(i64::MAX));
979 assert_eq!(
980 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
981 i64::MAX as i128 * 1_000
982 );
983 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
988 assert!(duration.num_microseconds().is_none());
989 assert_eq!(
990 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
991 i64::MAX as i128 * 1_000_000
992 );
993 }
994 #[test]
995 fn test_duration_microseconds_max_overflow() {
996 let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
999 assert!(duration.num_microseconds().is_none());
1000 assert_eq!(
1001 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1002 (i64::MAX as i128 + 1) * 1_000
1003 );
1004 assert!(
1007 TimeDelta::try_milliseconds(i64::MAX)
1008 .unwrap()
1009 .checked_add(&TimeDelta::microseconds(1))
1010 .is_none()
1011 );
1012 }
1013 #[test]
1014 fn test_duration_microseconds_min_allowed() {
1015 let duration = TimeDelta::microseconds(i64::MIN);
1019 assert_eq!(duration.num_microseconds(), Some(i64::MIN));
1020 assert_eq!(
1021 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1022 i64::MIN as i128 * 1_000
1023 );
1024 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1029 assert!(duration.num_microseconds().is_none());
1030 assert_eq!(
1031 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1032 -i64::MAX as i128 * 1_000_000
1033 );
1034 }
1035 #[test]
1036 fn test_duration_microseconds_min_underflow() {
1037 let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
1040 assert!(duration.num_microseconds().is_none());
1041 assert_eq!(
1042 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1043 (i64::MIN as i128 - 1) * 1_000
1044 );
1045 assert!(
1048 TimeDelta::try_milliseconds(-i64::MAX)
1049 .unwrap()
1050 .checked_sub(&TimeDelta::microseconds(1))
1051 .is_none()
1052 );
1053 }
1054
1055 #[test]
1056 fn test_duration_num_nanoseconds() {
1057 assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
1058 assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
1059 assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
1060
1061 const NANOS_PER_DAY: i64 = 86_400_000_000_000;
1063 assert_eq!(
1064 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1065 Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1066 );
1067 assert_eq!(
1068 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1069 Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1070 );
1071 assert_eq!(
1072 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
1073 None
1074 );
1075 assert_eq!(
1076 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
1077 None
1078 );
1079 }
1080 #[test]
1081 fn test_duration_nanoseconds_max_allowed() {
1082 let duration = TimeDelta::nanoseconds(i64::MAX);
1086 assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
1087 assert_eq!(
1088 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1089 i64::MAX as i128
1090 );
1091 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
1095 assert!(duration.num_nanoseconds().is_none());
1096 assert_eq!(
1097 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1098 i64::MAX as i128 * 1_000_000
1099 );
1100 }
1101
1102 #[test]
1103 fn test_duration_nanoseconds_max_overflow() {
1104 let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1107 assert!(duration.num_nanoseconds().is_none());
1108 assert_eq!(
1109 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1110 i64::MAX as i128 + 1
1111 );
1112 assert!(
1115 TimeDelta::try_milliseconds(i64::MAX)
1116 .unwrap()
1117 .checked_add(&TimeDelta::nanoseconds(1))
1118 .is_none()
1119 );
1120 }
1121
1122 #[test]
1123 fn test_duration_nanoseconds_min_allowed() {
1124 let duration = TimeDelta::nanoseconds(i64::MIN);
1128 assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1129 assert_eq!(
1130 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1131 i64::MIN as i128
1132 );
1133 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1137 assert!(duration.num_nanoseconds().is_none());
1138 assert_eq!(
1139 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1140 -i64::MAX as i128 * 1_000_000
1141 );
1142 }
1143
1144 #[test]
1145 fn test_duration_nanoseconds_min_underflow() {
1146 let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1149 assert!(duration.num_nanoseconds().is_none());
1150 assert_eq!(
1151 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1152 i64::MIN as i128 - 1
1153 );
1154 assert!(
1157 TimeDelta::try_milliseconds(-i64::MAX)
1158 .unwrap()
1159 .checked_sub(&TimeDelta::nanoseconds(1))
1160 .is_none()
1161 );
1162 }
1163
1164 #[test]
1165 fn test_max() {
1166 assert_eq!(
1167 MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1168 i64::MAX as i128 * 1_000_000
1169 );
1170 assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1171 assert_eq!(MAX.num_milliseconds(), i64::MAX);
1172 assert_eq!(MAX.num_microseconds(), None);
1173 assert_eq!(MAX.num_nanoseconds(), None);
1174 }
1175
1176 #[test]
1177 fn test_min() {
1178 assert_eq!(
1179 MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1180 -i64::MAX as i128 * 1_000_000
1181 );
1182 assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1183 assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1184 assert_eq!(MIN.num_microseconds(), None);
1185 assert_eq!(MIN.num_nanoseconds(), None);
1186 }
1187
1188 #[test]
1189 fn test_duration_ord() {
1190 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1191
1192 assert!(milliseconds(1) < milliseconds(2));
1193 assert!(milliseconds(2) > milliseconds(1));
1194 assert!(milliseconds(-1) > milliseconds(-2));
1195 assert!(milliseconds(-2) < milliseconds(-1));
1196 assert!(milliseconds(-1) < milliseconds(1));
1197 assert!(milliseconds(1) > milliseconds(-1));
1198 assert!(milliseconds(0) < milliseconds(1));
1199 assert!(milliseconds(0) > milliseconds(-1));
1200 assert!(milliseconds(1_001) < milliseconds(1_002));
1201 assert!(milliseconds(-1_001) > milliseconds(-1_002));
1202 assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1203 assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1204 assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1205 assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1206 }
1207
1208 #[test]
1209 fn test_duration_checked_ops() {
1210 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1211 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1212
1213 assert_eq!(
1214 milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1215 Some(milliseconds(i64::MAX))
1216 );
1217 assert_eq!(
1218 milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1219 Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1220 );
1221 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1222 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1223
1224 assert_eq!(
1225 milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1226 Some(milliseconds(-i64::MAX))
1227 );
1228 assert_eq!(
1229 milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1230 Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1231 );
1232 assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1233 assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1234
1235 assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1236 assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1237 assert!(seconds(1).checked_div(0).is_none());
1238 }
1239
1240 #[test]
1241 fn test_duration_abs() {
1242 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1243
1244 assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1245 assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1246 assert_eq!(milliseconds(300).abs(), milliseconds(300));
1247 assert_eq!(milliseconds(0).abs(), milliseconds(0));
1248 assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1249 assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1250 assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1251 assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1252 assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1253 assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1254 }
1255
1256 #[test]
1257 #[allow(clippy::erasing_op)]
1258 fn test_duration_mul() {
1259 assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1260 assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1261 assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1262 assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1263 assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1264 assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1265 assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1266 assert_eq!(
1267 TimeDelta::nanoseconds(30) * 333_333_333,
1268 TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1269 );
1270 assert_eq!(
1271 (TimeDelta::nanoseconds(1)
1272 + TimeDelta::try_seconds(1).unwrap()
1273 + TimeDelta::try_days(1).unwrap())
1274 * 3,
1275 TimeDelta::nanoseconds(3)
1276 + TimeDelta::try_seconds(3).unwrap()
1277 + TimeDelta::try_days(3).unwrap()
1278 );
1279 assert_eq!(
1280 TimeDelta::try_milliseconds(1500).unwrap() * -2,
1281 TimeDelta::try_seconds(-3).unwrap()
1282 );
1283 assert_eq!(
1284 TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1285 TimeDelta::try_seconds(-3).unwrap()
1286 );
1287 }
1288
1289 #[test]
1290 fn test_duration_div() {
1291 assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1292 assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1293 assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1294 assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
1295 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / -1, TimeDelta::nanoseconds(123_456_789));
1296 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / 1, -TimeDelta::nanoseconds(123_456_789));
1297 assert_eq!(TimeDelta::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1298 assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1299 assert_eq!(
1300 TimeDelta::try_seconds(-1).unwrap() / 2,
1301 TimeDelta::try_milliseconds(-500).unwrap()
1302 );
1303 assert_eq!(
1304 TimeDelta::try_seconds(1).unwrap() / -2,
1305 TimeDelta::try_milliseconds(-500).unwrap()
1306 );
1307 assert_eq!(
1308 TimeDelta::try_seconds(-1).unwrap() / -2,
1309 TimeDelta::try_milliseconds(500).unwrap()
1310 );
1311 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1312 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1313 }
1314
1315 #[test]
1316 fn test_duration_sum() {
1317 let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1318 let sum_1: TimeDelta = duration_list_1.iter().sum();
1319 assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1320
1321 let duration_list_2 = [
1322 TimeDelta::zero(),
1323 TimeDelta::try_seconds(1).unwrap(),
1324 TimeDelta::try_seconds(6).unwrap(),
1325 TimeDelta::try_seconds(10).unwrap(),
1326 ];
1327 let sum_2: TimeDelta = duration_list_2.iter().sum();
1328 assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1329
1330 let duration_arr = [
1331 TimeDelta::zero(),
1332 TimeDelta::try_seconds(1).unwrap(),
1333 TimeDelta::try_seconds(6).unwrap(),
1334 TimeDelta::try_seconds(10).unwrap(),
1335 ];
1336 let sum_3: TimeDelta = duration_arr.into_iter().sum();
1337 assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1338 }
1339
1340 #[test]
1341 fn test_duration_fmt() {
1342 assert_eq!(TimeDelta::zero().to_string(), "P0D");
1343 assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1344 assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1345 assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1346 assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1347 assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1348 assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1349 assert_eq!(
1350 (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1351 .to_string(),
1352 "PT604806.543S"
1353 );
1354 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1355 assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1356
1357 assert_eq!(
1359 format!(
1360 "{:30}",
1361 TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1362 ),
1363 "PT86402.345S"
1364 );
1365 }
1366
1367 #[test]
1368 fn test_to_std() {
1369 assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1370 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1371 assert_eq!(
1372 TimeDelta::try_milliseconds(123).unwrap().to_std(),
1373 Ok(Duration::new(0, 123_000_000))
1374 );
1375 assert_eq!(
1376 TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1377 Ok(Duration::new(123, 765_000_000))
1378 );
1379 assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1380 assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1381 assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1382 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1383 }
1384
1385 #[test]
1386 fn test_from_std() {
1387 assert_eq!(
1388 Ok(TimeDelta::try_seconds(1).unwrap()),
1389 TimeDelta::from_std(Duration::new(1, 0))
1390 );
1391 assert_eq!(
1392 Ok(TimeDelta::try_seconds(86_401).unwrap()),
1393 TimeDelta::from_std(Duration::new(86_401, 0))
1394 );
1395 assert_eq!(
1396 Ok(TimeDelta::try_milliseconds(123).unwrap()),
1397 TimeDelta::from_std(Duration::new(0, 123_000_000))
1398 );
1399 assert_eq!(
1400 Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1401 TimeDelta::from_std(Duration::new(123, 765_000_000))
1402 );
1403 assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1404 assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1405 assert_eq!(
1406 TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1407 Err(OutOfRangeError(()))
1408 );
1409 assert_eq!(
1410 TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1411 Err(OutOfRangeError(()))
1412 );
1413 }
1414
1415 #[test]
1416 fn test_duration_const() {
1417 const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1418 const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1419 const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1420 const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1421 const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1422 const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1423 const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1424 const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1425 let combo: TimeDelta = ONE_WEEK
1426 + ONE_DAY
1427 + ONE_HOUR
1428 + ONE_MINUTE
1429 + ONE_SECOND
1430 + ONE_MILLI
1431 + ONE_MICRO
1432 + ONE_NANO;
1433
1434 assert!(ONE_WEEK != TimeDelta::zero());
1435 assert!(ONE_DAY != TimeDelta::zero());
1436 assert!(ONE_HOUR != TimeDelta::zero());
1437 assert!(ONE_MINUTE != TimeDelta::zero());
1438 assert!(ONE_SECOND != TimeDelta::zero());
1439 assert!(ONE_MILLI != TimeDelta::zero());
1440 assert!(ONE_MICRO != TimeDelta::zero());
1441 assert!(ONE_NANO != TimeDelta::zero());
1442 assert_eq!(
1443 combo,
1444 TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1445 + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1446 );
1447 }
1448
1449 #[test]
1450 #[cfg(feature = "rkyv-validation")]
1451 fn test_rkyv_validation() {
1452 let duration = TimeDelta::try_seconds(1).unwrap();
1453 let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1454 assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1455 }
1456}