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 { self.secs + 1 } else { self.secs }
305 }
306
307 pub fn as_seconds_f64(self) -> f64 {
309 self.secs as f64 + self.nanos as f64 / NANOS_PER_SEC as f64
310 }
311
312 pub fn as_seconds_f32(self) -> f32 {
314 self.secs as f32 + self.nanos as f32 / NANOS_PER_SEC as f32
315 }
316
317 pub const fn num_milliseconds(&self) -> i64 {
319 let secs_part = self.num_seconds() * MILLIS_PER_SEC;
323 let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
324 secs_part + nanos_part as i64
325 }
326
327 pub const fn subsec_millis(&self) -> i32 {
333 self.subsec_nanos() / NANOS_PER_MILLI
334 }
335
336 pub const fn num_microseconds(&self) -> Option<i64> {
339 let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
340 let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
341 secs_part.checked_add(nanos_part as i64)
342 }
343
344 pub const fn subsec_micros(&self) -> i32 {
350 self.subsec_nanos() / NANOS_PER_MICRO
351 }
352
353 pub const fn num_nanoseconds(&self) -> Option<i64> {
356 let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
357 let nanos_part = self.subsec_nanos();
358 secs_part.checked_add(nanos_part as i64)
359 }
360
361 pub const fn subsec_nanos(&self) -> i32 {
367 if self.secs < 0 && self.nanos > 0 { self.nanos - NANOS_PER_SEC } else { self.nanos }
368 }
369
370 #[must_use]
372 pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
373 let mut secs = self.secs + rhs.secs;
376 let mut nanos = self.nanos + rhs.nanos;
377 if nanos >= NANOS_PER_SEC {
378 nanos -= NANOS_PER_SEC;
379 secs += 1;
380 }
381 TimeDelta::new(secs, nanos as u32)
382 }
383
384 #[must_use]
386 pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
387 let mut secs = self.secs - rhs.secs;
390 let mut nanos = self.nanos - rhs.nanos;
391 if nanos < 0 {
392 nanos += NANOS_PER_SEC;
393 secs -= 1;
394 }
395 TimeDelta::new(secs, nanos as u32)
396 }
397
398 #[must_use]
400 pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
401 let total_nanos = self.nanos as i64 * rhs as i64;
403 let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
404 let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
406 if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
407 return None;
408 };
409 Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
410 }
411
412 #[must_use]
414 pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
415 if rhs == 0 {
416 return None;
417 }
418 let secs = self.secs / rhs as i64;
419 let carry = self.secs % rhs as i64;
420 let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
421 let nanos = self.nanos / rhs + extra_nanos as i32;
422
423 let (secs, nanos) = match nanos {
424 i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
425 NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
426 _ => (secs, nanos),
427 };
428
429 Some(TimeDelta { secs, nanos })
430 }
431
432 #[inline]
434 pub const fn abs(&self) -> TimeDelta {
435 if self.secs < 0 && self.nanos != 0 {
436 TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
437 } else {
438 TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
439 }
440 }
441
442 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
444 #[inline]
445 pub const fn min_value() -> TimeDelta {
446 MIN
447 }
448
449 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
451 #[inline]
452 pub const fn max_value() -> TimeDelta {
453 MAX
454 }
455
456 #[inline]
458 pub const fn zero() -> TimeDelta {
459 TimeDelta { secs: 0, nanos: 0 }
460 }
461
462 #[inline]
464 pub const fn is_zero(&self) -> bool {
465 self.secs == 0 && self.nanos == 0
466 }
467
468 pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
473 if duration.as_secs() > MAX.secs as u64 {
475 return Err(OutOfRangeError(()));
476 }
477 match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
478 Some(d) => Ok(d),
479 None => Err(OutOfRangeError(())),
480 }
481 }
482
483 pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
488 if self.secs < 0 {
489 return Err(OutOfRangeError(()));
490 }
491 Ok(Duration::new(self.secs as u64, self.nanos as u32))
492 }
493
494 pub(crate) const fn neg(self) -> TimeDelta {
496 let (secs_diff, nanos) = match self.nanos {
497 0 => (0, 0),
498 nanos => (1, NANOS_PER_SEC - nanos),
499 };
500 TimeDelta { secs: -self.secs - secs_diff, nanos }
501 }
502
503 pub const MIN: Self = MIN;
505
506 pub const MAX: Self = MAX;
508}
509
510impl Neg for TimeDelta {
511 type Output = TimeDelta;
512
513 #[inline]
514 fn neg(self) -> TimeDelta {
515 let (secs_diff, nanos) = match self.nanos {
516 0 => (0, 0),
517 nanos => (1, NANOS_PER_SEC - nanos),
518 };
519 TimeDelta { secs: -self.secs - secs_diff, nanos }
520 }
521}
522
523impl Add for TimeDelta {
524 type Output = TimeDelta;
525
526 fn add(self, rhs: TimeDelta) -> TimeDelta {
527 self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
528 }
529}
530
531impl Sub for TimeDelta {
532 type Output = TimeDelta;
533
534 fn sub(self, rhs: TimeDelta) -> TimeDelta {
535 self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
536 }
537}
538
539impl AddAssign for TimeDelta {
540 fn add_assign(&mut self, rhs: TimeDelta) {
541 let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
542 *self = new;
543 }
544}
545
546impl SubAssign for TimeDelta {
547 fn sub_assign(&mut self, rhs: TimeDelta) {
548 let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
549 *self = new;
550 }
551}
552
553impl Mul<i32> for TimeDelta {
554 type Output = TimeDelta;
555
556 fn mul(self, rhs: i32) -> TimeDelta {
557 self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
558 }
559}
560
561impl Div<i32> for TimeDelta {
562 type Output = TimeDelta;
563
564 fn div(self, rhs: i32) -> TimeDelta {
565 self.checked_div(rhs).expect("`i32` is zero")
566 }
567}
568
569impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
570 fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
571 iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
572 }
573}
574
575impl core::iter::Sum<TimeDelta> for TimeDelta {
576 fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
577 iter.fold(TimeDelta::zero(), |acc, x| acc + x)
578 }
579}
580
581impl fmt::Display for TimeDelta {
582 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
586 let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
589
590 write!(f, "{}P", sign)?;
591 if abs.secs == 0 && abs.nanos == 0 {
593 return f.write_str("0D");
594 }
595
596 f.write_fmt(format_args!("T{}", abs.secs))?;
597
598 if abs.nanos > 0 {
599 let mut figures = 9usize;
601 let mut fraction_digits = abs.nanos;
602 loop {
603 let div = fraction_digits / 10;
604 let last_digit = fraction_digits % 10;
605 if last_digit != 0 {
606 break;
607 }
608 fraction_digits = div;
609 figures -= 1;
610 }
611 f.write_fmt(format_args!(".{:01$}", fraction_digits, figures))?;
612 }
613 f.write_str("S")?;
614 Ok(())
615 }
616}
617
618#[derive(Debug, Clone, Copy, PartialEq, Eq)]
625pub struct OutOfRangeError(());
626
627impl fmt::Display for OutOfRangeError {
628 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629 write!(f, "Source duration value is out of range for the target type")
630 }
631}
632
633#[cfg(feature = "std")]
634impl Error for OutOfRangeError {
635 #[allow(deprecated)]
636 fn description(&self) -> &str {
637 "out of range error"
638 }
639}
640
641#[inline]
642const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
643 (this.div_euclid(other), this.rem_euclid(other))
644}
645
646#[cfg(all(feature = "arbitrary", feature = "std"))]
647impl arbitrary::Arbitrary<'_> for TimeDelta {
648 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
649 const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
650 const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
651
652 let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
653 let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
654 let duration = TimeDelta { secs, nanos };
655
656 if duration < MIN || duration > MAX {
657 Err(arbitrary::Error::IncorrectFormat)
658 } else {
659 Ok(duration)
660 }
661 }
662}
663
664#[cfg(feature = "serde")]
665mod serde {
666 use super::TimeDelta;
667 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
668
669 impl Serialize for TimeDelta {
670 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
671 <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
672 }
673 }
674
675 impl<'de> Deserialize<'de> for TimeDelta {
676 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
677 let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
678 TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
679 }
680 }
681
682 #[cfg(test)]
683 mod tests {
684 use super::{super::MAX, TimeDelta};
685
686 #[test]
687 fn test_serde() {
688 let duration = TimeDelta::new(123, 456).unwrap();
689 assert_eq!(
690 serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
691 .unwrap(),
692 duration
693 );
694 }
695
696 #[test]
697 #[should_panic(expected = "TimeDelta out of bounds")]
698 fn test_serde_oob_panic() {
699 let _ =
700 serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
701 }
702 }
703}
704
705#[cfg(test)]
706mod tests {
707 use super::OutOfRangeError;
708 use super::{MAX, MIN, TimeDelta};
709 use crate::expect;
710 use core::time::Duration;
711
712 #[test]
713 fn test_duration() {
714 let days = |d| TimeDelta::try_days(d).unwrap();
715 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
716
717 assert!(seconds(1) != TimeDelta::zero());
718 assert_eq!(seconds(1) + seconds(2), seconds(3));
719 assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
720 assert_eq!(days(10) - seconds(1000), seconds(863_000));
721 assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
722 assert_eq!(
723 days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
724 days(3) + TimeDelta::nanoseconds(234_567_890)
725 );
726 assert_eq!(-days(3), days(-3));
727 assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
728
729 let mut d = TimeDelta::default();
730 d += TimeDelta::try_minutes(1).unwrap();
731 d -= seconds(30);
732 assert_eq!(d, seconds(30));
733 }
734
735 #[test]
736 fn test_duration_num_days() {
737 assert_eq!(TimeDelta::zero().num_days(), 0);
738 assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
739 assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
740 assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
741 assert_eq!(TimeDelta::try_seconds(86_401).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_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
745 assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
746 }
747
748 #[test]
749 fn test_duration_num_seconds() {
750 assert_eq!(TimeDelta::zero().num_seconds(), 0);
751 assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
752 assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
753 assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
754 assert_eq!(TimeDelta::try_milliseconds(1001).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 }
758
759 #[test]
760 fn test_duration_seconds_max_allowed() {
761 let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
762 assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
763 assert_eq!(
764 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
765 i64::MAX as i128 / 1_000 * 1_000_000_000
766 );
767 }
768
769 #[test]
770 fn test_duration_seconds_max_overflow() {
771 assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
772 }
773
774 #[test]
775 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
776 fn test_duration_seconds_max_overflow_panic() {
777 let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
778 }
779
780 #[test]
781 fn test_duration_seconds_min_allowed() {
782 let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); assert_eq!(duration.num_seconds(), i64::MIN / 1_000); assert_eq!(
785 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
786 -i64::MAX as i128 / 1_000 * 1_000_000_000
787 );
788 }
789
790 #[test]
791 fn test_duration_seconds_min_underflow() {
792 assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
793 }
794
795 #[test]
796 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
797 fn test_duration_seconds_min_underflow_panic() {
798 let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
799 }
800
801 #[test]
802 fn test_duration_as_seconds_f64() {
803 assert_eq!(TimeDelta::seconds(1).as_seconds_f64(), 1.0);
804 assert_eq!(TimeDelta::seconds(-1).as_seconds_f64(), -1.0);
805 assert_eq!(TimeDelta::seconds(100).as_seconds_f64(), 100.0);
806 assert_eq!(TimeDelta::seconds(-100).as_seconds_f64(), -100.0);
807
808 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f64(), 0.5);
809 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f64(), -0.5);
810 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f64(), 1.5);
811 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f64(), -1.5);
812 }
813
814 #[test]
815 fn test_duration_as_seconds_f32() {
816 assert_eq!(TimeDelta::seconds(1).as_seconds_f32(), 1.0);
817 assert_eq!(TimeDelta::seconds(-1).as_seconds_f32(), -1.0);
818 assert_eq!(TimeDelta::seconds(100).as_seconds_f32(), 100.0);
819 assert_eq!(TimeDelta::seconds(-100).as_seconds_f32(), -100.0);
820
821 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f32(), 0.5);
822 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f32(), -0.5);
823 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f32(), 1.5);
824 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f32(), -1.5);
825 }
826
827 #[test]
828 fn test_duration_subsec_nanos() {
829 assert_eq!(TimeDelta::zero().subsec_nanos(), 0);
830 assert_eq!(TimeDelta::nanoseconds(1).subsec_nanos(), 1);
831 assert_eq!(TimeDelta::nanoseconds(-1).subsec_nanos(), -1);
832 assert_eq!(TimeDelta::seconds(1).subsec_nanos(), 0);
833 assert_eq!(TimeDelta::nanoseconds(1_000_000_001).subsec_nanos(), 1);
834 }
835
836 #[test]
837 fn test_duration_subsec_micros() {
838 assert_eq!(TimeDelta::zero().subsec_micros(), 0);
839 assert_eq!(TimeDelta::microseconds(1).subsec_micros(), 1);
840 assert_eq!(TimeDelta::microseconds(-1).subsec_micros(), -1);
841 assert_eq!(TimeDelta::seconds(1).subsec_micros(), 0);
842 assert_eq!(TimeDelta::microseconds(1_000_001).subsec_micros(), 1);
843 assert_eq!(TimeDelta::nanoseconds(1_000_001_999).subsec_micros(), 1);
844 }
845
846 #[test]
847 fn test_duration_subsec_millis() {
848 assert_eq!(TimeDelta::zero().subsec_millis(), 0);
849 assert_eq!(TimeDelta::milliseconds(1).subsec_millis(), 1);
850 assert_eq!(TimeDelta::milliseconds(-1).subsec_millis(), -1);
851 assert_eq!(TimeDelta::seconds(1).subsec_millis(), 0);
852 assert_eq!(TimeDelta::milliseconds(1_001).subsec_millis(), 1);
853 assert_eq!(TimeDelta::microseconds(1_001_999).subsec_millis(), 1);
854 }
855
856 #[test]
857 fn test_duration_num_milliseconds() {
858 assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
859 assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
860 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
861 assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
862 assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
863 assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
864 assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
865 }
866
867 #[test]
868 fn test_duration_milliseconds_max_allowed() {
869 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
872 assert_eq!(duration.num_milliseconds(), i64::MAX);
873 assert_eq!(
874 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
875 i64::MAX as i128 * 1_000_000
876 );
877 }
878
879 #[test]
880 fn test_duration_milliseconds_max_overflow() {
881 assert!(
884 TimeDelta::try_milliseconds(i64::MAX)
885 .unwrap()
886 .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
887 .is_none()
888 );
889 }
890
891 #[test]
892 fn test_duration_milliseconds_min_allowed() {
893 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
897 assert_eq!(duration.num_milliseconds(), -i64::MAX);
898 assert_eq!(
899 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
900 -i64::MAX as i128 * 1_000_000
901 );
902 }
903
904 #[test]
905 fn test_duration_milliseconds_min_underflow() {
906 assert!(
909 TimeDelta::try_milliseconds(-i64::MAX)
910 .unwrap()
911 .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
912 .is_none()
913 );
914 }
915
916 #[test]
917 #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
918 fn test_duration_milliseconds_min_underflow_panic() {
919 let _ = TimeDelta::milliseconds(i64::MIN); }
925
926 #[test]
927 fn test_duration_num_microseconds() {
928 assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
929 assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
930 assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
931 assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
932 assert_eq!(TimeDelta::nanoseconds(1001).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
936 const MICROS_PER_DAY: i64 = 86_400_000_000;
938 assert_eq!(
939 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
940 Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
941 );
942 assert_eq!(
943 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
944 Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
945 );
946 assert_eq!(
947 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
948 None
949 );
950 assert_eq!(
951 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
952 None
953 );
954 }
955 #[test]
956 fn test_duration_microseconds_max_allowed() {
957 let duration = TimeDelta::microseconds(i64::MAX);
961 assert_eq!(duration.num_microseconds(), Some(i64::MAX));
962 assert_eq!(
963 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
964 i64::MAX as i128 * 1_000
965 );
966 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
971 assert!(duration.num_microseconds().is_none());
972 assert_eq!(
973 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
974 i64::MAX as i128 * 1_000_000
975 );
976 }
977 #[test]
978 fn test_duration_microseconds_max_overflow() {
979 let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
982 assert!(duration.num_microseconds().is_none());
983 assert_eq!(
984 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
985 (i64::MAX as i128 + 1) * 1_000
986 );
987 assert!(
990 TimeDelta::try_milliseconds(i64::MAX)
991 .unwrap()
992 .checked_add(&TimeDelta::microseconds(1))
993 .is_none()
994 );
995 }
996 #[test]
997 fn test_duration_microseconds_min_allowed() {
998 let duration = TimeDelta::microseconds(i64::MIN);
1002 assert_eq!(duration.num_microseconds(), Some(i64::MIN));
1003 assert_eq!(
1004 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1005 i64::MIN as i128 * 1_000
1006 );
1007 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1012 assert!(duration.num_microseconds().is_none());
1013 assert_eq!(
1014 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1015 -i64::MAX as i128 * 1_000_000
1016 );
1017 }
1018 #[test]
1019 fn test_duration_microseconds_min_underflow() {
1020 let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
1023 assert!(duration.num_microseconds().is_none());
1024 assert_eq!(
1025 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1026 (i64::MIN as i128 - 1) * 1_000
1027 );
1028 assert!(
1031 TimeDelta::try_milliseconds(-i64::MAX)
1032 .unwrap()
1033 .checked_sub(&TimeDelta::microseconds(1))
1034 .is_none()
1035 );
1036 }
1037
1038 #[test]
1039 fn test_duration_num_nanoseconds() {
1040 assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
1041 assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
1042 assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
1043
1044 const NANOS_PER_DAY: i64 = 86_400_000_000_000;
1046 assert_eq!(
1047 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1048 Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1049 );
1050 assert_eq!(
1051 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1052 Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1053 );
1054 assert_eq!(
1055 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
1056 None
1057 );
1058 assert_eq!(
1059 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
1060 None
1061 );
1062 }
1063 #[test]
1064 fn test_duration_nanoseconds_max_allowed() {
1065 let duration = TimeDelta::nanoseconds(i64::MAX);
1069 assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
1070 assert_eq!(
1071 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1072 i64::MAX as i128
1073 );
1074 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
1078 assert!(duration.num_nanoseconds().is_none());
1079 assert_eq!(
1080 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1081 i64::MAX as i128 * 1_000_000
1082 );
1083 }
1084
1085 #[test]
1086 fn test_duration_nanoseconds_max_overflow() {
1087 let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1090 assert!(duration.num_nanoseconds().is_none());
1091 assert_eq!(
1092 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1093 i64::MAX as i128 + 1
1094 );
1095 assert!(
1098 TimeDelta::try_milliseconds(i64::MAX)
1099 .unwrap()
1100 .checked_add(&TimeDelta::nanoseconds(1))
1101 .is_none()
1102 );
1103 }
1104
1105 #[test]
1106 fn test_duration_nanoseconds_min_allowed() {
1107 let duration = TimeDelta::nanoseconds(i64::MIN);
1111 assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1112 assert_eq!(
1113 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1114 i64::MIN as i128
1115 );
1116 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1120 assert!(duration.num_nanoseconds().is_none());
1121 assert_eq!(
1122 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1123 -i64::MAX as i128 * 1_000_000
1124 );
1125 }
1126
1127 #[test]
1128 fn test_duration_nanoseconds_min_underflow() {
1129 let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1132 assert!(duration.num_nanoseconds().is_none());
1133 assert_eq!(
1134 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1135 i64::MIN as i128 - 1
1136 );
1137 assert!(
1140 TimeDelta::try_milliseconds(-i64::MAX)
1141 .unwrap()
1142 .checked_sub(&TimeDelta::nanoseconds(1))
1143 .is_none()
1144 );
1145 }
1146
1147 #[test]
1148 fn test_max() {
1149 assert_eq!(
1150 MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1151 i64::MAX as i128 * 1_000_000
1152 );
1153 assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1154 assert_eq!(MAX.num_milliseconds(), i64::MAX);
1155 assert_eq!(MAX.num_microseconds(), None);
1156 assert_eq!(MAX.num_nanoseconds(), None);
1157 }
1158
1159 #[test]
1160 fn test_min() {
1161 assert_eq!(
1162 MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1163 -i64::MAX as i128 * 1_000_000
1164 );
1165 assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1166 assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1167 assert_eq!(MIN.num_microseconds(), None);
1168 assert_eq!(MIN.num_nanoseconds(), None);
1169 }
1170
1171 #[test]
1172 fn test_duration_ord() {
1173 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1174
1175 assert!(milliseconds(1) < milliseconds(2));
1176 assert!(milliseconds(2) > milliseconds(1));
1177 assert!(milliseconds(-1) > milliseconds(-2));
1178 assert!(milliseconds(-2) < milliseconds(-1));
1179 assert!(milliseconds(-1) < milliseconds(1));
1180 assert!(milliseconds(1) > milliseconds(-1));
1181 assert!(milliseconds(0) < milliseconds(1));
1182 assert!(milliseconds(0) > milliseconds(-1));
1183 assert!(milliseconds(1_001) < milliseconds(1_002));
1184 assert!(milliseconds(-1_001) > milliseconds(-1_002));
1185 assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1186 assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1187 assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1188 assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1189 }
1190
1191 #[test]
1192 fn test_duration_checked_ops() {
1193 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1194 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1195
1196 assert_eq!(
1197 milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1198 Some(milliseconds(i64::MAX))
1199 );
1200 assert_eq!(
1201 milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1202 Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1203 );
1204 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1205 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1206
1207 assert_eq!(
1208 milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1209 Some(milliseconds(-i64::MAX))
1210 );
1211 assert_eq!(
1212 milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1213 Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1214 );
1215 assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1216 assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1217
1218 assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1219 assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1220 assert!(seconds(1).checked_div(0).is_none());
1221 }
1222
1223 #[test]
1224 fn test_duration_abs() {
1225 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1226
1227 assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1228 assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1229 assert_eq!(milliseconds(300).abs(), milliseconds(300));
1230 assert_eq!(milliseconds(0).abs(), milliseconds(0));
1231 assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1232 assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1233 assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1234 assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1235 assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1236 assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1237 }
1238
1239 #[test]
1240 #[allow(clippy::erasing_op)]
1241 fn test_duration_mul() {
1242 assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1243 assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1244 assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1245 assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1246 assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1247 assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1248 assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1249 assert_eq!(
1250 TimeDelta::nanoseconds(30) * 333_333_333,
1251 TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1252 );
1253 assert_eq!(
1254 (TimeDelta::nanoseconds(1)
1255 + TimeDelta::try_seconds(1).unwrap()
1256 + TimeDelta::try_days(1).unwrap())
1257 * 3,
1258 TimeDelta::nanoseconds(3)
1259 + TimeDelta::try_seconds(3).unwrap()
1260 + TimeDelta::try_days(3).unwrap()
1261 );
1262 assert_eq!(
1263 TimeDelta::try_milliseconds(1500).unwrap() * -2,
1264 TimeDelta::try_seconds(-3).unwrap()
1265 );
1266 assert_eq!(
1267 TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1268 TimeDelta::try_seconds(-3).unwrap()
1269 );
1270 }
1271
1272 #[test]
1273 fn test_duration_div() {
1274 assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1275 assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1276 assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1277 assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
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::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1281 assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1282 assert_eq!(
1283 TimeDelta::try_seconds(-1).unwrap() / 2,
1284 TimeDelta::try_milliseconds(-500).unwrap()
1285 );
1286 assert_eq!(
1287 TimeDelta::try_seconds(1).unwrap() / -2,
1288 TimeDelta::try_milliseconds(-500).unwrap()
1289 );
1290 assert_eq!(
1291 TimeDelta::try_seconds(-1).unwrap() / -2,
1292 TimeDelta::try_milliseconds(500).unwrap()
1293 );
1294 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1295 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1296 }
1297
1298 #[test]
1299 fn test_duration_sum() {
1300 let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1301 let sum_1: TimeDelta = duration_list_1.iter().sum();
1302 assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1303
1304 let duration_list_2 = [
1305 TimeDelta::zero(),
1306 TimeDelta::try_seconds(1).unwrap(),
1307 TimeDelta::try_seconds(6).unwrap(),
1308 TimeDelta::try_seconds(10).unwrap(),
1309 ];
1310 let sum_2: TimeDelta = duration_list_2.iter().sum();
1311 assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1312
1313 let duration_arr = [
1314 TimeDelta::zero(),
1315 TimeDelta::try_seconds(1).unwrap(),
1316 TimeDelta::try_seconds(6).unwrap(),
1317 TimeDelta::try_seconds(10).unwrap(),
1318 ];
1319 let sum_3: TimeDelta = duration_arr.into_iter().sum();
1320 assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1321 }
1322
1323 #[test]
1324 fn test_duration_fmt() {
1325 assert_eq!(TimeDelta::zero().to_string(), "P0D");
1326 assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1327 assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1328 assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1329 assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1330 assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1331 assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1332 assert_eq!(
1333 (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1334 .to_string(),
1335 "PT604806.543S"
1336 );
1337 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1338 assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1339
1340 assert_eq!(
1342 format!(
1343 "{:30}",
1344 TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1345 ),
1346 "PT86402.345S"
1347 );
1348 }
1349
1350 #[test]
1351 fn test_to_std() {
1352 assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1353 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1354 assert_eq!(
1355 TimeDelta::try_milliseconds(123).unwrap().to_std(),
1356 Ok(Duration::new(0, 123_000_000))
1357 );
1358 assert_eq!(
1359 TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1360 Ok(Duration::new(123, 765_000_000))
1361 );
1362 assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1363 assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1364 assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1365 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1366 }
1367
1368 #[test]
1369 fn test_from_std() {
1370 assert_eq!(
1371 Ok(TimeDelta::try_seconds(1).unwrap()),
1372 TimeDelta::from_std(Duration::new(1, 0))
1373 );
1374 assert_eq!(
1375 Ok(TimeDelta::try_seconds(86_401).unwrap()),
1376 TimeDelta::from_std(Duration::new(86_401, 0))
1377 );
1378 assert_eq!(
1379 Ok(TimeDelta::try_milliseconds(123).unwrap()),
1380 TimeDelta::from_std(Duration::new(0, 123_000_000))
1381 );
1382 assert_eq!(
1383 Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1384 TimeDelta::from_std(Duration::new(123, 765_000_000))
1385 );
1386 assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1387 assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1388 assert_eq!(
1389 TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1390 Err(OutOfRangeError(()))
1391 );
1392 assert_eq!(
1393 TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1394 Err(OutOfRangeError(()))
1395 );
1396 }
1397
1398 #[test]
1399 fn test_duration_const() {
1400 const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1401 const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1402 const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1403 const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1404 const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1405 const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1406 const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1407 const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1408 let combo: TimeDelta = ONE_WEEK
1409 + ONE_DAY
1410 + ONE_HOUR
1411 + ONE_MINUTE
1412 + ONE_SECOND
1413 + ONE_MILLI
1414 + ONE_MICRO
1415 + ONE_NANO;
1416
1417 assert!(ONE_WEEK != TimeDelta::zero());
1418 assert!(ONE_DAY != TimeDelta::zero());
1419 assert!(ONE_HOUR != TimeDelta::zero());
1420 assert!(ONE_MINUTE != TimeDelta::zero());
1421 assert!(ONE_SECOND != TimeDelta::zero());
1422 assert!(ONE_MILLI != TimeDelta::zero());
1423 assert!(ONE_MICRO != TimeDelta::zero());
1424 assert!(ONE_NANO != TimeDelta::zero());
1425 assert_eq!(
1426 combo,
1427 TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1428 + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1429 );
1430 }
1431
1432 #[test]
1433 #[cfg(feature = "rkyv-validation")]
1434 fn test_rkyv_validation() {
1435 let duration = TimeDelta::try_seconds(1).unwrap();
1436 let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1437 assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1438 }
1439}