1use core::error::Error;
14use core::fmt;
15use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
16use core::time::Duration;
17
18use crate::{expect, try_opt};
19
20#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
21use rkyv::{Archive, Deserialize, Serialize};
22
23const NANOS_PER_MICRO: i32 = 1000;
25const NANOS_PER_MILLI: i32 = 1_000_000;
27pub(crate) const NANOS_PER_SEC: i32 = 1_000_000_000;
29const MICROS_PER_SEC: i64 = 1_000_000;
31const MILLIS_PER_SEC: i64 = 1000;
33const SECS_PER_MINUTE: i64 = 60;
35const SECS_PER_HOUR: i64 = 3600;
37const SECS_PER_DAY: i64 = 86_400;
39const SECS_PER_WEEK: i64 = 604_800;
41
42#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
52#[cfg_attr(
53 any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
54 derive(Archive, Deserialize, Serialize),
55 archive(compare(PartialEq, PartialOrd)),
56 archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
57)]
58#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
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 #[track_caller]
106 pub const fn weeks(weeks: i64) -> TimeDelta {
107 expect(TimeDelta::try_weeks(weeks), "TimeDelta::weeks out of bounds")
108 }
109
110 #[inline]
119 pub const fn try_weeks(weeks: i64) -> Option<TimeDelta> {
120 TimeDelta::try_seconds(try_opt!(weeks.checked_mul(SECS_PER_WEEK)))
121 }
122
123 #[inline]
132 #[must_use]
133 #[track_caller]
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 #[track_caller]
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 #[track_caller]
187 pub const fn minutes(minutes: i64) -> TimeDelta {
188 expect(TimeDelta::try_minutes(minutes), "TimeDelta::minutes out of bounds")
189 }
190
191 #[inline]
199 pub const fn try_minutes(minutes: i64) -> Option<TimeDelta> {
200 TimeDelta::try_seconds(try_opt!(minutes.checked_mul(SECS_PER_MINUTE)))
201 }
202
203 #[inline]
210 #[must_use]
211 #[track_caller]
212 pub const fn seconds(seconds: i64) -> TimeDelta {
213 expect(TimeDelta::try_seconds(seconds), "TimeDelta::seconds out of bounds")
214 }
215
216 #[inline]
224 pub const fn try_seconds(seconds: i64) -> Option<TimeDelta> {
225 TimeDelta::new(seconds, 0)
226 }
227
228 #[inline]
235 #[track_caller]
236 pub const fn milliseconds(milliseconds: i64) -> TimeDelta {
237 expect(TimeDelta::try_milliseconds(milliseconds), "TimeDelta::milliseconds out of bounds")
238 }
239
240 #[inline]
247 pub const fn try_milliseconds(milliseconds: i64) -> Option<TimeDelta> {
248 if milliseconds < -i64::MAX {
251 return None;
252 }
253 let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
254 let d = TimeDelta { secs, nanos: millis as i32 * NANOS_PER_MILLI };
255 Some(d)
256 }
257
258 #[inline]
265 pub const fn microseconds(microseconds: i64) -> TimeDelta {
266 let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
267 let nanos = micros as i32 * NANOS_PER_MICRO;
268 TimeDelta { secs, nanos }
269 }
270
271 #[inline]
278 pub const fn nanoseconds(nanos: i64) -> TimeDelta {
279 let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
280 TimeDelta { secs, nanos: nanos as i32 }
281 }
282
283 #[inline]
285 pub const fn num_weeks(&self) -> i64 {
286 self.num_days() / 7
287 }
288
289 #[inline]
291 pub const fn num_days(&self) -> i64 {
292 self.num_seconds() / SECS_PER_DAY
293 }
294
295 #[inline]
297 pub const fn num_hours(&self) -> i64 {
298 self.num_seconds() / SECS_PER_HOUR
299 }
300
301 #[inline]
303 pub const fn num_minutes(&self) -> i64 {
304 self.num_seconds() / SECS_PER_MINUTE
305 }
306
307 pub const fn num_seconds(&self) -> i64 {
309 if self.secs < 0 && self.nanos > 0 { self.secs + 1 } else { self.secs }
311 }
312
313 pub fn as_seconds_f64(self) -> f64 {
315 self.secs as f64 + self.nanos as f64 / NANOS_PER_SEC as f64
316 }
317
318 pub fn as_seconds_f32(self) -> f32 {
320 self.secs as f32 + self.nanos as f32 / NANOS_PER_SEC as f32
321 }
322
323 pub const fn num_milliseconds(&self) -> i64 {
325 let secs_part = self.num_seconds() * MILLIS_PER_SEC;
329 let nanos_part = self.subsec_nanos() / NANOS_PER_MILLI;
330 secs_part + nanos_part as i64
331 }
332
333 pub const fn subsec_millis(&self) -> i32 {
339 self.subsec_nanos() / NANOS_PER_MILLI
340 }
341
342 pub const fn num_microseconds(&self) -> Option<i64> {
345 let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
346 let nanos_part = self.subsec_nanos() / NANOS_PER_MICRO;
347 secs_part.checked_add(nanos_part as i64)
348 }
349
350 pub const fn subsec_micros(&self) -> i32 {
356 self.subsec_nanos() / NANOS_PER_MICRO
357 }
358
359 pub const fn num_nanoseconds(&self) -> Option<i64> {
362 let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
363 let nanos_part = self.subsec_nanos();
364 secs_part.checked_add(nanos_part as i64)
365 }
366
367 pub const fn subsec_nanos(&self) -> i32 {
373 if self.secs < 0 && self.nanos > 0 { self.nanos - NANOS_PER_SEC } else { self.nanos }
374 }
375
376 #[must_use]
378 pub const fn checked_add(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
379 let mut secs = self.secs + rhs.secs;
382 let mut nanos = self.nanos + rhs.nanos;
383 if nanos >= NANOS_PER_SEC {
384 nanos -= NANOS_PER_SEC;
385 secs += 1;
386 }
387 TimeDelta::new(secs, nanos as u32)
388 }
389
390 #[must_use]
392 pub const fn checked_sub(&self, rhs: &TimeDelta) -> Option<TimeDelta> {
393 let mut secs = self.secs - rhs.secs;
396 let mut nanos = self.nanos - rhs.nanos;
397 if nanos < 0 {
398 nanos += NANOS_PER_SEC;
399 secs -= 1;
400 }
401 TimeDelta::new(secs, nanos as u32)
402 }
403
404 #[must_use]
406 pub const fn checked_mul(&self, rhs: i32) -> Option<TimeDelta> {
407 let total_nanos = self.nanos as i64 * rhs as i64;
409 let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
410 let secs: i128 = self.secs as i128 * rhs as i128 + extra_secs as i128;
412 if secs <= i64::MIN as i128 || secs >= i64::MAX as i128 {
413 return None;
414 };
415 Some(TimeDelta { secs: secs as i64, nanos: nanos as i32 })
416 }
417
418 #[must_use]
420 pub const fn checked_div(&self, rhs: i32) -> Option<TimeDelta> {
421 if rhs == 0 {
422 return None;
423 }
424 let secs = self.secs / rhs as i64;
425 let carry = self.secs % rhs as i64;
426 let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
427 let nanos = self.nanos / rhs + extra_nanos as i32;
428
429 let (secs, nanos) = match nanos {
430 i32::MIN..=-1 => (secs - 1, nanos + NANOS_PER_SEC),
431 NANOS_PER_SEC..=i32::MAX => (secs + 1, nanos - NANOS_PER_SEC),
432 _ => (secs, nanos),
433 };
434
435 Some(TimeDelta { secs, nanos })
436 }
437
438 #[inline]
440 pub const fn abs(&self) -> TimeDelta {
441 if self.secs < 0 && self.nanos != 0 {
442 TimeDelta { secs: (self.secs + 1).abs(), nanos: NANOS_PER_SEC - self.nanos }
443 } else {
444 TimeDelta { secs: self.secs.abs(), nanos: self.nanos }
445 }
446 }
447
448 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MIN` instead")]
450 #[inline]
451 pub const fn min_value() -> TimeDelta {
452 MIN
453 }
454
455 #[deprecated(since = "0.4.39", note = "Use `TimeDelta::MAX` instead")]
457 #[inline]
458 pub const fn max_value() -> TimeDelta {
459 MAX
460 }
461
462 #[inline]
464 pub const fn zero() -> TimeDelta {
465 TimeDelta { secs: 0, nanos: 0 }
466 }
467
468 #[inline]
470 pub const fn is_zero(&self) -> bool {
471 self.secs == 0 && self.nanos == 0
472 }
473
474 pub const fn from_std(duration: Duration) -> Result<TimeDelta, OutOfRangeError> {
479 if duration.as_secs() > MAX.secs as u64 {
481 return Err(OutOfRangeError(()));
482 }
483 match TimeDelta::new(duration.as_secs() as i64, duration.subsec_nanos()) {
484 Some(d) => Ok(d),
485 None => Err(OutOfRangeError(())),
486 }
487 }
488
489 pub const fn to_std(&self) -> Result<Duration, OutOfRangeError> {
494 if self.secs < 0 {
495 return Err(OutOfRangeError(()));
496 }
497 Ok(Duration::new(self.secs as u64, self.nanos as u32))
498 }
499
500 pub(crate) const fn neg(self) -> TimeDelta {
502 let (secs_diff, nanos) = match self.nanos {
503 0 => (0, 0),
504 nanos => (1, NANOS_PER_SEC - nanos),
505 };
506 TimeDelta { secs: -self.secs - secs_diff, nanos }
507 }
508
509 pub const MIN: Self = MIN;
511
512 pub const MAX: Self = MAX;
514}
515
516impl Neg for TimeDelta {
517 type Output = TimeDelta;
518
519 #[inline]
520 #[track_caller]
521 fn neg(self) -> TimeDelta {
522 let (secs_diff, nanos) = match self.nanos {
523 0 => (0, 0),
524 nanos => (1, NANOS_PER_SEC - nanos),
525 };
526 TimeDelta { secs: -self.secs - secs_diff, nanos }
527 }
528}
529
530impl Add for TimeDelta {
531 type Output = TimeDelta;
532
533 #[track_caller]
534 fn add(self, rhs: TimeDelta) -> TimeDelta {
535 self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed")
536 }
537}
538
539impl Sub for TimeDelta {
540 type Output = TimeDelta;
541
542 #[track_caller]
543 fn sub(self, rhs: TimeDelta) -> TimeDelta {
544 self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed")
545 }
546}
547
548impl AddAssign for TimeDelta {
549 #[track_caller]
550 fn add_assign(&mut self, rhs: TimeDelta) {
551 let new = self.checked_add(&rhs).expect("`TimeDelta + TimeDelta` overflowed");
552 *self = new;
553 }
554}
555
556impl SubAssign for TimeDelta {
557 #[track_caller]
558 fn sub_assign(&mut self, rhs: TimeDelta) {
559 let new = self.checked_sub(&rhs).expect("`TimeDelta - TimeDelta` overflowed");
560 *self = new;
561 }
562}
563
564impl Mul<i32> for TimeDelta {
565 type Output = TimeDelta;
566
567 #[track_caller]
568 fn mul(self, rhs: i32) -> TimeDelta {
569 self.checked_mul(rhs).expect("`TimeDelta * i32` overflowed")
570 }
571}
572
573impl Div<i32> for TimeDelta {
574 type Output = TimeDelta;
575
576 #[track_caller]
577 fn div(self, rhs: i32) -> TimeDelta {
578 self.checked_div(rhs).expect("`i32` is zero")
579 }
580}
581
582impl<'a> core::iter::Sum<&'a TimeDelta> for TimeDelta {
583 fn sum<I: Iterator<Item = &'a TimeDelta>>(iter: I) -> TimeDelta {
584 iter.fold(TimeDelta::zero(), |acc, x| acc + *x)
585 }
586}
587
588impl core::iter::Sum<TimeDelta> for TimeDelta {
589 fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
590 iter.fold(TimeDelta::zero(), |acc, x| acc + x)
591 }
592}
593
594impl fmt::Display for TimeDelta {
595 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599 let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
602
603 write!(f, "{sign}P")?;
604 if abs.secs == 0 && abs.nanos == 0 {
606 return f.write_str("0D");
607 }
608
609 f.write_fmt(format_args!("T{}", abs.secs))?;
610
611 if abs.nanos > 0 {
612 let mut figures = 9usize;
614 let mut fraction_digits = abs.nanos;
615 loop {
616 let div = fraction_digits / 10;
617 let last_digit = fraction_digits % 10;
618 if last_digit != 0 {
619 break;
620 }
621 fraction_digits = div;
622 figures -= 1;
623 }
624 f.write_fmt(format_args!(".{fraction_digits:0figures$}"))?;
625 }
626 f.write_str("S")?;
627 Ok(())
628 }
629}
630
631#[derive(Debug, Clone, Copy, PartialEq, Eq)]
638#[cfg_attr(feature = "defmt", derive(defmt::Format))]
639pub struct OutOfRangeError(());
640
641impl fmt::Display for OutOfRangeError {
642 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
643 write!(f, "Source duration value is out of range for the target type")
644 }
645}
646
647impl Error for OutOfRangeError {
648 #[allow(deprecated)]
649 fn description(&self) -> &str {
650 "out of range error"
651 }
652}
653
654#[inline]
655const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
656 (this.div_euclid(other), this.rem_euclid(other))
657}
658
659#[cfg(all(feature = "arbitrary", feature = "std"))]
660impl arbitrary::Arbitrary<'_> for TimeDelta {
661 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<TimeDelta> {
662 const MIN_SECS: i64 = -i64::MAX / MILLIS_PER_SEC - 1;
663 const MAX_SECS: i64 = i64::MAX / MILLIS_PER_SEC;
664
665 let secs: i64 = u.int_in_range(MIN_SECS..=MAX_SECS)?;
666 let nanos: i32 = u.int_in_range(0..=(NANOS_PER_SEC - 1))?;
667 let duration = TimeDelta { secs, nanos };
668
669 if duration < MIN || duration > MAX {
670 Err(arbitrary::Error::IncorrectFormat)
671 } else {
672 Ok(duration)
673 }
674 }
675}
676
677#[cfg(feature = "serde")]
678mod serde {
679 use super::TimeDelta;
680 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
681
682 impl Serialize for TimeDelta {
683 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
684 <(i64, i32) as Serialize>::serialize(&(self.secs, self.nanos), serializer)
685 }
686 }
687
688 impl<'de> Deserialize<'de> for TimeDelta {
689 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
690 let (secs, nanos) = <(i64, i32) as Deserialize>::deserialize(deserializer)?;
691 TimeDelta::new(secs, nanos as u32).ok_or(Error::custom("TimeDelta out of bounds"))
692 }
693 }
694
695 #[cfg(test)]
696 mod tests {
697 use super::{super::MAX, TimeDelta};
698
699 #[test]
700 fn test_serde() {
701 let duration = TimeDelta::new(123, 456).unwrap();
702 assert_eq!(
703 serde_json::from_value::<TimeDelta>(serde_json::to_value(duration).unwrap())
704 .unwrap(),
705 duration
706 );
707 }
708
709 #[test]
710 #[should_panic(expected = "TimeDelta out of bounds")]
711 fn test_serde_oob_panic() {
712 let _ =
713 serde_json::from_value::<TimeDelta>(serde_json::json!([MAX.secs + 1, 0])).unwrap();
714 }
715 }
716}
717
718#[cfg(test)]
719mod tests {
720 use super::OutOfRangeError;
721 use super::{MAX, MIN, TimeDelta};
722 use crate::expect;
723 use core::time::Duration;
724
725 #[test]
726 fn test_duration() {
727 let days = |d| TimeDelta::try_days(d).unwrap();
728 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
729
730 assert!(seconds(1) != TimeDelta::zero());
731 assert_eq!(seconds(1) + seconds(2), seconds(3));
732 assert_eq!(seconds(86_399) + seconds(4), days(1) + seconds(3));
733 assert_eq!(days(10) - seconds(1000), seconds(863_000));
734 assert_eq!(days(10) - seconds(1_000_000), seconds(-136_000));
735 assert_eq!(
736 days(2) + seconds(86_399) + TimeDelta::nanoseconds(1_234_567_890),
737 days(3) + TimeDelta::nanoseconds(234_567_890)
738 );
739 assert_eq!(-days(3), days(-3));
740 assert_eq!(-(days(3) + seconds(70)), days(-4) + seconds(86_400 - 70));
741
742 let mut d = TimeDelta::default();
743 d += TimeDelta::try_minutes(1).unwrap();
744 d -= seconds(30);
745 assert_eq!(d, seconds(30));
746 }
747
748 #[test]
749 fn test_duration_num_days() {
750 assert_eq!(TimeDelta::zero().num_days(), 0);
751 assert_eq!(TimeDelta::try_days(1).unwrap().num_days(), 1);
752 assert_eq!(TimeDelta::try_days(-1).unwrap().num_days(), -1);
753 assert_eq!(TimeDelta::try_seconds(86_399).unwrap().num_days(), 0);
754 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().num_days(), 1);
755 assert_eq!(TimeDelta::try_seconds(-86_399).unwrap().num_days(), 0);
756 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().num_days(), -1);
757 assert_eq!(TimeDelta::try_days(i32::MAX as i64).unwrap().num_days(), i32::MAX as i64);
758 assert_eq!(TimeDelta::try_days(i32::MIN as i64).unwrap().num_days(), i32::MIN as i64);
759 }
760
761 #[test]
762 fn test_duration_num_seconds() {
763 assert_eq!(TimeDelta::zero().num_seconds(), 0);
764 assert_eq!(TimeDelta::try_seconds(1).unwrap().num_seconds(), 1);
765 assert_eq!(TimeDelta::try_seconds(-1).unwrap().num_seconds(), -1);
766 assert_eq!(TimeDelta::try_milliseconds(999).unwrap().num_seconds(), 0);
767 assert_eq!(TimeDelta::try_milliseconds(1001).unwrap().num_seconds(), 1);
768 assert_eq!(TimeDelta::try_milliseconds(-999).unwrap().num_seconds(), 0);
769 assert_eq!(TimeDelta::try_milliseconds(-1001).unwrap().num_seconds(), -1);
770 }
771
772 #[test]
773 fn test_duration_seconds_max_allowed() {
774 let duration = TimeDelta::try_seconds(i64::MAX / 1_000).unwrap();
775 assert_eq!(duration.num_seconds(), i64::MAX / 1_000);
776 assert_eq!(
777 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
778 i64::MAX as i128 / 1_000 * 1_000_000_000
779 );
780 }
781
782 #[test]
783 fn test_duration_seconds_max_overflow() {
784 assert!(TimeDelta::try_seconds(i64::MAX / 1_000 + 1).is_none());
785 }
786
787 #[test]
788 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
789 fn test_duration_seconds_max_overflow_panic() {
790 let _ = TimeDelta::seconds(i64::MAX / 1_000 + 1);
791 }
792
793 #[test]
794 fn test_duration_seconds_min_allowed() {
795 let duration = TimeDelta::try_seconds(i64::MIN / 1_000).unwrap(); assert_eq!(duration.num_seconds(), i64::MIN / 1_000); assert_eq!(
798 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
799 -i64::MAX as i128 / 1_000 * 1_000_000_000
800 );
801 }
802
803 #[test]
804 fn test_duration_seconds_min_underflow() {
805 assert!(TimeDelta::try_seconds(-i64::MAX / 1_000 - 1).is_none());
806 }
807
808 #[test]
809 #[should_panic(expected = "TimeDelta::seconds out of bounds")]
810 fn test_duration_seconds_min_underflow_panic() {
811 let _ = TimeDelta::seconds(-i64::MAX / 1_000 - 1);
812 }
813
814 #[test]
815 fn test_duration_as_seconds_f64() {
816 assert_eq!(TimeDelta::seconds(1).as_seconds_f64(), 1.0);
817 assert_eq!(TimeDelta::seconds(-1).as_seconds_f64(), -1.0);
818 assert_eq!(TimeDelta::seconds(100).as_seconds_f64(), 100.0);
819 assert_eq!(TimeDelta::seconds(-100).as_seconds_f64(), -100.0);
820
821 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f64(), 0.5);
822 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f64(), -0.5);
823 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f64(), 1.5);
824 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f64(), -1.5);
825 }
826
827 #[test]
828 fn test_duration_as_seconds_f32() {
829 assert_eq!(TimeDelta::seconds(1).as_seconds_f32(), 1.0);
830 assert_eq!(TimeDelta::seconds(-1).as_seconds_f32(), -1.0);
831 assert_eq!(TimeDelta::seconds(100).as_seconds_f32(), 100.0);
832 assert_eq!(TimeDelta::seconds(-100).as_seconds_f32(), -100.0);
833
834 assert_eq!(TimeDelta::milliseconds(500).as_seconds_f32(), 0.5);
835 assert_eq!(TimeDelta::milliseconds(-500).as_seconds_f32(), -0.5);
836 assert_eq!(TimeDelta::milliseconds(1_500).as_seconds_f32(), 1.5);
837 assert_eq!(TimeDelta::milliseconds(-1_500).as_seconds_f32(), -1.5);
838 }
839
840 #[test]
841 fn test_duration_subsec_nanos() {
842 assert_eq!(TimeDelta::zero().subsec_nanos(), 0);
843 assert_eq!(TimeDelta::nanoseconds(1).subsec_nanos(), 1);
844 assert_eq!(TimeDelta::nanoseconds(-1).subsec_nanos(), -1);
845 assert_eq!(TimeDelta::seconds(1).subsec_nanos(), 0);
846 assert_eq!(TimeDelta::nanoseconds(1_000_000_001).subsec_nanos(), 1);
847 }
848
849 #[test]
850 fn test_duration_subsec_micros() {
851 assert_eq!(TimeDelta::zero().subsec_micros(), 0);
852 assert_eq!(TimeDelta::microseconds(1).subsec_micros(), 1);
853 assert_eq!(TimeDelta::microseconds(-1).subsec_micros(), -1);
854 assert_eq!(TimeDelta::seconds(1).subsec_micros(), 0);
855 assert_eq!(TimeDelta::microseconds(1_000_001).subsec_micros(), 1);
856 assert_eq!(TimeDelta::nanoseconds(1_000_001_999).subsec_micros(), 1);
857 }
858
859 #[test]
860 fn test_duration_subsec_millis() {
861 assert_eq!(TimeDelta::zero().subsec_millis(), 0);
862 assert_eq!(TimeDelta::milliseconds(1).subsec_millis(), 1);
863 assert_eq!(TimeDelta::milliseconds(-1).subsec_millis(), -1);
864 assert_eq!(TimeDelta::seconds(1).subsec_millis(), 0);
865 assert_eq!(TimeDelta::milliseconds(1_001).subsec_millis(), 1);
866 assert_eq!(TimeDelta::microseconds(1_001_999).subsec_millis(), 1);
867 }
868
869 #[test]
870 fn test_duration_num_milliseconds() {
871 assert_eq!(TimeDelta::zero().num_milliseconds(), 0);
872 assert_eq!(TimeDelta::try_milliseconds(1).unwrap().num_milliseconds(), 1);
873 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().num_milliseconds(), -1);
874 assert_eq!(TimeDelta::microseconds(999).num_milliseconds(), 0);
875 assert_eq!(TimeDelta::microseconds(1001).num_milliseconds(), 1);
876 assert_eq!(TimeDelta::microseconds(-999).num_milliseconds(), 0);
877 assert_eq!(TimeDelta::microseconds(-1001).num_milliseconds(), -1);
878 }
879
880 #[test]
881 fn test_duration_milliseconds_max_allowed() {
882 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
885 assert_eq!(duration.num_milliseconds(), i64::MAX);
886 assert_eq!(
887 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
888 i64::MAX as i128 * 1_000_000
889 );
890 }
891
892 #[test]
893 fn test_duration_milliseconds_max_overflow() {
894 assert!(
897 TimeDelta::try_milliseconds(i64::MAX)
898 .unwrap()
899 .checked_add(&TimeDelta::try_milliseconds(1).unwrap())
900 .is_none()
901 );
902 }
903
904 #[test]
905 fn test_duration_milliseconds_min_allowed() {
906 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
910 assert_eq!(duration.num_milliseconds(), -i64::MAX);
911 assert_eq!(
912 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
913 -i64::MAX as i128 * 1_000_000
914 );
915 }
916
917 #[test]
918 fn test_duration_milliseconds_min_underflow() {
919 assert!(
922 TimeDelta::try_milliseconds(-i64::MAX)
923 .unwrap()
924 .checked_sub(&TimeDelta::try_milliseconds(1).unwrap())
925 .is_none()
926 );
927 }
928
929 #[test]
930 #[should_panic(expected = "TimeDelta::milliseconds out of bounds")]
931 fn test_duration_milliseconds_min_underflow_panic() {
932 let _ = TimeDelta::milliseconds(i64::MIN); }
938
939 #[test]
940 fn test_duration_num_microseconds() {
941 assert_eq!(TimeDelta::zero().num_microseconds(), Some(0));
942 assert_eq!(TimeDelta::microseconds(1).num_microseconds(), Some(1));
943 assert_eq!(TimeDelta::microseconds(-1).num_microseconds(), Some(-1));
944 assert_eq!(TimeDelta::nanoseconds(999).num_microseconds(), Some(0));
945 assert_eq!(TimeDelta::nanoseconds(1001).num_microseconds(), Some(1));
946 assert_eq!(TimeDelta::nanoseconds(-999).num_microseconds(), Some(0));
947 assert_eq!(TimeDelta::nanoseconds(-1001).num_microseconds(), Some(-1));
948
949 const MICROS_PER_DAY: i64 = 86_400_000_000;
951 assert_eq!(
952 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
953 Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
954 );
955 assert_eq!(
956 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY).unwrap().num_microseconds(),
957 Some(-i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)
958 );
959 assert_eq!(
960 TimeDelta::try_days(i64::MAX / MICROS_PER_DAY + 1).unwrap().num_microseconds(),
961 None
962 );
963 assert_eq!(
964 TimeDelta::try_days(-i64::MAX / MICROS_PER_DAY - 1).unwrap().num_microseconds(),
965 None
966 );
967 }
968 #[test]
969 fn test_duration_microseconds_max_allowed() {
970 let duration = TimeDelta::microseconds(i64::MAX);
974 assert_eq!(duration.num_microseconds(), Some(i64::MAX));
975 assert_eq!(
976 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
977 i64::MAX as i128 * 1_000
978 );
979 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
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_000_000
988 );
989 }
990 #[test]
991 fn test_duration_microseconds_max_overflow() {
992 let duration = TimeDelta::microseconds(i64::MAX) + TimeDelta::microseconds(1);
995 assert!(duration.num_microseconds().is_none());
996 assert_eq!(
997 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
998 (i64::MAX as i128 + 1) * 1_000
999 );
1000 assert!(
1003 TimeDelta::try_milliseconds(i64::MAX)
1004 .unwrap()
1005 .checked_add(&TimeDelta::microseconds(1))
1006 .is_none()
1007 );
1008 }
1009 #[test]
1010 fn test_duration_microseconds_min_allowed() {
1011 let duration = TimeDelta::microseconds(i64::MIN);
1015 assert_eq!(duration.num_microseconds(), Some(i64::MIN));
1016 assert_eq!(
1017 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1018 i64::MIN as i128 * 1_000
1019 );
1020 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
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::MAX as i128 * 1_000_000
1029 );
1030 }
1031 #[test]
1032 fn test_duration_microseconds_min_underflow() {
1033 let duration = TimeDelta::microseconds(i64::MIN) - TimeDelta::microseconds(1);
1036 assert!(duration.num_microseconds().is_none());
1037 assert_eq!(
1038 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1039 (i64::MIN as i128 - 1) * 1_000
1040 );
1041 assert!(
1044 TimeDelta::try_milliseconds(-i64::MAX)
1045 .unwrap()
1046 .checked_sub(&TimeDelta::microseconds(1))
1047 .is_none()
1048 );
1049 }
1050
1051 #[test]
1052 fn test_duration_num_nanoseconds() {
1053 assert_eq!(TimeDelta::zero().num_nanoseconds(), Some(0));
1054 assert_eq!(TimeDelta::nanoseconds(1).num_nanoseconds(), Some(1));
1055 assert_eq!(TimeDelta::nanoseconds(-1).num_nanoseconds(), Some(-1));
1056
1057 const NANOS_PER_DAY: i64 = 86_400_000_000_000;
1059 assert_eq!(
1060 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1061 Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1062 );
1063 assert_eq!(
1064 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY).unwrap().num_nanoseconds(),
1065 Some(-i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)
1066 );
1067 assert_eq!(
1068 TimeDelta::try_days(i64::MAX / NANOS_PER_DAY + 1).unwrap().num_nanoseconds(),
1069 None
1070 );
1071 assert_eq!(
1072 TimeDelta::try_days(-i64::MAX / NANOS_PER_DAY - 1).unwrap().num_nanoseconds(),
1073 None
1074 );
1075 }
1076 #[test]
1077 fn test_duration_nanoseconds_max_allowed() {
1078 let duration = TimeDelta::nanoseconds(i64::MAX);
1082 assert_eq!(duration.num_nanoseconds(), Some(i64::MAX));
1083 assert_eq!(
1084 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1085 i64::MAX as i128
1086 );
1087 let duration = TimeDelta::try_milliseconds(i64::MAX).unwrap();
1091 assert!(duration.num_nanoseconds().is_none());
1092 assert_eq!(
1093 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1094 i64::MAX as i128 * 1_000_000
1095 );
1096 }
1097
1098 #[test]
1099 fn test_duration_nanoseconds_max_overflow() {
1100 let duration = TimeDelta::nanoseconds(i64::MAX) + TimeDelta::nanoseconds(1);
1103 assert!(duration.num_nanoseconds().is_none());
1104 assert_eq!(
1105 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1106 i64::MAX as i128 + 1
1107 );
1108 assert!(
1111 TimeDelta::try_milliseconds(i64::MAX)
1112 .unwrap()
1113 .checked_add(&TimeDelta::nanoseconds(1))
1114 .is_none()
1115 );
1116 }
1117
1118 #[test]
1119 fn test_duration_nanoseconds_min_allowed() {
1120 let duration = TimeDelta::nanoseconds(i64::MIN);
1124 assert_eq!(duration.num_nanoseconds(), Some(i64::MIN));
1125 assert_eq!(
1126 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1127 i64::MIN as i128
1128 );
1129 let duration = TimeDelta::try_milliseconds(-i64::MAX).unwrap();
1133 assert!(duration.num_nanoseconds().is_none());
1134 assert_eq!(
1135 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1136 -i64::MAX as i128 * 1_000_000
1137 );
1138 }
1139
1140 #[test]
1141 fn test_duration_nanoseconds_min_underflow() {
1142 let duration = TimeDelta::nanoseconds(i64::MIN) - TimeDelta::nanoseconds(1);
1145 assert!(duration.num_nanoseconds().is_none());
1146 assert_eq!(
1147 duration.secs as i128 * 1_000_000_000 + duration.nanos as i128,
1148 i64::MIN as i128 - 1
1149 );
1150 assert!(
1153 TimeDelta::try_milliseconds(-i64::MAX)
1154 .unwrap()
1155 .checked_sub(&TimeDelta::nanoseconds(1))
1156 .is_none()
1157 );
1158 }
1159
1160 #[test]
1161 fn test_max() {
1162 assert_eq!(
1163 MAX.secs as i128 * 1_000_000_000 + MAX.nanos as i128,
1164 i64::MAX as i128 * 1_000_000
1165 );
1166 assert_eq!(MAX, TimeDelta::try_milliseconds(i64::MAX).unwrap());
1167 assert_eq!(MAX.num_milliseconds(), i64::MAX);
1168 assert_eq!(MAX.num_microseconds(), None);
1169 assert_eq!(MAX.num_nanoseconds(), None);
1170 }
1171
1172 #[test]
1173 fn test_min() {
1174 assert_eq!(
1175 MIN.secs as i128 * 1_000_000_000 + MIN.nanos as i128,
1176 -i64::MAX as i128 * 1_000_000
1177 );
1178 assert_eq!(MIN, TimeDelta::try_milliseconds(-i64::MAX).unwrap());
1179 assert_eq!(MIN.num_milliseconds(), -i64::MAX);
1180 assert_eq!(MIN.num_microseconds(), None);
1181 assert_eq!(MIN.num_nanoseconds(), None);
1182 }
1183
1184 #[test]
1185 fn test_duration_ord() {
1186 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1187
1188 assert!(milliseconds(1) < milliseconds(2));
1189 assert!(milliseconds(2) > milliseconds(1));
1190 assert!(milliseconds(-1) > milliseconds(-2));
1191 assert!(milliseconds(-2) < milliseconds(-1));
1192 assert!(milliseconds(-1) < milliseconds(1));
1193 assert!(milliseconds(1) > milliseconds(-1));
1194 assert!(milliseconds(0) < milliseconds(1));
1195 assert!(milliseconds(0) > milliseconds(-1));
1196 assert!(milliseconds(1_001) < milliseconds(1_002));
1197 assert!(milliseconds(-1_001) > milliseconds(-1_002));
1198 assert!(TimeDelta::nanoseconds(1_234_567_890) < TimeDelta::nanoseconds(1_234_567_891));
1199 assert!(TimeDelta::nanoseconds(-1_234_567_890) > TimeDelta::nanoseconds(-1_234_567_891));
1200 assert!(milliseconds(i64::MAX) > milliseconds(i64::MAX - 1));
1201 assert!(milliseconds(-i64::MAX) < milliseconds(-i64::MAX + 1));
1202 }
1203
1204 #[test]
1205 fn test_duration_checked_ops() {
1206 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1207 let seconds = |s| TimeDelta::try_seconds(s).unwrap();
1208
1209 assert_eq!(
1210 milliseconds(i64::MAX).checked_add(&milliseconds(0)),
1211 Some(milliseconds(i64::MAX))
1212 );
1213 assert_eq!(
1214 milliseconds(i64::MAX - 1).checked_add(&TimeDelta::microseconds(999)),
1215 Some(milliseconds(i64::MAX - 2) + TimeDelta::microseconds(1999))
1216 );
1217 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::microseconds(1000)).is_none());
1218 assert!(milliseconds(i64::MAX).checked_add(&TimeDelta::nanoseconds(1)).is_none());
1219
1220 assert_eq!(
1221 milliseconds(-i64::MAX).checked_sub(&milliseconds(0)),
1222 Some(milliseconds(-i64::MAX))
1223 );
1224 assert_eq!(
1225 milliseconds(-i64::MAX + 1).checked_sub(&TimeDelta::microseconds(999)),
1226 Some(milliseconds(-i64::MAX + 2) - TimeDelta::microseconds(1999))
1227 );
1228 assert!(milliseconds(-i64::MAX).checked_sub(&milliseconds(1)).is_none());
1229 assert!(milliseconds(-i64::MAX).checked_sub(&TimeDelta::nanoseconds(1)).is_none());
1230
1231 assert!(seconds(i64::MAX / 1000).checked_mul(2000).is_none());
1232 assert!(seconds(i64::MIN / 1000).checked_mul(2000).is_none());
1233 assert!(seconds(1).checked_div(0).is_none());
1234 }
1235
1236 #[test]
1237 fn test_duration_abs() {
1238 let milliseconds = |ms| TimeDelta::try_milliseconds(ms).unwrap();
1239
1240 assert_eq!(milliseconds(1300).abs(), milliseconds(1300));
1241 assert_eq!(milliseconds(1000).abs(), milliseconds(1000));
1242 assert_eq!(milliseconds(300).abs(), milliseconds(300));
1243 assert_eq!(milliseconds(0).abs(), milliseconds(0));
1244 assert_eq!(milliseconds(-300).abs(), milliseconds(300));
1245 assert_eq!(milliseconds(-700).abs(), milliseconds(700));
1246 assert_eq!(milliseconds(-1000).abs(), milliseconds(1000));
1247 assert_eq!(milliseconds(-1300).abs(), milliseconds(1300));
1248 assert_eq!(milliseconds(-1700).abs(), milliseconds(1700));
1249 assert_eq!(milliseconds(-i64::MAX).abs(), milliseconds(i64::MAX));
1250 }
1251
1252 #[test]
1253 #[allow(clippy::erasing_op)]
1254 fn test_duration_mul() {
1255 assert_eq!(TimeDelta::zero() * i32::MAX, TimeDelta::zero());
1256 assert_eq!(TimeDelta::zero() * i32::MIN, TimeDelta::zero());
1257 assert_eq!(TimeDelta::nanoseconds(1) * 0, TimeDelta::zero());
1258 assert_eq!(TimeDelta::nanoseconds(1) * 1, TimeDelta::nanoseconds(1));
1259 assert_eq!(TimeDelta::nanoseconds(1) * 1_000_000_000, TimeDelta::try_seconds(1).unwrap());
1260 assert_eq!(TimeDelta::nanoseconds(1) * -1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1261 assert_eq!(-TimeDelta::nanoseconds(1) * 1_000_000_000, -TimeDelta::try_seconds(1).unwrap());
1262 assert_eq!(
1263 TimeDelta::nanoseconds(30) * 333_333_333,
1264 TimeDelta::try_seconds(10).unwrap() - TimeDelta::nanoseconds(10)
1265 );
1266 assert_eq!(
1267 (TimeDelta::nanoseconds(1)
1268 + TimeDelta::try_seconds(1).unwrap()
1269 + TimeDelta::try_days(1).unwrap())
1270 * 3,
1271 TimeDelta::nanoseconds(3)
1272 + TimeDelta::try_seconds(3).unwrap()
1273 + TimeDelta::try_days(3).unwrap()
1274 );
1275 assert_eq!(
1276 TimeDelta::try_milliseconds(1500).unwrap() * -2,
1277 TimeDelta::try_seconds(-3).unwrap()
1278 );
1279 assert_eq!(
1280 TimeDelta::try_milliseconds(-1500).unwrap() * 2,
1281 TimeDelta::try_seconds(-3).unwrap()
1282 );
1283 }
1284
1285 #[test]
1286 fn test_duration_div() {
1287 assert_eq!(TimeDelta::zero() / i32::MAX, TimeDelta::zero());
1288 assert_eq!(TimeDelta::zero() / i32::MIN, TimeDelta::zero());
1289 assert_eq!(TimeDelta::nanoseconds(123_456_789) / 1, TimeDelta::nanoseconds(123_456_789));
1290 assert_eq!(TimeDelta::nanoseconds(123_456_789) / -1, -TimeDelta::nanoseconds(123_456_789));
1291 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / -1, TimeDelta::nanoseconds(123_456_789));
1292 assert_eq!(-TimeDelta::nanoseconds(123_456_789) / 1, -TimeDelta::nanoseconds(123_456_789));
1293 assert_eq!(TimeDelta::try_seconds(1).unwrap() / 3, TimeDelta::nanoseconds(333_333_333));
1294 assert_eq!(TimeDelta::try_seconds(4).unwrap() / 3, TimeDelta::nanoseconds(1_333_333_333));
1295 assert_eq!(
1296 TimeDelta::try_seconds(-1).unwrap() / 2,
1297 TimeDelta::try_milliseconds(-500).unwrap()
1298 );
1299 assert_eq!(
1300 TimeDelta::try_seconds(1).unwrap() / -2,
1301 TimeDelta::try_milliseconds(-500).unwrap()
1302 );
1303 assert_eq!(
1304 TimeDelta::try_seconds(-1).unwrap() / -2,
1305 TimeDelta::try_milliseconds(500).unwrap()
1306 );
1307 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / 3, TimeDelta::nanoseconds(-1_333_333_333));
1308 assert_eq!(TimeDelta::try_seconds(-4).unwrap() / -3, TimeDelta::nanoseconds(1_333_333_333));
1309 }
1310
1311 #[test]
1312 fn test_duration_sum() {
1313 let duration_list_1 = [TimeDelta::zero(), TimeDelta::try_seconds(1).unwrap()];
1314 let sum_1: TimeDelta = duration_list_1.iter().sum();
1315 assert_eq!(sum_1, TimeDelta::try_seconds(1).unwrap());
1316
1317 let duration_list_2 = [
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_2: TimeDelta = duration_list_2.iter().sum();
1324 assert_eq!(sum_2, TimeDelta::try_seconds(17).unwrap());
1325
1326 let duration_arr = [
1327 TimeDelta::zero(),
1328 TimeDelta::try_seconds(1).unwrap(),
1329 TimeDelta::try_seconds(6).unwrap(),
1330 TimeDelta::try_seconds(10).unwrap(),
1331 ];
1332 let sum_3: TimeDelta = duration_arr.into_iter().sum();
1333 assert_eq!(sum_3, TimeDelta::try_seconds(17).unwrap());
1334 }
1335
1336 #[test]
1337 fn test_duration_fmt() {
1338 assert_eq!(TimeDelta::zero().to_string(), "P0D");
1339 assert_eq!(TimeDelta::try_days(42).unwrap().to_string(), "PT3628800S");
1340 assert_eq!(TimeDelta::try_days(-42).unwrap().to_string(), "-PT3628800S");
1341 assert_eq!(TimeDelta::try_seconds(42).unwrap().to_string(), "PT42S");
1342 assert_eq!(TimeDelta::try_milliseconds(42).unwrap().to_string(), "PT0.042S");
1343 assert_eq!(TimeDelta::microseconds(42).to_string(), "PT0.000042S");
1344 assert_eq!(TimeDelta::nanoseconds(42).to_string(), "PT0.000000042S");
1345 assert_eq!(
1346 (TimeDelta::try_days(7).unwrap() + TimeDelta::try_milliseconds(6543).unwrap())
1347 .to_string(),
1348 "PT604806.543S"
1349 );
1350 assert_eq!(TimeDelta::try_seconds(-86_401).unwrap().to_string(), "-PT86401S");
1351 assert_eq!(TimeDelta::nanoseconds(-1).to_string(), "-PT0.000000001S");
1352
1353 assert_eq!(
1355 format!(
1356 "{:30}",
1357 TimeDelta::try_days(1).unwrap() + TimeDelta::try_milliseconds(2345).unwrap()
1358 ),
1359 "PT86402.345S"
1360 );
1361 }
1362
1363 #[test]
1364 fn test_to_std() {
1365 assert_eq!(TimeDelta::try_seconds(1).unwrap().to_std(), Ok(Duration::new(1, 0)));
1366 assert_eq!(TimeDelta::try_seconds(86_401).unwrap().to_std(), Ok(Duration::new(86_401, 0)));
1367 assert_eq!(
1368 TimeDelta::try_milliseconds(123).unwrap().to_std(),
1369 Ok(Duration::new(0, 123_000_000))
1370 );
1371 assert_eq!(
1372 TimeDelta::try_milliseconds(123_765).unwrap().to_std(),
1373 Ok(Duration::new(123, 765_000_000))
1374 );
1375 assert_eq!(TimeDelta::nanoseconds(777).to_std(), Ok(Duration::new(0, 777)));
1376 assert_eq!(MAX.to_std(), Ok(Duration::new(9_223_372_036_854_775, 807_000_000)));
1377 assert_eq!(TimeDelta::try_seconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1378 assert_eq!(TimeDelta::try_milliseconds(-1).unwrap().to_std(), Err(OutOfRangeError(())));
1379 }
1380
1381 #[test]
1382 fn test_from_std() {
1383 assert_eq!(
1384 Ok(TimeDelta::try_seconds(1).unwrap()),
1385 TimeDelta::from_std(Duration::new(1, 0))
1386 );
1387 assert_eq!(
1388 Ok(TimeDelta::try_seconds(86_401).unwrap()),
1389 TimeDelta::from_std(Duration::new(86_401, 0))
1390 );
1391 assert_eq!(
1392 Ok(TimeDelta::try_milliseconds(123).unwrap()),
1393 TimeDelta::from_std(Duration::new(0, 123_000_000))
1394 );
1395 assert_eq!(
1396 Ok(TimeDelta::try_milliseconds(123_765).unwrap()),
1397 TimeDelta::from_std(Duration::new(123, 765_000_000))
1398 );
1399 assert_eq!(Ok(TimeDelta::nanoseconds(777)), TimeDelta::from_std(Duration::new(0, 777)));
1400 assert_eq!(Ok(MAX), TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_000)));
1401 assert_eq!(
1402 TimeDelta::from_std(Duration::new(9_223_372_036_854_776, 0)),
1403 Err(OutOfRangeError(()))
1404 );
1405 assert_eq!(
1406 TimeDelta::from_std(Duration::new(9_223_372_036_854_775, 807_000_001)),
1407 Err(OutOfRangeError(()))
1408 );
1409 }
1410
1411 #[test]
1412 fn test_duration_const() {
1413 const ONE_WEEK: TimeDelta = expect(TimeDelta::try_weeks(1), "");
1414 const ONE_DAY: TimeDelta = expect(TimeDelta::try_days(1), "");
1415 const ONE_HOUR: TimeDelta = expect(TimeDelta::try_hours(1), "");
1416 const ONE_MINUTE: TimeDelta = expect(TimeDelta::try_minutes(1), "");
1417 const ONE_SECOND: TimeDelta = expect(TimeDelta::try_seconds(1), "");
1418 const ONE_MILLI: TimeDelta = expect(TimeDelta::try_milliseconds(1), "");
1419 const ONE_MICRO: TimeDelta = TimeDelta::microseconds(1);
1420 const ONE_NANO: TimeDelta = TimeDelta::nanoseconds(1);
1421 let combo: TimeDelta = ONE_WEEK
1422 + ONE_DAY
1423 + ONE_HOUR
1424 + ONE_MINUTE
1425 + ONE_SECOND
1426 + ONE_MILLI
1427 + ONE_MICRO
1428 + ONE_NANO;
1429
1430 assert!(ONE_WEEK != TimeDelta::zero());
1431 assert!(ONE_DAY != TimeDelta::zero());
1432 assert!(ONE_HOUR != TimeDelta::zero());
1433 assert!(ONE_MINUTE != TimeDelta::zero());
1434 assert!(ONE_SECOND != TimeDelta::zero());
1435 assert!(ONE_MILLI != TimeDelta::zero());
1436 assert!(ONE_MICRO != TimeDelta::zero());
1437 assert!(ONE_NANO != TimeDelta::zero());
1438 assert_eq!(
1439 combo,
1440 TimeDelta::try_seconds(86400 * 7 + 86400 + 3600 + 60 + 1).unwrap()
1441 + TimeDelta::nanoseconds(1 + 1_000 + 1_000_000)
1442 );
1443 }
1444
1445 #[test]
1446 #[cfg(feature = "rkyv-validation")]
1447 fn test_rkyv_validation() {
1448 let duration = TimeDelta::try_seconds(1).unwrap();
1449 let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
1450 assert_eq!(rkyv::from_bytes::<TimeDelta>(&bytes).unwrap(), duration);
1451 }
1452}