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))]
62pub struct TimeDelta {
63 secs: i64,
64 nanos: i32, }
66
67pub(crate) const MIN: TimeDelta = TimeDelta {
69 secs: -i64::MAX / MILLIS_PER_SEC - 1,
70 nanos: NANOS_PER_SEC + (-i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
71};
72
73pub(crate) const MAX: TimeDelta = TimeDelta {
75 secs: i64::MAX / MILLIS_PER_SEC,
76 nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI,
77};
78
79impl TimeDelta {
80 pub const fn new(secs: i64, nanos: u32) -> Option<TimeDelta> {
86 if secs < MIN.secs
87 || secs > MAX.secs
88 || nanos >= 1_000_000_000
89 || (secs == MAX.secs && nanos > MAX.nanos as u32)
90 || (secs == MIN.secs && nanos < MIN.nanos as u32)
91 {
92 return None;
93 }
94 Some(TimeDelta { secs, nanos: nanos as i32 })
95 }
96
97 #[inline]
106 #[must_use]
107 pub const fn weeks(weeks: i64) -> TimeDelta {
108 expect(TimeDelta::try_weeks(weeks), "TimeDelta::weeks out of bounds")
109 }
110
111 #[inline]
120 pub const fn try_weeks(weeks: i64) -> Option<TimeDelta> {
121 TimeDelta::try_seconds(try_opt!(weeks.checked_mul(SECS_PER_WEEK)))
122 }
123
124 #[inline]
133 #[must_use]
134 pub const fn days(days: i64) -> TimeDelta {
135 expect(TimeDelta::try_days(days), "TimeDelta::days out of bounds")
136 }
137
138 #[inline]
147 pub const fn try_days(days: i64) -> Option<TimeDelta> {
148 TimeDelta::try_seconds(try_opt!(days.checked_mul(SECS_PER_DAY)))
149 }
150
151 #[inline]
159 #[must_use]
160 pub const fn hours(hours: i64) -> TimeDelta {
161 expect(TimeDelta::try_hours(hours), "TimeDelta::hours out of bounds")
162 }
163
164 #[inline]
172 pub const fn try_hours(hours: i64) -> Option<TimeDelta> {
173 TimeDelta::try_seconds(try_opt!(hours.checked_mul(SECS_PER_HOUR)))
174 }
175
176 #[inline]
184 #[must_use]
185 pub const fn minutes(minutes: i64) -> TimeDelta {
186 expect(TimeDelta::try_minutes(minutes), "TimeDelta::minutes out of bounds")
187 }
188
189 #[inline]
197 pub const fn try_minutes(minutes: i64) -> Option<TimeDelta> {
198 TimeDelta::try_seconds(try_opt!(minutes.checked_mul(SECS_PER_MINUTE)))
199 }
200
201 #[inline]
208 #[must_use]
209 pub const fn seconds(seconds: i64) -> TimeDelta {
210 expect(TimeDelta::try_seconds(seconds), "TimeDelta::seconds out of bounds")
211 }
212
213 #[inline]
221 pub const fn try_seconds(seconds: i64) -> Option<TimeDelta> {
222 TimeDelta::new(seconds, 0)
223 }
224
225 #[inline]
232 pub const fn milliseconds(milliseconds: i64) -> TimeDelta {
233 expect(TimeDelta::try_milliseconds(milliseconds), "TimeDelta::milliseconds out of bounds")
234 }
235
236 #[inline]
243 pub const fn try_milliseconds(milliseconds: i64) -> Option<TimeDelta> {
244 if milliseconds < -i64::MAX {
247 return None;
248 }
249 let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
250 let d = TimeDelta { secs, nanos: millis as i32 * NANOS_PER_MILLI };
251 Some(d)
252 }
253
254 #[inline]
261 pub const fn microseconds(microseconds: i64) -> TimeDelta {
262 let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
263 let nanos = micros as i32 * NANOS_PER_MICRO;
264 TimeDelta { secs, nanos }
265 }
266
267 #[inline]
274 pub const fn nanoseconds(nanos: i64) -> TimeDelta {
275 let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
276 TimeDelta { secs, nanos: nanos as i32 }
277 }
278
279 #[inline]
281 pub const fn num_weeks(&self) -> i64 {
282 self.num_days() / 7
283 }
284
285 #[inline]
287 pub const fn num_days(&self) -> i64 {
288 self.num_seconds() / SECS_PER_DAY
289 }
290
291 #[inline]
293 pub const fn num_hours(&self) -> i64 {
294 self.num_seconds() / SECS_PER_HOUR
295 }
296
297 #[inline]
299 pub const fn num_minutes(&self) -> i64 {
300 self.num_seconds() / SECS_PER_MINUTE
301 }
302
303 pub const fn num_seconds(&self) -> i64 {
305 if self.secs < 0 && self.nanos > 0 { self.secs + 1 } else { self.secs }
307 }
308
309 pub fn as_seconds_f64(self) -> f64 {
311 self.secs as f64 + self.nanos as f64 / NANOS_PER_SEC as f64
312 }
313
314 pub fn as_seconds_f32(self) -> f32 {
316 self.secs as f32 + self.nanos as f32 / NANOS_PER_SEC as f32
317 }
318
319 pub const fn num_milliseconds(&self) -> i64 {
321 let secs_part = self.num_seconds() * MILLIS_PER_SEC;
325 let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
326 secs_part + nanos_part as i64
327 }
328
329 pub const fn subsec_millis(&self) -> i32 {
335 self.subsec_nanos() / NANOS_PER_MILLI
336 }
337
338 pub const fn num_microseconds(&self) -> Option<i64> {
341 let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
342 let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
343 secs_part.checked_add(nanos_part as i64)
344 }
345
346 pub const fn subsec_micros(&self) -> i32 {
352 self.subsec_nanos() / NANOS_PER_MICRO
353 }
354
355 pub const fn num_nanoseconds(&self) -> Option<i64> {
358 let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
359 let nanos_part = self.subsec_nanos();
360 secs_part.checked_add(nanos_part as i64)
361 }
362
363 pub const fn subsec_nanos(&self) -> i32 {
369 if self.secs < 0 && self.nanos > 0 { self.nanos - NANOS_PER_SEC } else { self.nanos }
370 }
371
372 #[must_use]
374 pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
375 let mut secs = self.secs + rhs.secs;
378 let mut nanos = self.nanos + rhs.nanos;
379 if nanos >= NANOS_PER_SEC {
380 nanos -= NANOS_PER_SEC;
381 secs += 1;
382 }
383 TimeDelta::new(secs, nanos as u32)
384 }
385
386 #[must_use]
388 pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
389 let mut secs = self.secs - rhs.secs;
392 let mut nanos = self.nanos - rhs.nanos;
393 if nanos < 0 {
394 nanos += NANOS_PER_SEC;
395 secs -= 1;
396 }
397 TimeDelta::new(secs, nanos as u32)
398 }
399
400 #[must_use]
402 pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
403 let total_nanos = self.nanos as i64 * rhs as i64;
405 let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
406 let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
408 if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
409 return None;
410 };
411 Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
412 }
413
414 #[must_use]
416 pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
417 if rhs == 0 {
418 return None;
419 }
420 let secs = self.secs / rhs as i64;
421 let carry = self.secs % rhs as i64;
422 let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
423 let nanos = self.nanos / rhs + extra_nanos as i32;
424
425 let (secs, nanos) = match nanos {
426 i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
427 NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
428 _ => (secs, nanos),
429 };
430
431 Some(TimeDelta { secs, nanos })
432 }
433
434 #[inline]
436 pub const fn abs(&self) -> TimeDelta {
437 if self.secs < 0 && self.nanos != 0 {
438 TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
439 } else {
440 TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
441 }
442 }
443
444 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
446 #[inline]
447 pub const fn min_value() -> TimeDelta {
448 MIN
449 }
450
451 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
453 #[inline]
454 pub const fn max_value() -> TimeDelta {
455 MAX
456 }
457
458 #[inline]
460 pub const fn zero() -> TimeDelta {
461 TimeDelta { secs: 0, nanos: 0 }
462 }
463
464 #[inline]
466 pub const fn is_zero(&self) -> bool {
467 self.secs == 0 && self.nanos == 0
468 }
469
470 pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
475 if duration.as_secs() > MAX.secs as u64 {
477 return Err(OutOfRangeError(()));
478 }
479 match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
480 Some(d) => Ok(d),
481 None => Err(OutOfRangeError(())),
482 }
483 }
484
485 pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
490 if self.secs < 0 {
491 return Err(OutOfRangeError(()));
492 }
493 Ok(Duration::new(self.secs as u64, self.nanos as u32))
494 }
495
496 pub(crate) const fn neg(self) -> TimeDelta {
498 let (secs_diff, nanos) = match self.nanos {
499 0 => (0, 0),
500 nanos => (1, NANOS_PER_SEC - nanos),
501 };
502 TimeDelta { secs: -self.secs - secs_diff, nanos }
503 }
504
505 pub const MIN: Self = MIN;
507
508 pub const MAX: Self = MAX;
510}
511
512impl Neg for TimeDelta {
513 type Output = TimeDelta;
514
515 #[inline]
516 fn neg(self) -> TimeDelta {
517 let (secs_diff, nanos) = match self.nanos {
518 0 => (0, 0),
519 nanos => (1, NANOS_PER_SEC - nanos),
520 };
521 TimeDelta { secs: -self.secs - secs_diff, nanos }
522 }
523}
524
525impl Add for TimeDelta {
526 type Output = TimeDelta;
527
528 fn add(self, rhs: TimeDelta) -> TimeDelta {
529 self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
530 }
531}
532
533impl Sub for TimeDelta {
534 type Output = TimeDelta;
535
536 fn sub(self, rhs: TimeDelta) -> TimeDelta {
537 self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
538 }
539}
540
541impl AddAssign for TimeDelta {
542 fn add_assign(&mut self, rhs: TimeDelta) {
543 let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
544 *self = new;
545 }
546}
547
548impl SubAssign for TimeDelta {
549 fn sub_assign(&mut self, rhs: TimeDelta) {
550 let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
551 *self = new;
552 }
553}
554
555impl Mul<i32> for TimeDelta {
556 type Output = TimeDelta;
557
558 fn mul(self, rhs: i32) -> TimeDelta {
559 self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
560 }
561}
562
563impl Div<i32> for TimeDelta {
564 type Output = TimeDelta;
565
566 fn div(self, rhs: i32) -> TimeDelta {
567 self.checked_div(rhs).expect("`i32` is zero")
568 }
569}
570
571impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
572 fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
573 iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
574 }
575}
576
577impl core::iter::Sum<TimeDelta> for TimeDelta {
578 fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
579 iter.fold(TimeDelta::zero(), |acc, x| acc + x)
580 }
581}
582
583impl fmt::Display for TimeDelta {
584 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
588 let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
591
592 write!(f, "{sign}P")?;
593 if abs.secs == 0 && abs.nanos == 0 {
595 return f.write_str("0D");
596 }
597
598 f.write_fmt(format_args!("T{}", abs.secs))?;
599
600 if abs.nanos > 0 {
601 let mut figures = 9usize;
603 let mut fraction_digits = abs.nanos;
604 loop {
605 let div = fraction_digits / 10;
606 let last_digit = fraction_digits % 10;
607 if last_digit != 0 {
608 break;
609 }
610 fraction_digits = div;
611 figures -= 1;
612 }
613 f.write_fmt(format_args!(".{fraction_digits:0figures$}"))?;
614 }
615 f.write_str("S")?;
616 Ok(())
617 }
618}
619
620#[derive(Debug, Clone, Copy, PartialEq, Eq)]
627pub struct OutOfRangeError(());
628
629impl fmt::Display for OutOfRangeError {
630 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631 write!(f, "Source duration value is out of range for the target type")
632 }
633}
634
635#[cfg(any(feature = "std", feature = "core-error"))]
636impl Error for OutOfRangeError {
637 #[allow(deprecated)]
638 fn description(&self) -> &str {
639 "out of range error"
640 }
641}
642
643#[inline]
644const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
645 (this.div_euclid(other), this.rem_euclid(other))
646}
647
648#[cfg(all(feature = "arbitrary", feature = "std"))]
649impl arbitrary::Arbitrary<'_> for TimeDelta {
650 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
651 const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
652 const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
653
654 let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
655 let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
656 let duration = TimeDelta { secs, nanos };
657
658 if duration < MIN || duration > MAX {
659 Err(arbitrary::Error::IncorrectFormat)
660 } else {
661 Ok(duration)
662 }
663 }
664}
665
666#[cfg(feature = "serde")]
667mod serde {
668 use super::TimeDelta;
669 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
670
671 impl Serialize for TimeDelta {
672 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
673 <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
674 }
675 }
676
677 impl<'de> Deserialize<'de> for TimeDelta {
678 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
679 let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
680 TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
681 }
682 }
683
684 #[cfg(test)]
685 mod tests {
686 use super::{super::MAX, TimeDelta};
687
688 #[test]
689 fn test_serde() {
690 let duration = TimeDelta::new(123, 456).unwrap();
691 assert_eq!(
692 serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
693 .unwrap(),
694 duration
695 );
696 }
697
698 #[test]
699 #[should_panic(expected = "TimeDelta out of bounds")]
700 fn test_serde_oob_panic() {
701 let _ =
702 serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
703 }
704 }
705}
706
707#[cfg(test)]
708mod tests {
709 use super::OutOfRangeError;
710 use super::{MAX, MIN, TimeDelta};
711 use crate::expect;
712 use core::time::Duration;
713
714 #[test]
715 fn test_duration() {
716 let days = |d| TimeDelta::try_days(d).unwrap();
717 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
718
719 assert!(seconds(1) != TimeDelta::zero());
720 assert_eq!(seconds(1) + seconds(2), seconds(3));
721 assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
722 assert_eq!(days(10) - seconds(1000), seconds(863_000));
723 assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
724 assert_eq!(
725 days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
726 days(3) + TimeDelta::nanoseconds(234_567_890)
727 );
728 assert_eq!(-days(3), days(-3));
729 assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
730
731 let mut d = TimeDelta::default();
732 d += TimeDelta::try_minutes(1).unwrap();
733 d -= seconds(30);
734 assert_eq!(d, seconds(30));
735 }
736
737 #[test]
738 fn test_duration_num_days() {
739 assert_eq!(TimeDelta::zero().num_days(), 0);
740 assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
741 assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
742 assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
743 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().num_days(), 1);
744 assert_eq!(TimeDelta::try_seconds(-86_399).unwrap().num_days(), 0);
745 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().num_days(), -1);
746 assert_eq!(TimeDelta::try_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
747 assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
748 }
749
750 #[test]
751 fn test_duration_num_seconds() {
752 assert_eq!(TimeDelta::zero().num_seconds(), 0);
753 assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
754 assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
755 assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
756 assert_eq!(TimeDelta::try_milliseconds(1001).unwrap().num_seconds(), 1);
757 assert_eq!(TimeDelta::try_milliseconds(-999).unwrap().num_seconds(), 0);
758 assert_eq!(TimeDelta::try_milliseconds(-1001).unwrap().num_seconds(), -1);
759 }
760
761 #[test]
762 fn test_duration_seconds_max_allowed() {
763 let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
764 assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
765 assert_eq!(
766 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
767 i64::MAX as i128 / 1_000 * 1_000_000_000
768 );
769 }
770
771 #[test]
772 fn test_duration_seconds_max_overflow() {
773 assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
774 }
775
776 #[test]
777 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
778 fn test_duration_seconds_max_overflow_panic() {
779 let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
780 }
781
782 #[test]
783 fn test_duration_seconds_min_allowed() {
784 let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); assert_eq!(duration.num_seconds(), i64::MIN / 1_000); assert_eq!(
787 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
788 -i64::MAX as i128 / 1_000 * 1_000_000_000
789 );
790 }
791
792 #[test]
793 fn test_duration_seconds_min_underflow() {
794 assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
795 }
796
797 #[test]
798 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
799 fn test_duration_seconds_min_underflow_panic() {
800 let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
801 }
802
803 #[test]
804 fn test_duration_as_seconds_f64() {
805 assert_eq!(TimeDelta::seconds(1).as_seconds_f64(), 1.0);
806 assert_eq!(TimeDelta::seconds(-1).as_seconds_f64(), -1.0);
807 assert_eq!(TimeDelta::seconds(100).as_seconds_f64(), 100.0);
808 assert_eq!(TimeDelta::seconds(-100).as_seconds_f64(), -100.0);
809
810 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f64(), 0.5);
811 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f64(), -0.5);
812 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f64(), 1.5);
813 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f64(), -1.5);
814 }
815
816 #[test]
817 fn test_duration_as_seconds_f32() {
818 assert_eq!(TimeDelta::seconds(1).as_seconds_f32(), 1.0);
819 assert_eq!(TimeDelta::seconds(-1).as_seconds_f32(), -1.0);
820 assert_eq!(TimeDelta::seconds(100).as_seconds_f32(), 100.0);
821 assert_eq!(TimeDelta::seconds(-100).as_seconds_f32(), -100.0);
822
823 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f32(), 0.5);
824 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f32(), -0.5);
825 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f32(), 1.5);
826 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f32(), -1.5);
827 }
828
829 #[test]
830 fn test_duration_subsec_nanos() {
831 assert_eq!(TimeDelta::zero().subsec_nanos(), 0);
832 assert_eq!(TimeDelta::nanoseconds(1).subsec_nanos(), 1);
833 assert_eq!(TimeDelta::nanoseconds(-1).subsec_nanos(), -1);
834 assert_eq!(TimeDelta::seconds(1).subsec_nanos(), 0);
835 assert_eq!(TimeDelta::nanoseconds(1_000_000_001).subsec_nanos(), 1);
836 }
837
838 #[test]
839 fn test_duration_subsec_micros() {
840 assert_eq!(TimeDelta::zero().subsec_micros(), 0);
841 assert_eq!(TimeDelta::microseconds(1).subsec_micros(), 1);
842 assert_eq!(TimeDelta::microseconds(-1).subsec_micros(), -1);
843 assert_eq!(TimeDelta::seconds(1).subsec_micros(), 0);
844 assert_eq!(TimeDelta::microseconds(1_000_001).subsec_micros(), 1);
845 assert_eq!(TimeDelta::nanoseconds(1_000_001_999).subsec_micros(), 1);
846 }
847
848 #[test]
849 fn test_duration_subsec_millis() {
850 assert_eq!(TimeDelta::zero().subsec_millis(), 0);
851 assert_eq!(TimeDelta::milliseconds(1).subsec_millis(), 1);
852 assert_eq!(TimeDelta::milliseconds(-1).subsec_millis(), -1);
853 assert_eq!(TimeDelta::seconds(1).subsec_millis(), 0);
854 assert_eq!(TimeDelta::milliseconds(1_001).subsec_millis(), 1);
855 assert_eq!(TimeDelta::microseconds(1_001_999).subsec_millis(), 1);
856 }
857
858 #[test]
859 fn test_duration_num_milliseconds() {
860 assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
861 assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
862 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
863 assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
864 assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
865 assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
866 assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
867 }
868
869 #[test]
870 fn test_duration_milliseconds_max_allowed() {
871 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
874 assert_eq!(duration.num_milliseconds(), i64::MAX);
875 assert_eq!(
876 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
877 i64::MAX as i128 * 1_000_000
878 );
879 }
880
881 #[test]
882 fn test_duration_milliseconds_max_overflow() {
883 assert!(
886 TimeDelta::try_milliseconds(i64::MAX)
887 .unwrap()
888 .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
889 .is_none()
890 );
891 }
892
893 #[test]
894 fn test_duration_milliseconds_min_allowed() {
895 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
899 assert_eq!(duration.num_milliseconds(), -i64::MAX);
900 assert_eq!(
901 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
902 -i64::MAX as i128 * 1_000_000
903 );
904 }
905
906 #[test]
907 fn test_duration_milliseconds_min_underflow() {
908 assert!(
911 TimeDelta::try_milliseconds(-i64::MAX)
912 .unwrap()
913 .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
914 .is_none()
915 );
916 }
917
918 #[test]
919 #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
920 fn test_duration_milliseconds_min_underflow_panic() {
921 let _ = TimeDelta::milliseconds(i64::MIN); }
927
928 #[test]
929 fn test_duration_num_microseconds() {
930 assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
931 assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
932 assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
933 assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
934 assert_eq!(TimeDelta::nanoseconds(1001).num_microseconds(), Some(1));
935 assert_eq!(TimeDelta::nanoseconds(-999).num_microseconds(), Some(0));
936 assert_eq!(TimeDelta::nanoseconds(-1001).num_microseconds(), Some(-1));
937
938 const MICROS_PER_DAY: i64 = 86_400_000_000;
940 assert_eq!(
941 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
942 Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
943 );
944 assert_eq!(
945 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
946 Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
947 );
948 assert_eq!(
949 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
950 None
951 );
952 assert_eq!(
953 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
954 None
955 );
956 }
957 #[test]
958 fn test_duration_microseconds_max_allowed() {
959 let duration = TimeDelta::microseconds(i64::MAX);
963 assert_eq!(duration.num_microseconds(), Some(i64::MAX));
964 assert_eq!(
965 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
966 i64::MAX as i128 * 1_000
967 );
968 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
973 assert!(duration.num_microseconds().is_none());
974 assert_eq!(
975 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
976 i64::MAX as i128 * 1_000_000
977 );
978 }
979 #[test]
980 fn test_duration_microseconds_max_overflow() {
981 let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
984 assert!(duration.num_microseconds().is_none());
985 assert_eq!(
986 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
987 (i64::MAX as i128 + 1) * 1_000
988 );
989 assert!(
992 TimeDelta::try_milliseconds(i64::MAX)
993 .unwrap()
994 .checked_add(&TimeDelta::microseconds(1))
995 .is_none()
996 );
997 }
998 #[test]
999 fn test_duration_microseconds_min_allowed() {
1000 let duration = TimeDelta::microseconds(i64::MIN);
1004 assert_eq!(duration.num_microseconds(), Some(i64::MIN));
1005 assert_eq!(
1006 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1007 i64::MIN as i128 * 1_000
1008 );
1009 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1014 assert!(duration.num_microseconds().is_none());
1015 assert_eq!(
1016 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1017 -i64::MAX as i128 * 1_000_000
1018 );
1019 }
1020 #[test]
1021 fn test_duration_microseconds_min_underflow() {
1022 let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
1025 assert!(duration.num_microseconds().is_none());
1026 assert_eq!(
1027 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1028 (i64::MIN as i128 - 1) * 1_000
1029 );
1030 assert!(
1033 TimeDelta::try_milliseconds(-i64::MAX)
1034 .unwrap()
1035 .checked_sub(&TimeDelta::microseconds(1))
1036 .is_none()
1037 );
1038 }
1039
1040 #[test]
1041 fn test_duration_num_nanoseconds() {
1042 assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
1043 assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
1044 assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
1045
1046 const NANOS_PER_DAY: i64 = 86_400_000_000_000;
1048 assert_eq!(
1049 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1050 Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1051 );
1052 assert_eq!(
1053 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1054 Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1055 );
1056 assert_eq!(
1057 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
1058 None
1059 );
1060 assert_eq!(
1061 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
1062 None
1063 );
1064 }
1065 #[test]
1066 fn test_duration_nanoseconds_max_allowed() {
1067 let duration = TimeDelta::nanoseconds(i64::MAX);
1071 assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
1072 assert_eq!(
1073 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1074 i64::MAX as i128
1075 );
1076 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
1080 assert!(duration.num_nanoseconds().is_none());
1081 assert_eq!(
1082 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1083 i64::MAX as i128 * 1_000_000
1084 );
1085 }
1086
1087 #[test]
1088 fn test_duration_nanoseconds_max_overflow() {
1089 let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1092 assert!(duration.num_nanoseconds().is_none());
1093 assert_eq!(
1094 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1095 i64::MAX as i128 + 1
1096 );
1097 assert!(
1100 TimeDelta::try_milliseconds(i64::MAX)
1101 .unwrap()
1102 .checked_add(&TimeDelta::nanoseconds(1))
1103 .is_none()
1104 );
1105 }
1106
1107 #[test]
1108 fn test_duration_nanoseconds_min_allowed() {
1109 let duration = TimeDelta::nanoseconds(i64::MIN);
1113 assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1114 assert_eq!(
1115 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1116 i64::MIN as i128
1117 );
1118 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1122 assert!(duration.num_nanoseconds().is_none());
1123 assert_eq!(
1124 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1125 -i64::MAX as i128 * 1_000_000
1126 );
1127 }
1128
1129 #[test]
1130 fn test_duration_nanoseconds_min_underflow() {
1131 let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1134 assert!(duration.num_nanoseconds().is_none());
1135 assert_eq!(
1136 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1137 i64::MIN as i128 - 1
1138 );
1139 assert!(
1142 TimeDelta::try_milliseconds(-i64::MAX)
1143 .unwrap()
1144 .checked_sub(&TimeDelta::nanoseconds(1))
1145 .is_none()
1146 );
1147 }
1148
1149 #[test]
1150 fn test_max() {
1151 assert_eq!(
1152 MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1153 i64::MAX as i128 * 1_000_000
1154 );
1155 assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1156 assert_eq!(MAX.num_milliseconds(), i64::MAX);
1157 assert_eq!(MAX.num_microseconds(), None);
1158 assert_eq!(MAX.num_nanoseconds(), None);
1159 }
1160
1161 #[test]
1162 fn test_min() {
1163 assert_eq!(
1164 MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1165 -i64::MAX as i128 * 1_000_000
1166 );
1167 assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1168 assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1169 assert_eq!(MIN.num_microseconds(), None);
1170 assert_eq!(MIN.num_nanoseconds(), None);
1171 }
1172
1173 #[test]
1174 fn test_duration_ord() {
1175 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1176
1177 assert!(milliseconds(1) < milliseconds(2));
1178 assert!(milliseconds(2) > milliseconds(1));
1179 assert!(milliseconds(-1) > milliseconds(-2));
1180 assert!(milliseconds(-2) < milliseconds(-1));
1181 assert!(milliseconds(-1) < milliseconds(1));
1182 assert!(milliseconds(1) > milliseconds(-1));
1183 assert!(milliseconds(0) < milliseconds(1));
1184 assert!(milliseconds(0) > milliseconds(-1));
1185 assert!(milliseconds(1_001) < milliseconds(1_002));
1186 assert!(milliseconds(-1_001) > milliseconds(-1_002));
1187 assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1188 assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1189 assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1190 assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1191 }
1192
1193 #[test]
1194 fn test_duration_checked_ops() {
1195 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1196 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1197
1198 assert_eq!(
1199 milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1200 Some(milliseconds(i64::MAX))
1201 );
1202 assert_eq!(
1203 milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1204 Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1205 );
1206 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1207 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1208
1209 assert_eq!(
1210 milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1211 Some(milliseconds(-i64::MAX))
1212 );
1213 assert_eq!(
1214 milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1215 Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1216 );
1217 assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1218 assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1219
1220 assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1221 assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1222 assert!(seconds(1).checked_div(0).is_none());
1223 }
1224
1225 #[test]
1226 fn test_duration_abs() {
1227 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1228
1229 assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1230 assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1231 assert_eq!(milliseconds(300).abs(), milliseconds(300));
1232 assert_eq!(milliseconds(0).abs(), milliseconds(0));
1233 assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1234 assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1235 assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1236 assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1237 assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1238 assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1239 }
1240
1241 #[test]
1242 #[allow(clippy::erasing_op)]
1243 fn test_duration_mul() {
1244 assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1245 assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1246 assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1247 assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1248 assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1249 assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1250 assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1251 assert_eq!(
1252 TimeDelta::nanoseconds(30) * 333_333_333,
1253 TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1254 );
1255 assert_eq!(
1256 (TimeDelta::nanoseconds(1)
1257 + TimeDelta::try_seconds(1).unwrap()
1258 + TimeDelta::try_days(1).unwrap())
1259 * 3,
1260 TimeDelta::nanoseconds(3)
1261 + TimeDelta::try_seconds(3).unwrap()
1262 + TimeDelta::try_days(3).unwrap()
1263 );
1264 assert_eq!(
1265 TimeDelta::try_milliseconds(1500).unwrap() * -2,
1266 TimeDelta::try_seconds(-3).unwrap()
1267 );
1268 assert_eq!(
1269 TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1270 TimeDelta::try_seconds(-3).unwrap()
1271 );
1272 }
1273
1274 #[test]
1275 fn test_duration_div() {
1276 assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1277 assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1278 assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1279 assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
1280 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / -1, TimeDelta::nanoseconds(123_456_789));
1281 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / 1, -TimeDelta::nanoseconds(123_456_789));
1282 assert_eq!(TimeDelta::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1283 assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1284 assert_eq!(
1285 TimeDelta::try_seconds(-1).unwrap() / 2,
1286 TimeDelta::try_milliseconds(-500).unwrap()
1287 );
1288 assert_eq!(
1289 TimeDelta::try_seconds(1).unwrap() / -2,
1290 TimeDelta::try_milliseconds(-500).unwrap()
1291 );
1292 assert_eq!(
1293 TimeDelta::try_seconds(-1).unwrap() / -2,
1294 TimeDelta::try_milliseconds(500).unwrap()
1295 );
1296 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1297 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1298 }
1299
1300 #[test]
1301 fn test_duration_sum() {
1302 let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1303 let sum_1: TimeDelta = duration_list_1.iter().sum();
1304 assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1305
1306 let duration_list_2 = [
1307 TimeDelta::zero(),
1308 TimeDelta::try_seconds(1).unwrap(),
1309 TimeDelta::try_seconds(6).unwrap(),
1310 TimeDelta::try_seconds(10).unwrap(),
1311 ];
1312 let sum_2: TimeDelta = duration_list_2.iter().sum();
1313 assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1314
1315 let duration_arr = [
1316 TimeDelta::zero(),
1317 TimeDelta::try_seconds(1).unwrap(),
1318 TimeDelta::try_seconds(6).unwrap(),
1319 TimeDelta::try_seconds(10).unwrap(),
1320 ];
1321 let sum_3: TimeDelta = duration_arr.into_iter().sum();
1322 assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1323 }
1324
1325 #[test]
1326 fn test_duration_fmt() {
1327 assert_eq!(TimeDelta::zero().to_string(), "P0D");
1328 assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1329 assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1330 assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1331 assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1332 assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1333 assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1334 assert_eq!(
1335 (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1336 .to_string(),
1337 "PT604806.543S"
1338 );
1339 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1340 assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1341
1342 assert_eq!(
1344 format!(
1345 "{:30}",
1346 TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1347 ),
1348 "PT86402.345S"
1349 );
1350 }
1351
1352 #[test]
1353 fn test_to_std() {
1354 assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1355 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1356 assert_eq!(
1357 TimeDelta::try_milliseconds(123).unwrap().to_std(),
1358 Ok(Duration::new(0, 123_000_000))
1359 );
1360 assert_eq!(
1361 TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1362 Ok(Duration::new(123, 765_000_000))
1363 );
1364 assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1365 assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1366 assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1367 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1368 }
1369
1370 #[test]
1371 fn test_from_std() {
1372 assert_eq!(
1373 Ok(TimeDelta::try_seconds(1).unwrap()),
1374 TimeDelta::from_std(Duration::new(1, 0))
1375 );
1376 assert_eq!(
1377 Ok(TimeDelta::try_seconds(86_401).unwrap()),
1378 TimeDelta::from_std(Duration::new(86_401, 0))
1379 );
1380 assert_eq!(
1381 Ok(TimeDelta::try_milliseconds(123).unwrap()),
1382 TimeDelta::from_std(Duration::new(0, 123_000_000))
1383 );
1384 assert_eq!(
1385 Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1386 TimeDelta::from_std(Duration::new(123, 765_000_000))
1387 );
1388 assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1389 assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1390 assert_eq!(
1391 TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1392 Err(OutOfRangeError(()))
1393 );
1394 assert_eq!(
1395 TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1396 Err(OutOfRangeError(()))
1397 );
1398 }
1399
1400 #[test]
1401 fn test_duration_const() {
1402 const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1403 const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1404 const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1405 const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1406 const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1407 const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1408 const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1409 const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1410 let combo: TimeDelta = ONE_WEEK
1411 + ONE_DAY
1412 + ONE_HOUR
1413 + ONE_MINUTE
1414 + ONE_SECOND
1415 + ONE_MILLI
1416 + ONE_MICRO
1417 + ONE_NANO;
1418
1419 assert!(ONE_WEEK != TimeDelta::zero());
1420 assert!(ONE_DAY != TimeDelta::zero());
1421 assert!(ONE_HOUR != TimeDelta::zero());
1422 assert!(ONE_MINUTE != TimeDelta::zero());
1423 assert!(ONE_SECOND != TimeDelta::zero());
1424 assert!(ONE_MILLI != TimeDelta::zero());
1425 assert!(ONE_MICRO != TimeDelta::zero());
1426 assert!(ONE_NANO != TimeDelta::zero());
1427 assert_eq!(
1428 combo,
1429 TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1430 + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1431 );
1432 }
1433
1434 #[test]
1435 #[cfg(feature = "rkyv-validation")]
1436 fn test_rkyv_validation() {
1437 let duration = TimeDelta::try_seconds(1).unwrap();
1438 let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1439 assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1440 }
1441}