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