1use core::{
8 ops::{Add, AddAssign, Sub, SubAssign},
9 time::Duration,
10};
11#[cfg(feature = "std")]
12use std::time::SystemTime;
13
14#[cfg(feature = "chrono")]
15use chrono::{DateTime, TimeDelta, Utc};
16#[cfg(feature = "jiff")]
17use jiff::{Span, Timestamp};
18use time::UtcDateTime;
19
20use super::{FILE_TIMES_PER_SEC, FileTime};
21
22impl FileTime {
23 pub fn checked_add(self, rhs: Duration) -> Option<Self> {
50 let duration = u64::try_from(rhs.as_nanos() / 100).ok()?;
51 self.to_raw().checked_add(duration).map(Self::new)
52 }
53
54 pub fn checked_sub(self, rhs: Duration) -> Option<Self> {
85 let duration = u64::try_from(rhs.as_nanos() / 100).ok()?;
86 self.to_raw().checked_sub(duration).map(Self::new)
87 }
88
89 #[must_use]
119 pub fn saturating_add(self, rhs: Duration) -> Self {
120 self.checked_add(rhs).unwrap_or(Self::MAX)
121 }
122
123 #[must_use]
154 pub fn saturating_sub(self, rhs: Duration) -> Self {
155 self.checked_sub(rhs).unwrap_or_default()
156 }
157}
158
159impl Add<Duration> for FileTime {
160 type Output = Self;
161
162 fn add(self, rhs: Duration) -> Self::Output {
163 self.checked_add(rhs)
164 .expect("overflow when adding duration to date and time")
165 }
166}
167
168impl Add<time::Duration> for FileTime {
169 type Output = Self;
170
171 fn add(self, rhs: time::Duration) -> Self::Output {
172 if rhs.is_positive() {
173 self + rhs.unsigned_abs()
174 } else {
175 self - rhs.unsigned_abs()
176 }
177 }
178}
179
180#[cfg(feature = "chrono")]
181impl Add<TimeDelta> for FileTime {
182 type Output = Self;
183
184 fn add(self, rhs: TimeDelta) -> Self::Output {
185 if rhs > TimeDelta::zero() {
186 self + rhs.abs().to_std().expect("duration is less than zero")
187 } else {
188 self - rhs.abs().to_std().expect("duration is less than zero")
189 }
190 }
191}
192
193#[cfg(feature = "jiff")]
194impl Add<Span> for FileTime {
195 type Output = Self;
196
197 fn add(self, rhs: Span) -> Self::Output {
198 if rhs.is_positive() {
199 self + Duration::try_from(rhs.abs()).expect("duration is less than zero")
200 } else {
201 self - Duration::try_from(rhs.abs()).expect("duration is less than zero")
202 }
203 }
204}
205
206impl AddAssign<Duration> for FileTime {
207 fn add_assign(&mut self, rhs: Duration) {
208 *self = *self + rhs;
209 }
210}
211
212impl AddAssign<time::Duration> for FileTime {
213 fn add_assign(&mut self, rhs: time::Duration) {
214 *self = *self + rhs;
215 }
216}
217
218#[cfg(feature = "chrono")]
219impl AddAssign<TimeDelta> for FileTime {
220 fn add_assign(&mut self, rhs: TimeDelta) {
221 *self = *self + rhs;
222 }
223}
224
225#[cfg(feature = "jiff")]
226impl AddAssign<Span> for FileTime {
227 fn add_assign(&mut self, rhs: Span) {
228 *self = *self + rhs;
229 }
230}
231
232impl Sub for FileTime {
233 type Output = Duration;
234
235 fn sub(self, rhs: Self) -> Self::Output {
236 let duration = self.to_raw() - rhs.to_raw();
237 Self::Output::new(
238 duration / FILE_TIMES_PER_SEC,
239 u32::try_from((duration % FILE_TIMES_PER_SEC) * 100)
240 .expect("the number of nanoseconds should be in the range of `u32`"),
241 )
242 }
243}
244
245impl Sub<Duration> for FileTime {
246 type Output = Self;
247
248 fn sub(self, rhs: Duration) -> Self::Output {
249 self.checked_sub(rhs)
250 .expect("overflow when subtracting duration from date and time")
251 }
252}
253
254impl Sub<time::Duration> for FileTime {
255 type Output = Self;
256
257 fn sub(self, rhs: time::Duration) -> Self::Output {
258 if rhs.is_positive() {
259 self - rhs.unsigned_abs()
260 } else {
261 self + rhs.unsigned_abs()
262 }
263 }
264}
265
266#[cfg(feature = "chrono")]
267impl Sub<TimeDelta> for FileTime {
268 type Output = Self;
269
270 fn sub(self, rhs: TimeDelta) -> Self::Output {
271 if rhs > TimeDelta::zero() {
272 self - rhs.abs().to_std().expect("duration is less than zero")
273 } else {
274 self + rhs.abs().to_std().expect("duration is less than zero")
275 }
276 }
277}
278
279#[cfg(feature = "jiff")]
280impl Sub<Span> for FileTime {
281 type Output = Self;
282
283 fn sub(self, rhs: Span) -> Self::Output {
284 if rhs.is_positive() {
285 self - Duration::try_from(rhs.abs()).expect("duration is less than zero")
286 } else {
287 self + Duration::try_from(rhs.abs()).expect("duration is less than zero")
288 }
289 }
290}
291
292#[cfg(feature = "std")]
293impl Sub<FileTime> for SystemTime {
294 type Output = Duration;
295
296 fn sub(self, rhs: FileTime) -> Self::Output {
297 self.duration_since(rhs.into())
298 .expect("RHS provided is later than LHS")
299 }
300}
301
302#[cfg(feature = "std")]
303impl Sub<SystemTime> for FileTime {
304 type Output = Duration;
305
306 fn sub(self, rhs: SystemTime) -> Self::Output {
307 SystemTime::from(self)
308 .duration_since(rhs)
309 .expect("RHS provided is later than LHS")
310 }
311}
312
313impl Sub<FileTime> for UtcDateTime {
314 type Output = time::Duration;
315
316 fn sub(self, rhs: FileTime) -> Self::Output {
317 self - Self::try_from(rhs).expect("RHS is out of range for `UtcDateTime`")
318 }
319}
320
321impl Sub<UtcDateTime> for FileTime {
322 type Output = time::Duration;
323
324 fn sub(self, rhs: UtcDateTime) -> Self::Output {
325 UtcDateTime::try_from(self).expect("LHS is out of range for `UtcDateTime`") - rhs
326 }
327}
328
329#[cfg(feature = "chrono")]
330impl Sub<FileTime> for DateTime<Utc> {
331 type Output = TimeDelta;
332
333 fn sub(self, rhs: FileTime) -> Self::Output {
334 self - Self::from(rhs)
335 }
336}
337
338#[cfg(feature = "chrono")]
339impl Sub<DateTime<Utc>> for FileTime {
340 type Output = TimeDelta;
341
342 fn sub(self, rhs: DateTime<Utc>) -> Self::Output {
343 DateTime::<Utc>::from(self) - rhs
344 }
345}
346
347#[cfg(feature = "jiff")]
348impl Sub<FileTime> for Timestamp {
349 type Output = Span;
350
351 fn sub(self, rhs: FileTime) -> Self::Output {
352 self - Self::try_from(rhs).expect("RHS is out of range for `Timestamp`")
353 }
354}
355
356#[cfg(feature = "jiff")]
357impl Sub<Timestamp> for FileTime {
358 type Output = Span;
359
360 fn sub(self, rhs: Timestamp) -> Self::Output {
361 Timestamp::try_from(self).expect("LHS is out of range for `Timestamp`") - rhs
362 }
363}
364
365impl SubAssign<Duration> for FileTime {
366 fn sub_assign(&mut self, rhs: Duration) {
367 *self = *self - rhs;
368 }
369}
370
371impl SubAssign<time::Duration> for FileTime {
372 fn sub_assign(&mut self, rhs: time::Duration) {
373 *self = *self - rhs;
374 }
375}
376
377#[cfg(feature = "chrono")]
378impl SubAssign<TimeDelta> for FileTime {
379 fn sub_assign(&mut self, rhs: TimeDelta) {
380 *self = *self - rhs;
381 }
382}
383
384#[cfg(feature = "jiff")]
385impl SubAssign<Span> for FileTime {
386 fn sub_assign(&mut self, rhs: Span) {
387 *self = *self - rhs;
388 }
389}
390
391#[cfg(test)]
392mod tests {
393 #[cfg(feature = "jiff")]
394 use jiff::ToSpan;
395 #[cfg(feature = "std")]
396 use proptest::{prop_assert, prop_assert_eq, prop_assert_ne};
397 #[cfg(feature = "std")]
398 use test_strategy::proptest;
399 use time::macros::utc_datetime;
400
401 use super::*;
402
403 #[test]
404 fn checked_add() {
405 assert_eq!(
406 FileTime::NT_TIME_EPOCH.checked_add(Duration::ZERO),
407 Some(FileTime::NT_TIME_EPOCH)
408 );
409 assert_eq!(
410 FileTime::NT_TIME_EPOCH.checked_add(Duration::from_nanos(1)),
411 Some(FileTime::NT_TIME_EPOCH)
412 );
413 assert_eq!(
414 FileTime::NT_TIME_EPOCH.checked_add(Duration::from_nanos(99)),
415 Some(FileTime::NT_TIME_EPOCH)
416 );
417 assert_eq!(
418 FileTime::NT_TIME_EPOCH.checked_add(Duration::from_nanos(100)),
419 Some(FileTime::new(1))
420 );
421
422 assert_eq!(
423 FileTime::MAX.checked_add(Duration::ZERO),
424 Some(FileTime::MAX)
425 );
426 assert_eq!(
427 FileTime::MAX.checked_add(Duration::from_nanos(1)),
428 Some(FileTime::MAX)
429 );
430 assert_eq!(
431 FileTime::MAX.checked_add(Duration::from_nanos(99)),
432 Some(FileTime::MAX)
433 );
434 assert_eq!(FileTime::MAX.checked_add(Duration::from_nanos(100)), None);
435 }
436
437 #[cfg(feature = "std")]
438 #[proptest]
439 fn checked_add_roundtrip(dur: Duration) {
440 if dur <= Duration::new(1_844_674_407_370, 955_161_500) {
441 prop_assert!(FileTime::NT_TIME_EPOCH.checked_add(dur).is_some());
442 } else {
443 prop_assert!(FileTime::NT_TIME_EPOCH.checked_add(dur).is_none());
444 }
445 }
446
447 #[test]
448 fn checked_sub() {
449 assert_eq!(
450 FileTime::MAX.checked_sub(Duration::ZERO),
451 Some(FileTime::MAX)
452 );
453 assert_eq!(
454 FileTime::MAX.checked_sub(Duration::from_nanos(1)),
455 Some(FileTime::MAX)
456 );
457 assert_eq!(
458 FileTime::MAX.checked_sub(Duration::from_nanos(99)),
459 Some(FileTime::MAX)
460 );
461 assert_eq!(
462 FileTime::MAX.checked_sub(Duration::from_nanos(100)),
463 Some(FileTime::new(u64::MAX - 1))
464 );
465
466 assert_eq!(
467 FileTime::NT_TIME_EPOCH.checked_sub(Duration::ZERO),
468 Some(FileTime::NT_TIME_EPOCH)
469 );
470 assert_eq!(
471 FileTime::NT_TIME_EPOCH.checked_sub(Duration::from_nanos(1)),
472 Some(FileTime::NT_TIME_EPOCH)
473 );
474 assert_eq!(
475 FileTime::NT_TIME_EPOCH.checked_sub(Duration::from_nanos(99)),
476 Some(FileTime::NT_TIME_EPOCH)
477 );
478 assert_eq!(
479 FileTime::NT_TIME_EPOCH.checked_sub(Duration::from_nanos(100)),
480 None
481 );
482 }
483
484 #[cfg(feature = "std")]
485 #[proptest]
486 fn checked_sub_roundtrip(dur: Duration) {
487 if dur <= Duration::new(1_844_674_407_370, 955_161_500) {
488 prop_assert!(FileTime::MAX.checked_sub(dur).is_some());
489 } else {
490 prop_assert!(FileTime::MAX.checked_sub(dur).is_none());
491 }
492 }
493
494 #[test]
495 fn saturating_add() {
496 assert_eq!(
497 FileTime::NT_TIME_EPOCH.saturating_add(Duration::ZERO),
498 FileTime::NT_TIME_EPOCH
499 );
500 assert_eq!(
501 FileTime::NT_TIME_EPOCH.saturating_add(Duration::from_nanos(1)),
502 FileTime::NT_TIME_EPOCH
503 );
504 assert_eq!(
505 FileTime::NT_TIME_EPOCH.saturating_add(Duration::from_nanos(99)),
506 FileTime::NT_TIME_EPOCH
507 );
508 assert_eq!(
509 FileTime::NT_TIME_EPOCH.saturating_add(Duration::from_nanos(100)),
510 FileTime::new(1)
511 );
512
513 assert_eq!(FileTime::MAX.saturating_add(Duration::ZERO), FileTime::MAX);
514 assert_eq!(
515 FileTime::MAX.saturating_add(Duration::from_nanos(1)),
516 FileTime::MAX
517 );
518 assert_eq!(
519 FileTime::MAX.saturating_add(Duration::from_nanos(99)),
520 FileTime::MAX
521 );
522 assert_eq!(
523 FileTime::MAX.saturating_add(Duration::from_nanos(100)),
524 FileTime::MAX
525 );
526 }
527
528 #[cfg(feature = "std")]
529 #[proptest]
530 fn saturating_add_roundtrip(dur: Duration) {
531 if dur <= Duration::new(1_844_674_407_370, 955_161_400) {
532 prop_assert_ne!(FileTime::NT_TIME_EPOCH.saturating_add(dur), FileTime::MAX);
533 } else {
534 prop_assert_eq!(FileTime::NT_TIME_EPOCH.saturating_add(dur), FileTime::MAX);
535 }
536 }
537
538 #[test]
539 fn saturating_sub() {
540 assert_eq!(FileTime::MAX.saturating_sub(Duration::ZERO), FileTime::MAX);
541 assert_eq!(
542 FileTime::MAX.saturating_sub(Duration::from_nanos(1)),
543 FileTime::MAX
544 );
545 assert_eq!(
546 FileTime::MAX.saturating_sub(Duration::from_nanos(99)),
547 FileTime::MAX
548 );
549 assert_eq!(
550 FileTime::MAX.saturating_sub(Duration::from_nanos(100)),
551 FileTime::new(u64::MAX - 1)
552 );
553
554 assert_eq!(
555 FileTime::NT_TIME_EPOCH.saturating_sub(Duration::ZERO),
556 FileTime::NT_TIME_EPOCH
557 );
558 assert_eq!(
559 FileTime::NT_TIME_EPOCH.saturating_sub(Duration::from_nanos(1)),
560 FileTime::NT_TIME_EPOCH
561 );
562 assert_eq!(
563 FileTime::NT_TIME_EPOCH.saturating_sub(Duration::from_nanos(99)),
564 FileTime::NT_TIME_EPOCH
565 );
566 assert_eq!(
567 FileTime::NT_TIME_EPOCH.saturating_sub(Duration::from_nanos(100)),
568 FileTime::NT_TIME_EPOCH
569 );
570 }
571
572 #[cfg(feature = "std")]
573 #[proptest]
574 fn saturating_sub_roundtrip(dur: Duration) {
575 if dur <= Duration::new(1_844_674_407_370, 955_161_400) {
576 prop_assert_ne!(FileTime::MAX.saturating_sub(dur), FileTime::NT_TIME_EPOCH);
577 } else {
578 prop_assert_eq!(FileTime::MAX.saturating_sub(dur), FileTime::NT_TIME_EPOCH);
579 }
580 }
581
582 #[test]
583 fn add_std_duration() {
584 assert_eq!(
585 FileTime::NT_TIME_EPOCH + Duration::ZERO,
586 FileTime::NT_TIME_EPOCH
587 );
588 assert_eq!(
589 FileTime::NT_TIME_EPOCH + Duration::from_nanos(1),
590 FileTime::NT_TIME_EPOCH
591 );
592 assert_eq!(
593 FileTime::NT_TIME_EPOCH + Duration::from_nanos(99),
594 FileTime::NT_TIME_EPOCH
595 );
596 assert_eq!(
597 FileTime::NT_TIME_EPOCH + Duration::from_nanos(100),
598 FileTime::new(1)
599 );
600
601 assert_eq!(FileTime::MAX + Duration::ZERO, FileTime::MAX);
602 assert_eq!(FileTime::MAX + Duration::from_nanos(1), FileTime::MAX);
603 assert_eq!(FileTime::MAX + Duration::from_nanos(99), FileTime::MAX);
604 }
605
606 #[test]
607 #[should_panic(expected = "overflow when adding duration to date and time")]
608 fn add_std_duration_with_overflow() {
609 let _ = FileTime::MAX + Duration::from_nanos(100);
610 }
611
612 #[test]
613 fn add_positive_time_duration() {
614 assert_eq!(
615 FileTime::NT_TIME_EPOCH + time::Duration::ZERO,
616 FileTime::NT_TIME_EPOCH
617 );
618 assert_eq!(
619 FileTime::NT_TIME_EPOCH + time::Duration::NANOSECOND,
620 FileTime::NT_TIME_EPOCH
621 );
622 assert_eq!(
623 FileTime::NT_TIME_EPOCH + time::Duration::nanoseconds(99),
624 FileTime::NT_TIME_EPOCH
625 );
626 assert_eq!(
627 FileTime::NT_TIME_EPOCH + time::Duration::nanoseconds(100),
628 FileTime::new(1)
629 );
630
631 assert_eq!(FileTime::MAX + time::Duration::ZERO, FileTime::MAX);
632 assert_eq!(FileTime::MAX + time::Duration::NANOSECOND, FileTime::MAX);
633 assert_eq!(
634 FileTime::MAX + time::Duration::nanoseconds(99),
635 FileTime::MAX
636 );
637 }
638
639 #[test]
640 #[should_panic(expected = "overflow when adding duration to date and time")]
641 fn add_positive_time_duration_with_overflow() {
642 let _ = FileTime::MAX + time::Duration::nanoseconds(100);
643 }
644
645 #[test]
646 fn add_negative_time_duration() {
647 assert_eq!(FileTime::MAX + -time::Duration::ZERO, FileTime::MAX);
648 assert_eq!(FileTime::MAX + -time::Duration::NANOSECOND, FileTime::MAX);
649 assert_eq!(
650 FileTime::MAX + -time::Duration::nanoseconds(99),
651 FileTime::MAX
652 );
653 assert_eq!(
654 FileTime::MAX + -time::Duration::nanoseconds(100),
655 FileTime::new(u64::MAX - 1)
656 );
657
658 assert_eq!(
659 FileTime::NT_TIME_EPOCH + -time::Duration::ZERO,
660 FileTime::NT_TIME_EPOCH
661 );
662 assert_eq!(
663 FileTime::NT_TIME_EPOCH + -time::Duration::NANOSECOND,
664 FileTime::NT_TIME_EPOCH
665 );
666 assert_eq!(
667 FileTime::NT_TIME_EPOCH + -time::Duration::nanoseconds(99),
668 FileTime::NT_TIME_EPOCH
669 );
670 }
671
672 #[test]
673 #[should_panic(expected = "overflow when subtracting duration from date and time")]
674 fn add_negative_time_duration_with_overflow() {
675 let _ = FileTime::NT_TIME_EPOCH + -time::Duration::nanoseconds(100);
676 }
677
678 #[cfg(feature = "chrono")]
679 #[test]
680 fn add_positive_chrono_time_delta() {
681 assert_eq!(
682 FileTime::NT_TIME_EPOCH + TimeDelta::zero(),
683 FileTime::NT_TIME_EPOCH
684 );
685 assert_eq!(
686 FileTime::NT_TIME_EPOCH + TimeDelta::nanoseconds(1),
687 FileTime::NT_TIME_EPOCH
688 );
689 assert_eq!(
690 FileTime::NT_TIME_EPOCH + TimeDelta::nanoseconds(99),
691 FileTime::NT_TIME_EPOCH
692 );
693 assert_eq!(
694 FileTime::NT_TIME_EPOCH + TimeDelta::nanoseconds(100),
695 FileTime::new(1)
696 );
697
698 assert_eq!(FileTime::MAX + TimeDelta::zero(), FileTime::MAX);
699 assert_eq!(FileTime::MAX + TimeDelta::nanoseconds(1), FileTime::MAX);
700 assert_eq!(FileTime::MAX + TimeDelta::nanoseconds(99), FileTime::MAX);
701 }
702
703 #[cfg(feature = "chrono")]
704 #[test]
705 #[should_panic(expected = "overflow when adding duration to date and time")]
706 fn add_positive_chrono_time_delta_with_overflow() {
707 let _ = FileTime::MAX + TimeDelta::nanoseconds(100);
708 }
709
710 #[cfg(feature = "chrono")]
711 #[test]
712 fn add_negative_chrono_time_delta() {
713 assert_eq!(FileTime::MAX + -TimeDelta::zero(), FileTime::MAX);
714 assert_eq!(FileTime::MAX + -TimeDelta::nanoseconds(1), FileTime::MAX);
715 assert_eq!(FileTime::MAX + -TimeDelta::nanoseconds(99), FileTime::MAX);
716 assert_eq!(
717 FileTime::MAX + -TimeDelta::nanoseconds(100),
718 FileTime::new(u64::MAX - 1)
719 );
720
721 assert_eq!(
722 FileTime::NT_TIME_EPOCH + -TimeDelta::zero(),
723 FileTime::NT_TIME_EPOCH
724 );
725 assert_eq!(
726 FileTime::NT_TIME_EPOCH + -TimeDelta::nanoseconds(1),
727 FileTime::NT_TIME_EPOCH
728 );
729 assert_eq!(
730 FileTime::NT_TIME_EPOCH + -TimeDelta::nanoseconds(99),
731 FileTime::NT_TIME_EPOCH
732 );
733 }
734
735 #[cfg(feature = "chrono")]
736 #[test]
737 #[should_panic(expected = "overflow when subtracting duration from date and time")]
738 fn add_negative_chrono_time_delta_with_overflow() {
739 let _ = FileTime::NT_TIME_EPOCH + -TimeDelta::nanoseconds(100);
740 }
741
742 #[cfg(feature = "jiff")]
743 #[test]
744 fn add_positive_jiff_span() {
745 assert_eq!(
746 FileTime::NT_TIME_EPOCH + Span::new(),
747 FileTime::NT_TIME_EPOCH
748 );
749 assert_eq!(
750 FileTime::NT_TIME_EPOCH + 1.nanosecond(),
751 FileTime::NT_TIME_EPOCH
752 );
753 assert_eq!(
754 FileTime::NT_TIME_EPOCH + 99.nanoseconds(),
755 FileTime::NT_TIME_EPOCH
756 );
757 assert_eq!(
758 FileTime::NT_TIME_EPOCH + 100.nanoseconds(),
759 FileTime::new(1)
760 );
761
762 assert_eq!(FileTime::MAX + Span::new(), FileTime::MAX);
763 assert_eq!(FileTime::MAX + 1.nanosecond(), FileTime::MAX);
764 assert_eq!(FileTime::MAX + 99.nanoseconds(), FileTime::MAX);
765 }
766
767 #[cfg(feature = "jiff")]
768 #[test]
769 #[should_panic(expected = "overflow when adding duration to date and time")]
770 fn add_positive_jiff_span_with_overflow() {
771 let _ = FileTime::MAX + 100.nanoseconds();
772 }
773
774 #[cfg(feature = "jiff")]
775 #[test]
776 fn add_negative_jiff_span() {
777 assert_eq!(FileTime::MAX + -Span::new(), FileTime::MAX);
778 assert_eq!(FileTime::MAX + -(1.nanosecond()), FileTime::MAX);
779 assert_eq!(FileTime::MAX + -(99.nanoseconds()), FileTime::MAX);
780 assert_eq!(
781 FileTime::MAX + -(100.nanoseconds()),
782 FileTime::new(u64::MAX - 1)
783 );
784
785 assert_eq!(
786 FileTime::NT_TIME_EPOCH + -Span::new(),
787 FileTime::NT_TIME_EPOCH
788 );
789 assert_eq!(
790 FileTime::NT_TIME_EPOCH + -(1.nanosecond()),
791 FileTime::NT_TIME_EPOCH
792 );
793 assert_eq!(
794 FileTime::NT_TIME_EPOCH + -(99.nanoseconds()),
795 FileTime::NT_TIME_EPOCH
796 );
797 }
798
799 #[cfg(feature = "jiff")]
800 #[test]
801 #[should_panic(expected = "overflow when subtracting duration from date and time")]
802 fn add_negative_jiff_span_with_overflow() {
803 let _ = FileTime::NT_TIME_EPOCH + -(100.nanoseconds());
804 }
805
806 #[test]
807 fn add_assign_std_duration() {
808 {
809 let mut ft = FileTime::NT_TIME_EPOCH;
810 ft += Duration::ZERO;
811 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
812 }
813 {
814 let mut ft = FileTime::NT_TIME_EPOCH;
815 ft += Duration::from_nanos(1);
816 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
817 }
818 {
819 let mut ft = FileTime::NT_TIME_EPOCH;
820 ft += Duration::from_nanos(99);
821 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
822 }
823 {
824 let mut ft = FileTime::NT_TIME_EPOCH;
825 ft += Duration::from_nanos(100);
826 assert_eq!(ft, FileTime::new(1));
827 }
828
829 {
830 let mut ft = FileTime::MAX;
831 ft += Duration::ZERO;
832 assert_eq!(ft, FileTime::MAX);
833 }
834 {
835 let mut ft = FileTime::MAX;
836 ft += Duration::from_nanos(1);
837 assert_eq!(ft, FileTime::MAX);
838 }
839 {
840 let mut ft = FileTime::MAX;
841 ft += Duration::from_nanos(99);
842 assert_eq!(ft, FileTime::MAX);
843 }
844 }
845
846 #[test]
847 #[should_panic(expected = "overflow when adding duration to date and time")]
848 fn add_assign_std_duration_with_overflow() {
849 let mut ft = FileTime::MAX;
850 ft += Duration::from_nanos(100);
851 }
852
853 #[test]
854 fn add_assign_positive_time_duration() {
855 {
856 let mut ft = FileTime::NT_TIME_EPOCH;
857 ft += time::Duration::ZERO;
858 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
859 }
860 {
861 let mut ft = FileTime::NT_TIME_EPOCH;
862 ft += time::Duration::NANOSECOND;
863 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
864 }
865 {
866 let mut ft = FileTime::NT_TIME_EPOCH;
867 ft += time::Duration::nanoseconds(99);
868 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
869 }
870 {
871 let mut ft = FileTime::NT_TIME_EPOCH;
872 ft += time::Duration::nanoseconds(100);
873 assert_eq!(ft, FileTime::new(1));
874 }
875
876 {
877 let mut ft = FileTime::MAX;
878 ft += time::Duration::ZERO;
879 assert_eq!(ft, FileTime::MAX);
880 }
881 {
882 let mut ft = FileTime::MAX;
883 ft += time::Duration::NANOSECOND;
884 assert_eq!(ft, FileTime::MAX);
885 }
886 {
887 let mut ft = FileTime::MAX;
888 ft += time::Duration::nanoseconds(99);
889 assert_eq!(ft, FileTime::MAX);
890 }
891 }
892
893 #[test]
894 #[should_panic(expected = "overflow when adding duration to date and time")]
895 fn add_assign_positive_time_duration_with_overflow() {
896 let mut ft = FileTime::MAX;
897 ft += time::Duration::nanoseconds(100);
898 }
899
900 #[test]
901 fn add_assign_negative_time_duration() {
902 {
903 let mut ft = FileTime::MAX;
904 ft += -time::Duration::ZERO;
905 assert_eq!(ft, FileTime::MAX);
906 }
907 {
908 let mut ft = FileTime::MAX;
909 ft += -time::Duration::NANOSECOND;
910 assert_eq!(ft, FileTime::MAX);
911 }
912 {
913 let mut ft = FileTime::MAX;
914 ft += -time::Duration::nanoseconds(99);
915 assert_eq!(ft, FileTime::MAX);
916 }
917 {
918 let mut ft = FileTime::MAX;
919 ft += -time::Duration::nanoseconds(100);
920 assert_eq!(ft, FileTime::new(u64::MAX - 1));
921 }
922
923 {
924 let mut ft = FileTime::NT_TIME_EPOCH;
925 ft += -time::Duration::ZERO;
926 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
927 }
928 {
929 let mut ft = FileTime::NT_TIME_EPOCH;
930 ft += -time::Duration::NANOSECOND;
931 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
932 }
933 {
934 let mut ft = FileTime::NT_TIME_EPOCH;
935 ft += -time::Duration::nanoseconds(99);
936 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
937 }
938 }
939
940 #[test]
941 #[should_panic(expected = "overflow when subtracting duration from date and time")]
942 fn add_assign_negative_time_duration_with_overflow() {
943 let mut ft = FileTime::NT_TIME_EPOCH;
944 ft += -time::Duration::nanoseconds(100);
945 }
946
947 #[cfg(feature = "chrono")]
948 #[test]
949 fn add_assign_positive_chrono_time_delta() {
950 {
951 let mut ft = FileTime::NT_TIME_EPOCH;
952 ft += TimeDelta::zero();
953 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
954 }
955 {
956 let mut ft = FileTime::NT_TIME_EPOCH;
957 ft += TimeDelta::nanoseconds(1);
958 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
959 }
960 {
961 let mut ft = FileTime::NT_TIME_EPOCH;
962 ft += TimeDelta::nanoseconds(99);
963 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
964 }
965 {
966 let mut ft = FileTime::NT_TIME_EPOCH;
967 ft += TimeDelta::nanoseconds(100);
968 assert_eq!(ft, FileTime::new(1));
969 }
970
971 {
972 let mut ft = FileTime::MAX;
973 ft += TimeDelta::zero();
974 assert_eq!(ft, FileTime::MAX);
975 }
976 {
977 let mut ft = FileTime::MAX;
978 ft += TimeDelta::nanoseconds(1);
979 assert_eq!(ft, FileTime::MAX);
980 }
981 {
982 let mut ft = FileTime::MAX;
983 ft += TimeDelta::nanoseconds(99);
984 assert_eq!(ft, FileTime::MAX);
985 }
986 }
987
988 #[cfg(feature = "chrono")]
989 #[test]
990 #[should_panic(expected = "overflow when adding duration to date and time")]
991 fn add_assign_positive_chrono_time_delta_with_overflow() {
992 let mut ft = FileTime::MAX;
993 ft += TimeDelta::nanoseconds(100);
994 }
995
996 #[cfg(feature = "chrono")]
997 #[test]
998 fn add_assign_negative_chrono_time_delta() {
999 {
1000 let mut ft = FileTime::MAX;
1001 ft += -TimeDelta::zero();
1002 assert_eq!(ft, FileTime::MAX);
1003 }
1004 {
1005 let mut ft = FileTime::MAX;
1006 ft += -TimeDelta::nanoseconds(1);
1007 assert_eq!(ft, FileTime::MAX);
1008 }
1009 {
1010 let mut ft = FileTime::MAX;
1011 ft += -TimeDelta::nanoseconds(99);
1012 assert_eq!(ft, FileTime::MAX);
1013 }
1014 {
1015 let mut ft = FileTime::MAX;
1016 ft += -TimeDelta::nanoseconds(100);
1017 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1018 }
1019
1020 {
1021 let mut ft = FileTime::NT_TIME_EPOCH;
1022 ft += -TimeDelta::zero();
1023 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1024 }
1025 {
1026 let mut ft = FileTime::NT_TIME_EPOCH;
1027 ft += -TimeDelta::nanoseconds(1);
1028 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1029 }
1030 {
1031 let mut ft = FileTime::NT_TIME_EPOCH;
1032 ft += -TimeDelta::nanoseconds(99);
1033 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1034 }
1035 }
1036
1037 #[cfg(feature = "chrono")]
1038 #[test]
1039 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1040 fn add_assign_negative_chrono_time_delta_with_overflow() {
1041 let mut ft = FileTime::NT_TIME_EPOCH;
1042 ft += -TimeDelta::nanoseconds(100);
1043 }
1044
1045 #[cfg(feature = "jiff")]
1046 #[test]
1047 fn add_assign_positive_jiff_span() {
1048 {
1049 let mut ft = FileTime::NT_TIME_EPOCH;
1050 ft += Span::new();
1051 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1052 }
1053 {
1054 let mut ft = FileTime::NT_TIME_EPOCH;
1055 ft += 1.nanosecond();
1056 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1057 }
1058 {
1059 let mut ft = FileTime::NT_TIME_EPOCH;
1060 ft += 99.nanoseconds();
1061 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1062 }
1063 {
1064 let mut ft = FileTime::NT_TIME_EPOCH;
1065 ft += 100.nanoseconds();
1066 assert_eq!(ft, FileTime::new(1));
1067 }
1068
1069 {
1070 let mut ft = FileTime::MAX;
1071 ft += Span::new();
1072 assert_eq!(ft, FileTime::MAX);
1073 }
1074 {
1075 let mut ft = FileTime::MAX;
1076 ft += 1.nanosecond();
1077 assert_eq!(ft, FileTime::MAX);
1078 }
1079 {
1080 let mut ft = FileTime::MAX;
1081 ft += 99.nanoseconds();
1082 assert_eq!(ft, FileTime::MAX);
1083 }
1084 }
1085
1086 #[cfg(feature = "jiff")]
1087 #[test]
1088 #[should_panic(expected = "overflow when adding duration to date and time")]
1089 fn add_assign_positive_jiff_span_with_overflow() {
1090 let mut ft = FileTime::MAX;
1091 ft += 100.nanoseconds();
1092 }
1093
1094 #[cfg(feature = "jiff")]
1095 #[test]
1096 fn add_assign_negative_jiff_span() {
1097 {
1098 let mut ft = FileTime::MAX;
1099 ft += -Span::new();
1100 assert_eq!(ft, FileTime::MAX);
1101 }
1102 {
1103 let mut ft = FileTime::MAX;
1104 ft += -(1.nanosecond());
1105 assert_eq!(ft, FileTime::MAX);
1106 }
1107 {
1108 let mut ft = FileTime::MAX;
1109 ft += -(99.nanoseconds());
1110 assert_eq!(ft, FileTime::MAX);
1111 }
1112 {
1113 let mut ft = FileTime::MAX;
1114 ft += -(100.nanoseconds());
1115 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1116 }
1117
1118 {
1119 let mut ft = FileTime::NT_TIME_EPOCH;
1120 ft += -Span::new();
1121 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1122 }
1123 {
1124 let mut ft = FileTime::NT_TIME_EPOCH;
1125 ft += -(1.nanosecond());
1126 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1127 }
1128 {
1129 let mut ft = FileTime::NT_TIME_EPOCH;
1130 ft += -(99.nanoseconds());
1131 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1132 }
1133 }
1134
1135 #[cfg(feature = "jiff")]
1136 #[test]
1137 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1138 fn add_assign_negative_jiff_span_with_overflow() {
1139 let mut ft = FileTime::NT_TIME_EPOCH;
1140 ft += -(100.nanoseconds());
1141 }
1142
1143 #[test]
1144 fn sub_file_time() {
1145 assert_eq!(FileTime::MAX - FileTime::MAX, Duration::ZERO);
1146 assert_eq!(
1147 FileTime::MAX - (FileTime::MAX - Duration::from_nanos(100)),
1148 Duration::from_nanos(100)
1149 );
1150 assert_eq!(
1151 FileTime::MAX - FileTime::NT_TIME_EPOCH,
1152 Duration::new(1_844_674_407_370, 955_161_500)
1153 );
1154 }
1155
1156 #[test]
1157 #[should_panic(expected = "attempt to subtract with overflow")]
1158 fn sub_file_time_with_overflow() {
1159 let _ = (FileTime::MAX - Duration::from_nanos(100)) - FileTime::MAX;
1160 }
1161
1162 #[test]
1163 fn sub_std_duration() {
1164 assert_eq!(FileTime::MAX - Duration::ZERO, FileTime::MAX);
1165 assert_eq!(FileTime::MAX - Duration::from_nanos(1), FileTime::MAX);
1166 assert_eq!(FileTime::MAX - Duration::from_nanos(99), FileTime::MAX);
1167 assert_eq!(
1168 FileTime::MAX - Duration::from_nanos(100),
1169 FileTime::new(u64::MAX - 1)
1170 );
1171
1172 assert_eq!(
1173 FileTime::NT_TIME_EPOCH - Duration::ZERO,
1174 FileTime::NT_TIME_EPOCH
1175 );
1176 assert_eq!(
1177 FileTime::NT_TIME_EPOCH - Duration::from_nanos(1),
1178 FileTime::NT_TIME_EPOCH
1179 );
1180 assert_eq!(
1181 FileTime::NT_TIME_EPOCH - Duration::from_nanos(99),
1182 FileTime::NT_TIME_EPOCH
1183 );
1184 }
1185
1186 #[test]
1187 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1188 fn sub_std_duration_with_overflow() {
1189 let _ = FileTime::NT_TIME_EPOCH - Duration::from_nanos(100);
1190 }
1191
1192 #[test]
1193 fn sub_positive_time_duration() {
1194 assert_eq!(FileTime::MAX - time::Duration::ZERO, FileTime::MAX);
1195 assert_eq!(FileTime::MAX - time::Duration::NANOSECOND, FileTime::MAX);
1196 assert_eq!(
1197 FileTime::MAX - time::Duration::nanoseconds(99),
1198 FileTime::MAX
1199 );
1200 assert_eq!(
1201 FileTime::MAX - time::Duration::nanoseconds(100),
1202 FileTime::new(u64::MAX - 1)
1203 );
1204
1205 assert_eq!(
1206 FileTime::NT_TIME_EPOCH - time::Duration::ZERO,
1207 FileTime::NT_TIME_EPOCH
1208 );
1209 assert_eq!(
1210 FileTime::NT_TIME_EPOCH - time::Duration::NANOSECOND,
1211 FileTime::NT_TIME_EPOCH
1212 );
1213 assert_eq!(
1214 FileTime::NT_TIME_EPOCH - time::Duration::nanoseconds(99),
1215 FileTime::NT_TIME_EPOCH
1216 );
1217 }
1218
1219 #[test]
1220 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1221 fn sub_positive_time_duration_with_overflow() {
1222 let _ = FileTime::NT_TIME_EPOCH - time::Duration::nanoseconds(100);
1223 }
1224
1225 #[test]
1226 fn sub_negative_time_duration() {
1227 assert_eq!(
1228 FileTime::NT_TIME_EPOCH - -time::Duration::ZERO,
1229 FileTime::NT_TIME_EPOCH
1230 );
1231 assert_eq!(
1232 FileTime::NT_TIME_EPOCH - -time::Duration::NANOSECOND,
1233 FileTime::NT_TIME_EPOCH
1234 );
1235 assert_eq!(
1236 FileTime::NT_TIME_EPOCH - -time::Duration::nanoseconds(99),
1237 FileTime::NT_TIME_EPOCH
1238 );
1239 assert_eq!(
1240 FileTime::NT_TIME_EPOCH - -time::Duration::nanoseconds(100),
1241 FileTime::new(1)
1242 );
1243
1244 assert_eq!(FileTime::MAX - -time::Duration::ZERO, FileTime::MAX);
1245 assert_eq!(FileTime::MAX - -time::Duration::NANOSECOND, FileTime::MAX);
1246 assert_eq!(
1247 FileTime::MAX - -time::Duration::nanoseconds(99),
1248 FileTime::MAX
1249 );
1250 }
1251
1252 #[test]
1253 #[should_panic(expected = "overflow when adding duration to date and time")]
1254 fn sub_negative_time_duration_with_overflow() {
1255 let _ = FileTime::MAX - -time::Duration::nanoseconds(100);
1256 }
1257
1258 #[cfg(feature = "chrono")]
1259 #[test]
1260 fn sub_positive_chrono_time_delta() {
1261 assert_eq!(FileTime::MAX - TimeDelta::zero(), FileTime::MAX);
1262 assert_eq!(FileTime::MAX - TimeDelta::nanoseconds(1), FileTime::MAX);
1263 assert_eq!(FileTime::MAX - TimeDelta::nanoseconds(99), FileTime::MAX);
1264 assert_eq!(
1265 FileTime::MAX - TimeDelta::nanoseconds(100),
1266 FileTime::new(u64::MAX - 1)
1267 );
1268
1269 assert_eq!(
1270 FileTime::NT_TIME_EPOCH - TimeDelta::zero(),
1271 FileTime::NT_TIME_EPOCH
1272 );
1273 assert_eq!(
1274 FileTime::NT_TIME_EPOCH - TimeDelta::nanoseconds(1),
1275 FileTime::NT_TIME_EPOCH
1276 );
1277 assert_eq!(
1278 FileTime::NT_TIME_EPOCH - TimeDelta::nanoseconds(99),
1279 FileTime::NT_TIME_EPOCH
1280 );
1281 }
1282
1283 #[cfg(feature = "chrono")]
1284 #[test]
1285 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1286 fn sub_positive_chrono_time_delta_with_overflow() {
1287 let _ = FileTime::NT_TIME_EPOCH - TimeDelta::nanoseconds(100);
1288 }
1289
1290 #[cfg(feature = "chrono")]
1291 #[test]
1292 fn sub_negative_chrono_time_delta() {
1293 assert_eq!(
1294 FileTime::NT_TIME_EPOCH - -TimeDelta::zero(),
1295 FileTime::NT_TIME_EPOCH
1296 );
1297 assert_eq!(
1298 FileTime::NT_TIME_EPOCH - -TimeDelta::nanoseconds(1),
1299 FileTime::NT_TIME_EPOCH
1300 );
1301 assert_eq!(
1302 FileTime::NT_TIME_EPOCH - -TimeDelta::nanoseconds(99),
1303 FileTime::NT_TIME_EPOCH
1304 );
1305 assert_eq!(
1306 FileTime::NT_TIME_EPOCH - -TimeDelta::nanoseconds(100),
1307 FileTime::new(1)
1308 );
1309
1310 assert_eq!(FileTime::MAX - -TimeDelta::zero(), FileTime::MAX);
1311 assert_eq!(FileTime::MAX - -TimeDelta::nanoseconds(1), FileTime::MAX);
1312 assert_eq!(FileTime::MAX - -TimeDelta::nanoseconds(99), FileTime::MAX);
1313 }
1314
1315 #[cfg(feature = "chrono")]
1316 #[test]
1317 #[should_panic(expected = "overflow when adding duration to date and time")]
1318 fn sub_negative_chrono_time_delta_with_overflow() {
1319 let _ = FileTime::MAX - -TimeDelta::nanoseconds(100);
1320 }
1321
1322 #[cfg(feature = "jiff")]
1323 #[test]
1324 fn sub_positive_jiff_span() {
1325 assert_eq!(FileTime::MAX - Span::new(), FileTime::MAX);
1326 assert_eq!(FileTime::MAX - 1.nanosecond(), FileTime::MAX);
1327 assert_eq!(FileTime::MAX - 99.nanoseconds(), FileTime::MAX);
1328 assert_eq!(
1329 FileTime::MAX - 100.nanoseconds(),
1330 FileTime::new(u64::MAX - 1)
1331 );
1332
1333 assert_eq!(
1334 FileTime::NT_TIME_EPOCH - Span::new(),
1335 FileTime::NT_TIME_EPOCH
1336 );
1337 assert_eq!(
1338 FileTime::NT_TIME_EPOCH - 1.nanosecond(),
1339 FileTime::NT_TIME_EPOCH
1340 );
1341 assert_eq!(
1342 FileTime::NT_TIME_EPOCH - 99.nanoseconds(),
1343 FileTime::NT_TIME_EPOCH
1344 );
1345 }
1346
1347 #[cfg(feature = "jiff")]
1348 #[test]
1349 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1350 fn sub_positive_jiff_span_with_overflow() {
1351 let _ = FileTime::NT_TIME_EPOCH - 100.nanoseconds();
1352 }
1353
1354 #[cfg(feature = "jiff")]
1355 #[test]
1356 fn sub_negative_jiff_span() {
1357 assert_eq!(
1358 FileTime::NT_TIME_EPOCH - -Span::new(),
1359 FileTime::NT_TIME_EPOCH
1360 );
1361 assert_eq!(
1362 FileTime::NT_TIME_EPOCH - -(1.nanosecond()),
1363 FileTime::NT_TIME_EPOCH
1364 );
1365 assert_eq!(
1366 FileTime::NT_TIME_EPOCH - -(99.nanoseconds()),
1367 FileTime::NT_TIME_EPOCH
1368 );
1369 assert_eq!(
1370 FileTime::NT_TIME_EPOCH - -(100.nanoseconds()),
1371 FileTime::new(1)
1372 );
1373
1374 assert_eq!(FileTime::MAX - -Span::new(), FileTime::MAX);
1375 assert_eq!(FileTime::MAX - -(1.nanosecond()), FileTime::MAX);
1376 assert_eq!(FileTime::MAX - -(99.nanoseconds()), FileTime::MAX);
1377 }
1378
1379 #[cfg(feature = "jiff")]
1380 #[test]
1381 #[should_panic(expected = "overflow when adding duration to date and time")]
1382 fn sub_negative_jiff_span_with_overflow() {
1383 let _ = FileTime::MAX - -(100.nanoseconds());
1384 }
1385
1386 #[cfg(feature = "std")]
1387 #[test]
1388 fn sub_file_time_from_system_time() {
1389 assert_eq!(
1390 (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
1391 - FileTime::new(9_223_372_036_854_775_807),
1392 Duration::ZERO
1393 );
1394 assert_eq!(
1395 (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
1396 - FileTime::new(9_223_372_036_854_775_806),
1397 Duration::from_nanos(100)
1398 );
1399 assert_eq!(
1400 (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
1401 - FileTime::UNIX_EPOCH,
1402 Duration::new(910_692_730_085, 477_580_700)
1403 );
1404 }
1405
1406 #[cfg(feature = "std")]
1407 #[test]
1408 #[should_panic(expected = "RHS provided is later than LHS")]
1409 fn sub_file_time_from_system_time_with_overflow() {
1410 let _ = FileTime::new(9_223_372_036_854_775_806)
1411 - (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700));
1412 }
1413
1414 #[cfg(feature = "std")]
1415 #[test]
1416 fn sub_system_time_from_file_time() {
1417 assert_eq!(
1418 FileTime::new(9_223_372_036_854_775_807)
1419 - (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700)),
1420 Duration::ZERO
1421 );
1422 assert_eq!(
1423 FileTime::new(9_223_372_036_854_775_807)
1424 - (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_699)),
1425 Duration::from_nanos(if cfg!(windows) { 100 } else { 1 })
1426 );
1427 assert_eq!(
1428 FileTime::new(9_223_372_036_854_775_807)
1429 - (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_601)),
1430 Duration::from_nanos(if cfg!(windows) { 100 } else { 99 })
1431 );
1432 assert_eq!(
1433 FileTime::new(9_223_372_036_854_775_807)
1434 - (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_600)),
1435 Duration::from_nanos(100)
1436 );
1437 assert_eq!(
1438 FileTime::new(9_223_372_036_854_775_807) - SystemTime::UNIX_EPOCH,
1439 Duration::new(910_692_730_085, 477_580_700)
1440 );
1441 }
1442
1443 #[cfg(feature = "std")]
1444 #[test]
1445 #[should_panic(expected = "RHS provided is later than LHS")]
1446 fn sub_system_time_from_file_time_with_overflow() {
1447 let _ = (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_600))
1448 - FileTime::new(9_223_372_036_854_775_807);
1449 }
1450
1451 #[test]
1452 fn sub_file_time_from_utc_date_time() {
1453 assert_eq!(
1454 utc_datetime!(9999-12-31 23:59:59.999_999_900)
1455 - FileTime::new(2_650_467_743_999_999_999),
1456 time::Duration::ZERO
1457 );
1458 assert_eq!(
1459 utc_datetime!(9999-12-31 23:59:59.999_999_900)
1460 - (FileTime::new(2_650_467_743_999_999_999) - time::Duration::nanoseconds(100)),
1461 time::Duration::nanoseconds(100)
1462 );
1463 assert_eq!(
1464 utc_datetime!(9999-12-31 23:59:59.999_999_900) - FileTime::NT_TIME_EPOCH,
1465 time::Duration::new(265_046_774_399, 999_999_900)
1466 );
1467 }
1468
1469 #[test]
1470 fn sub_utc_date_time_from_file_time() {
1471 assert_eq!(
1472 FileTime::new(2_650_467_743_999_999_999)
1473 - utc_datetime!(9999-12-31 23:59:59.999_999_900),
1474 time::Duration::ZERO
1475 );
1476 assert_eq!(
1477 FileTime::new(2_650_467_743_999_999_999)
1478 - (utc_datetime!(9999-12-31 23:59:59.999_999_900) - time::Duration::nanoseconds(1)),
1479 time::Duration::nanoseconds(1)
1480 );
1481 assert_eq!(
1482 FileTime::new(2_650_467_743_999_999_999)
1483 - (utc_datetime!(9999-12-31 23:59:59.999_999_900)
1484 - time::Duration::nanoseconds(99)),
1485 time::Duration::nanoseconds(99)
1486 );
1487 assert_eq!(
1488 FileTime::new(2_650_467_743_999_999_999)
1489 - (utc_datetime!(9999-12-31 23:59:59.999_999_900)
1490 - time::Duration::nanoseconds(100)),
1491 time::Duration::nanoseconds(100)
1492 );
1493 assert_eq!(
1494 FileTime::new(2_650_467_743_999_999_999) - utc_datetime!(1601-01-01 00:00:00),
1495 time::Duration::new(265_046_774_399, 999_999_900)
1496 );
1497 }
1498
1499 #[cfg(feature = "chrono")]
1500 #[test]
1501 fn sub_file_time_from_chrono_date_time() {
1502 assert_eq!(
1503 "+60056-05-28 05:36:10.955161500 UTC"
1504 .parse::<DateTime<Utc>>()
1505 .unwrap()
1506 - FileTime::MAX,
1507 TimeDelta::zero()
1508 );
1509 assert_eq!(
1510 "+60056-05-28 05:36:10.955161500 UTC"
1511 .parse::<DateTime<Utc>>()
1512 .unwrap()
1513 - (FileTime::MAX - Duration::from_nanos(100)),
1514 TimeDelta::nanoseconds(100)
1515 );
1516 assert_eq!(
1517 "+60056-05-28 05:36:10.955161500 UTC"
1518 .parse::<DateTime<Utc>>()
1519 .unwrap()
1520 - FileTime::NT_TIME_EPOCH,
1521 TimeDelta::new(1_844_674_407_370, 955_161_500).unwrap()
1522 );
1523 }
1524
1525 #[cfg(feature = "chrono")]
1526 #[test]
1527 fn sub_chrono_date_time_from_file_time() {
1528 assert_eq!(
1529 FileTime::MAX
1530 - "+60056-05-28 05:36:10.955161500 UTC"
1531 .parse::<DateTime<Utc>>()
1532 .unwrap(),
1533 TimeDelta::zero()
1534 );
1535 assert_eq!(
1536 FileTime::MAX
1537 - ("+60056-05-28 05:36:10.955161500 UTC"
1538 .parse::<DateTime<Utc>>()
1539 .unwrap()
1540 - TimeDelta::nanoseconds(1)),
1541 TimeDelta::nanoseconds(1)
1542 );
1543 assert_eq!(
1544 FileTime::MAX
1545 - ("+60056-05-28 05:36:10.955161500 UTC"
1546 .parse::<DateTime<Utc>>()
1547 .unwrap()
1548 - TimeDelta::nanoseconds(99)),
1549 TimeDelta::nanoseconds(99)
1550 );
1551 assert_eq!(
1552 FileTime::MAX
1553 - ("+60056-05-28 05:36:10.955161500 UTC"
1554 .parse::<DateTime<Utc>>()
1555 .unwrap()
1556 - TimeDelta::nanoseconds(100)),
1557 TimeDelta::nanoseconds(100)
1558 );
1559 assert_eq!(
1560 FileTime::MAX - "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap(),
1561 TimeDelta::new(1_844_674_407_370, 955_161_500).unwrap()
1562 );
1563 }
1564
1565 #[cfg(feature = "jiff")]
1566 #[test]
1567 fn sub_file_time_from_jiff_timestamp() {
1568 assert_eq!(
1569 (Timestamp::MAX - 99.nanoseconds()) - FileTime::new(2_650_466_808_009_999_999),
1570 Span::new().fieldwise()
1571 );
1572 assert_eq!(
1573 (Timestamp::MAX - 99.nanoseconds())
1574 - (FileTime::new(2_650_466_808_009_999_999) - 100.nanoseconds()),
1575 100.nanoseconds().fieldwise()
1576 );
1577 assert_eq!(
1578 (Timestamp::MAX - 99.nanoseconds()) - FileTime::NT_TIME_EPOCH,
1579 265_046_680_800_i64
1580 .seconds()
1581 .milliseconds(999)
1582 .microseconds(999)
1583 .nanoseconds(900)
1584 .fieldwise()
1585 );
1586 }
1587
1588 #[cfg(feature = "jiff")]
1589 #[test]
1590 fn sub_jiff_timestamp_from_file_time() {
1591 assert_eq!(
1592 FileTime::new(2_650_466_808_009_999_999) - (Timestamp::MAX - 99.nanoseconds()),
1593 Span::new().fieldwise()
1594 );
1595 assert_eq!(
1596 FileTime::new(2_650_466_808_009_999_999)
1597 - ((Timestamp::MAX - 99.nanoseconds()) - 1.nanosecond()),
1598 1.nanosecond().fieldwise()
1599 );
1600 assert_eq!(
1601 FileTime::new(2_650_466_808_009_999_999)
1602 - ((Timestamp::MAX - 99.nanoseconds()) - 99.nanoseconds()),
1603 99.nanoseconds().fieldwise()
1604 );
1605 assert_eq!(
1606 FileTime::new(2_650_466_808_009_999_999)
1607 - ((Timestamp::MAX - 99.nanoseconds()) - 100.nanoseconds()),
1608 100.nanoseconds().fieldwise()
1609 );
1610 assert_eq!(
1611 FileTime::new(2_650_466_808_009_999_999)
1612 - Timestamp::from_second(-11_644_473_600).unwrap(),
1613 265_046_680_800_i64
1614 .seconds()
1615 .milliseconds(999)
1616 .microseconds(999)
1617 .nanoseconds(900)
1618 .fieldwise()
1619 );
1620 }
1621
1622 #[test]
1623 fn sub_assign_std_duration() {
1624 {
1625 let mut ft = FileTime::MAX;
1626 ft -= Duration::ZERO;
1627 assert_eq!(ft, FileTime::MAX);
1628 }
1629 {
1630 let mut ft = FileTime::MAX;
1631 ft -= Duration::from_nanos(1);
1632 assert_eq!(ft, FileTime::MAX);
1633 }
1634 {
1635 let mut ft = FileTime::MAX;
1636 ft -= Duration::from_nanos(99);
1637 assert_eq!(ft, FileTime::MAX);
1638 }
1639 {
1640 let mut ft = FileTime::MAX;
1641 ft -= Duration::from_nanos(100);
1642 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1643 }
1644
1645 {
1646 let mut ft = FileTime::NT_TIME_EPOCH;
1647 ft -= Duration::ZERO;
1648 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1649 }
1650 {
1651 let mut ft = FileTime::NT_TIME_EPOCH;
1652 ft -= Duration::from_nanos(1);
1653 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1654 }
1655 {
1656 let mut ft = FileTime::NT_TIME_EPOCH;
1657 ft -= Duration::from_nanos(99);
1658 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1659 }
1660 }
1661
1662 #[test]
1663 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1664 fn sub_assign_std_duration_with_overflow() {
1665 let mut ft = FileTime::NT_TIME_EPOCH;
1666 ft -= Duration::from_nanos(100);
1667 }
1668
1669 #[test]
1670 fn sub_assign_positive_time_duration() {
1671 {
1672 let mut ft = FileTime::MAX;
1673 ft -= time::Duration::ZERO;
1674 assert_eq!(ft, FileTime::MAX);
1675 }
1676 {
1677 let mut ft = FileTime::MAX;
1678 ft -= time::Duration::NANOSECOND;
1679 assert_eq!(ft, FileTime::MAX);
1680 }
1681 {
1682 let mut ft = FileTime::MAX;
1683 ft -= time::Duration::nanoseconds(99);
1684 assert_eq!(ft, FileTime::MAX);
1685 }
1686 {
1687 let mut ft = FileTime::MAX;
1688 ft -= time::Duration::nanoseconds(100);
1689 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1690 }
1691
1692 {
1693 let mut ft = FileTime::NT_TIME_EPOCH;
1694 ft -= time::Duration::ZERO;
1695 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1696 }
1697 {
1698 let mut ft = FileTime::NT_TIME_EPOCH;
1699 ft -= time::Duration::NANOSECOND;
1700 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1701 }
1702 {
1703 let mut ft = FileTime::NT_TIME_EPOCH;
1704 ft -= time::Duration::nanoseconds(99);
1705 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1706 }
1707 }
1708
1709 #[test]
1710 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1711 fn sub_assign_positive_time_duration_with_overflow() {
1712 let mut ft = FileTime::NT_TIME_EPOCH;
1713 ft -= time::Duration::nanoseconds(100);
1714 }
1715
1716 #[test]
1717 fn sub_assign_negative_time_duration() {
1718 {
1719 let mut ft = FileTime::NT_TIME_EPOCH;
1720 ft -= -time::Duration::ZERO;
1721 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1722 }
1723 {
1724 let mut ft = FileTime::NT_TIME_EPOCH;
1725 ft -= -time::Duration::NANOSECOND;
1726 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1727 }
1728 {
1729 let mut ft = FileTime::NT_TIME_EPOCH;
1730 ft -= -time::Duration::nanoseconds(99);
1731 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1732 }
1733 {
1734 let mut ft = FileTime::NT_TIME_EPOCH;
1735 ft -= -time::Duration::nanoseconds(100);
1736 assert_eq!(ft, FileTime::new(1));
1737 }
1738
1739 {
1740 let mut ft = FileTime::MAX;
1741 ft -= -time::Duration::ZERO;
1742 assert_eq!(ft, FileTime::MAX);
1743 }
1744 {
1745 let mut ft = FileTime::MAX;
1746 ft -= -time::Duration::NANOSECOND;
1747 assert_eq!(ft, FileTime::MAX);
1748 }
1749 {
1750 let mut ft = FileTime::MAX;
1751 ft -= -time::Duration::nanoseconds(99);
1752 assert_eq!(ft, FileTime::MAX);
1753 }
1754 }
1755
1756 #[test]
1757 #[should_panic(expected = "overflow when adding duration to date and time")]
1758 fn sub_assign_negative_time_duration_with_overflow() {
1759 let mut ft = FileTime::MAX;
1760 ft -= -time::Duration::nanoseconds(100);
1761 }
1762
1763 #[cfg(feature = "chrono")]
1764 #[test]
1765 fn sub_assign_positive_chrono_time_delta() {
1766 {
1767 let mut ft = FileTime::MAX;
1768 ft -= TimeDelta::zero();
1769 assert_eq!(ft, FileTime::MAX);
1770 }
1771 {
1772 let mut ft = FileTime::MAX;
1773 ft -= TimeDelta::nanoseconds(1);
1774 assert_eq!(ft, FileTime::MAX);
1775 }
1776 {
1777 let mut ft = FileTime::MAX;
1778 ft -= TimeDelta::nanoseconds(99);
1779 assert_eq!(ft, FileTime::MAX);
1780 }
1781 {
1782 let mut ft = FileTime::MAX;
1783 ft -= TimeDelta::nanoseconds(100);
1784 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1785 }
1786
1787 {
1788 let mut ft = FileTime::NT_TIME_EPOCH;
1789 ft -= TimeDelta::zero();
1790 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1791 }
1792 {
1793 let mut ft = FileTime::NT_TIME_EPOCH;
1794 ft -= TimeDelta::nanoseconds(1);
1795 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1796 }
1797 {
1798 let mut ft = FileTime::NT_TIME_EPOCH;
1799 ft -= TimeDelta::nanoseconds(99);
1800 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1801 }
1802 }
1803
1804 #[cfg(feature = "chrono")]
1805 #[test]
1806 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1807 fn sub_assign_positive_chrono_time_delta_with_overflow() {
1808 let mut ft = FileTime::NT_TIME_EPOCH;
1809 ft -= TimeDelta::nanoseconds(100);
1810 }
1811
1812 #[cfg(feature = "chrono")]
1813 #[test]
1814 fn sub_assign_negative_chrono_time_delta() {
1815 {
1816 let mut ft = FileTime::NT_TIME_EPOCH;
1817 ft -= -TimeDelta::zero();
1818 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1819 }
1820 {
1821 let mut ft = FileTime::NT_TIME_EPOCH;
1822 ft -= -TimeDelta::nanoseconds(1);
1823 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1824 }
1825 {
1826 let mut ft = FileTime::NT_TIME_EPOCH;
1827 ft -= -TimeDelta::nanoseconds(99);
1828 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1829 }
1830 {
1831 let mut ft = FileTime::NT_TIME_EPOCH;
1832 ft -= -TimeDelta::nanoseconds(100);
1833 assert_eq!(ft, FileTime::new(1));
1834 }
1835
1836 {
1837 let mut ft = FileTime::MAX;
1838 ft -= -TimeDelta::zero();
1839 assert_eq!(ft, FileTime::MAX);
1840 }
1841 {
1842 let mut ft = FileTime::MAX;
1843 ft -= -TimeDelta::nanoseconds(1);
1844 assert_eq!(ft, FileTime::MAX);
1845 }
1846 {
1847 let mut ft = FileTime::MAX;
1848 ft -= -TimeDelta::nanoseconds(99);
1849 assert_eq!(ft, FileTime::MAX);
1850 }
1851 }
1852
1853 #[cfg(feature = "chrono")]
1854 #[test]
1855 #[should_panic(expected = "overflow when adding duration to date and time")]
1856 fn sub_assign_negative_chrono_time_delta_with_overflow() {
1857 let mut ft = FileTime::MAX;
1858 ft -= -TimeDelta::nanoseconds(100);
1859 }
1860
1861 #[cfg(feature = "jiff")]
1862 #[test]
1863 fn sub_assign_positive_jiff_span() {
1864 {
1865 let mut ft = FileTime::MAX;
1866 ft -= Span::new();
1867 assert_eq!(ft, FileTime::MAX);
1868 }
1869 {
1870 let mut ft = FileTime::MAX;
1871 ft -= 1.nanosecond();
1872 assert_eq!(ft, FileTime::MAX);
1873 }
1874 {
1875 let mut ft = FileTime::MAX;
1876 ft -= 99.nanoseconds();
1877 assert_eq!(ft, FileTime::MAX);
1878 }
1879 {
1880 let mut ft = FileTime::MAX;
1881 ft -= 100.nanoseconds();
1882 assert_eq!(ft, FileTime::new(u64::MAX - 1));
1883 }
1884
1885 {
1886 let mut ft = FileTime::NT_TIME_EPOCH;
1887 ft -= Span::new();
1888 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1889 }
1890 {
1891 let mut ft = FileTime::NT_TIME_EPOCH;
1892 ft -= 1.nanosecond();
1893 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1894 }
1895 {
1896 let mut ft = FileTime::NT_TIME_EPOCH;
1897 ft -= 99.nanoseconds();
1898 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1899 }
1900 }
1901
1902 #[cfg(feature = "jiff")]
1903 #[test]
1904 #[should_panic(expected = "overflow when subtracting duration from date and time")]
1905 fn sub_assign_positive_jiff_span_with_overflow() {
1906 let mut ft = FileTime::NT_TIME_EPOCH;
1907 ft -= 100.nanoseconds();
1908 }
1909
1910 #[cfg(feature = "jiff")]
1911 #[test]
1912 fn sub_assign_negative_jiff_span() {
1913 {
1914 let mut ft = FileTime::NT_TIME_EPOCH;
1915 ft -= -Span::new();
1916 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1917 }
1918 {
1919 let mut ft = FileTime::NT_TIME_EPOCH;
1920 ft -= -(1.nanosecond());
1921 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1922 }
1923 {
1924 let mut ft = FileTime::NT_TIME_EPOCH;
1925 ft -= -(99.nanoseconds());
1926 assert_eq!(ft, FileTime::NT_TIME_EPOCH);
1927 }
1928 {
1929 let mut ft = FileTime::NT_TIME_EPOCH;
1930 ft -= -(100.nanoseconds());
1931 assert_eq!(ft, FileTime::new(1));
1932 }
1933
1934 {
1935 let mut ft = FileTime::MAX;
1936 ft -= -Span::new();
1937 assert_eq!(ft, FileTime::MAX);
1938 }
1939 {
1940 let mut ft = FileTime::MAX;
1941 ft -= -(1.nanosecond());
1942 assert_eq!(ft, FileTime::MAX);
1943 }
1944 {
1945 let mut ft = FileTime::MAX;
1946 ft -= -(99.nanoseconds());
1947 assert_eq!(ft, FileTime::MAX);
1948 }
1949 }
1950
1951 #[cfg(feature = "jiff")]
1952 #[test]
1953 #[should_panic(expected = "overflow when adding duration to date and time")]
1954 fn sub_assign_negative_jiff_span_with_overflow() {
1955 let mut ft = FileTime::MAX;
1956 ft -= -(100.nanoseconds());
1957 }
1958}