1use core::time::Duration;
10
11use super::{FILE_TIMES_PER_SEC, FileTime};
12use crate::error::{FileTimeRangeError, FileTimeRangeErrorKind};
13
14impl FileTime {
15 #[allow(clippy::missing_panics_doc)]
16 #[must_use]
44 #[inline]
45 pub fn to_unix_time(self) -> (i64, u32) {
46 let (secs, subsec_nanos) = (
47 self.to_unix_time_secs(),
48 u32::try_from((self.to_raw() % FILE_TIMES_PER_SEC) * 100)
49 .expect("the number of nanoseconds should be in the range of `u32`"),
50 );
51 (secs, subsec_nanos)
52 }
53
54 #[allow(clippy::missing_panics_doc)]
55 #[must_use]
71 #[inline]
72 pub fn to_unix_time_secs(self) -> i64 {
73 i64::try_from(self.to_raw() / FILE_TIMES_PER_SEC)
74 .expect("the number of seconds should be in the range of `i64`")
75 - 11_644_473_600
76 }
77
78 #[allow(clippy::missing_panics_doc)]
79 #[must_use]
101 #[inline]
102 pub fn to_unix_time_millis(self) -> i64 {
103 self.to_unix_time_nanos()
104 .div_euclid(1_000_000)
105 .try_into()
106 .expect("the number of milliseconds should be in the range of `i64`")
107 }
108
109 #[allow(clippy::missing_panics_doc)]
110 #[must_use]
135 #[inline]
136 pub fn to_unix_time_micros(self) -> i64 {
137 self.to_unix_time_nanos()
138 .div_euclid(1000)
139 .try_into()
140 .expect("the number of microseconds should be in the range of `i64`")
141 }
142
143 #[must_use]
168 #[inline]
169 pub fn to_unix_time_nanos(self) -> i128 {
170 (i128::from(self.to_raw()) * 100) - 11_644_473_600_000_000_000
171 }
172
173 #[inline]
225 pub fn from_unix_time(secs: i64, nanos: u32) -> Result<Self, FileTimeRangeError> {
226 Self::from_unix_time_secs(secs).and_then(|ft| {
227 ft.checked_add(Duration::from_nanos(nanos.into()))
228 .ok_or_else(|| FileTimeRangeErrorKind::Overflow.into())
229 })
230 }
231
232 #[inline]
267 pub fn from_unix_time_secs(secs: i64) -> Result<Self, FileTimeRangeError> {
268 if secs <= 1_833_029_933_770 {
269 u64::try_from(secs + 11_644_473_600)
270 .map_err(|_| FileTimeRangeErrorKind::Negative.into())
271 .map(|t| t * FILE_TIMES_PER_SEC)
272 .map(Self::new)
273 } else {
274 Err(FileTimeRangeErrorKind::Overflow.into())
275 }
276 }
277
278 #[inline]
313 pub fn from_unix_time_millis(millis: i64) -> Result<Self, FileTimeRangeError> {
314 let nanos = i128::from(millis) * 1_000_000;
315 Self::from_unix_time_nanos(nanos)
316 }
317
318 #[inline]
353 pub fn from_unix_time_micros(micros: i64) -> Result<Self, FileTimeRangeError> {
354 let nanos = i128::from(micros) * 1000;
355 Self::from_unix_time_nanos(nanos)
356 }
357
358 #[inline]
391 pub fn from_unix_time_nanos(nanos: i128) -> Result<Self, FileTimeRangeError> {
392 if nanos <= 1_833_029_933_770_955_161_500 {
393 (nanos + 11_644_473_600_000_000_000)
394 .div_euclid(100)
395 .try_into()
396 .map_err(|_| FileTimeRangeErrorKind::Negative.into())
397 .map(Self::new)
398 } else {
399 Err(FileTimeRangeErrorKind::Overflow.into())
400 }
401 }
402}
403
404#[cfg(test)]
405mod tests {
406 use super::*;
407
408 const NANOS_PER_SEC: u32 = 1_000_000_000;
409
410 #[test]
411 fn to_unix_time() {
412 assert_eq!(
413 FileTime::NT_TIME_EPOCH.to_unix_time(),
414 (-11_644_473_600, u32::MIN)
415 );
416 assert_eq!(FileTime::new(1).to_unix_time(), (-11_644_473_600, 100));
417 assert_eq!(
418 FileTime::new(FILE_TIMES_PER_SEC - 1).to_unix_time(),
419 (-11_644_473_600, NANOS_PER_SEC - 100)
420 );
421 assert_eq!(
422 FileTime::new(FILE_TIMES_PER_SEC).to_unix_time(),
423 (-11_644_473_599, u32::MIN)
424 );
425 assert_eq!(
426 (FileTime::UNIX_EPOCH - Duration::from_nanos(100)).to_unix_time(),
427 (i64::default() - 1, NANOS_PER_SEC - 100)
428 );
429 assert_eq!(
430 FileTime::UNIX_EPOCH.to_unix_time(),
431 (i64::default(), u32::MIN)
432 );
433 assert_eq!(
434 (FileTime::UNIX_EPOCH + Duration::from_nanos(100)).to_unix_time(),
435 (i64::default(), 100)
436 );
437 assert_eq!(
438 FileTime::SIGNED_MAX.to_unix_time(),
439 (910_692_730_085, 477_580_700)
440 );
441 assert_eq!(
442 (FileTime::MAX - Duration::from_nanos(100)).to_unix_time(),
443 (1_833_029_933_770, 955_161_400)
444 );
445 assert_eq!(
446 FileTime::MAX.to_unix_time(),
447 (1_833_029_933_770, 955_161_500)
448 );
449 }
450
451 #[cfg(feature = "std")]
452 #[test_strategy::proptest]
453 fn to_unix_time_roundtrip(ft: u64) {
454 use proptest::prop_assert;
455
456 let ts = FileTime::new(ft).to_unix_time();
457 prop_assert!((-11_644_473_600..=1_833_029_933_770).contains(&ts.0));
458 prop_assert!(ts.1 < NANOS_PER_SEC);
459 }
460
461 #[test]
462 fn to_unix_time_secs() {
463 assert_eq!(FileTime::NT_TIME_EPOCH.to_unix_time_secs(), -11_644_473_600);
464 assert_eq!(FileTime::new(1).to_unix_time_secs(), -11_644_473_600);
465 assert_eq!(
466 FileTime::new(FILE_TIMES_PER_SEC - 1).to_unix_time_secs(),
467 -11_644_473_600
468 );
469 assert_eq!(
470 FileTime::new(FILE_TIMES_PER_SEC).to_unix_time_secs(),
471 -11_644_473_599
472 );
473 assert_eq!(
474 (FileTime::UNIX_EPOCH - Duration::from_secs(1)).to_unix_time_secs(),
475 i64::default() - 1
476 );
477 assert_eq!(
478 (FileTime::UNIX_EPOCH - Duration::from_nanos(999_999_900)).to_unix_time_secs(),
479 i64::default() - 1
480 );
481 assert_eq!(
482 (FileTime::UNIX_EPOCH - Duration::from_nanos(100)).to_unix_time_secs(),
483 i64::default() - 1
484 );
485 assert_eq!(FileTime::UNIX_EPOCH.to_unix_time_secs(), i64::default());
486 assert_eq!(
487 (FileTime::UNIX_EPOCH + Duration::from_nanos(100)).to_unix_time_secs(),
488 i64::default()
489 );
490 assert_eq!(
491 (FileTime::UNIX_EPOCH + Duration::from_nanos(999_999_900)).to_unix_time_secs(),
492 i64::default()
493 );
494 assert_eq!(
495 (FileTime::UNIX_EPOCH + Duration::from_secs(1)).to_unix_time_secs(),
496 i64::default() + 1
497 );
498 assert_eq!(FileTime::SIGNED_MAX.to_unix_time_secs(), 910_692_730_085);
499 assert_eq!(
500 (FileTime::MAX - Duration::from_nanos(955_161_600)).to_unix_time_secs(),
501 1_833_029_933_769
502 );
503 assert_eq!(
504 (FileTime::MAX - Duration::from_nanos(955_161_500)).to_unix_time_secs(),
505 1_833_029_933_770
506 );
507 assert_eq!(
508 (FileTime::MAX - Duration::from_nanos(955_161_400)).to_unix_time_secs(),
509 1_833_029_933_770
510 );
511 assert_eq!(FileTime::MAX.to_unix_time_secs(), 1_833_029_933_770);
512 }
513
514 #[cfg(feature = "std")]
515 #[test_strategy::proptest]
516 fn to_unix_time_secs_roundtrip(ft: u64) {
517 use proptest::prop_assert;
518
519 let ts = FileTime::new(ft).to_unix_time_secs();
520 prop_assert!((-11_644_473_600..=1_833_029_933_770).contains(&ts));
521 }
522
523 #[test]
524 fn to_unix_time_millis() {
525 assert_eq!(
526 FileTime::NT_TIME_EPOCH.to_unix_time_millis(),
527 -11_644_473_600_000
528 );
529 assert_eq!(FileTime::new(1).to_unix_time_millis(), -11_644_473_600_000);
530 assert_eq!(
531 FileTime::new(9999).to_unix_time_millis(),
532 -11_644_473_600_000
533 );
534 assert_eq!(
535 FileTime::new(10000).to_unix_time_millis(),
536 -11_644_473_599_999
537 );
538 assert_eq!(
539 (FileTime::UNIX_EPOCH - Duration::from_millis(1)).to_unix_time_millis(),
540 i64::default() - 1
541 );
542 assert_eq!(
543 (FileTime::UNIX_EPOCH - Duration::from_nanos(999_900)).to_unix_time_millis(),
544 i64::default() - 1
545 );
546 assert_eq!(
547 (FileTime::UNIX_EPOCH - Duration::from_nanos(100)).to_unix_time_millis(),
548 i64::default() - 1
549 );
550 assert_eq!(FileTime::UNIX_EPOCH.to_unix_time_millis(), i64::default());
551 assert_eq!(
552 (FileTime::UNIX_EPOCH + Duration::from_nanos(999_900)).to_unix_time_millis(),
553 i64::default()
554 );
555 assert_eq!(
556 (FileTime::UNIX_EPOCH + Duration::from_nanos(100)).to_unix_time_millis(),
557 i64::default()
558 );
559 assert_eq!(
560 (FileTime::UNIX_EPOCH + Duration::from_millis(1)).to_unix_time_millis(),
561 i64::default() + 1
562 );
563 assert_eq!(
564 FileTime::SIGNED_MAX.to_unix_time_millis(),
565 910_692_730_085_477
566 );
567 assert_eq!(
568 (FileTime::MAX - Duration::from_nanos(161_600)).to_unix_time_millis(),
569 1_833_029_933_770_954
570 );
571 assert_eq!(
572 (FileTime::MAX - Duration::from_nanos(161_500)).to_unix_time_millis(),
573 1_833_029_933_770_955
574 );
575 assert_eq!(
576 (FileTime::MAX - Duration::from_nanos(161_400)).to_unix_time_millis(),
577 1_833_029_933_770_955
578 );
579 assert_eq!(FileTime::MAX.to_unix_time_millis(), 1_833_029_933_770_955);
580 }
581
582 #[cfg(feature = "std")]
583 #[test_strategy::proptest]
584 fn to_unix_time_millis_roundtrip(ft: u64) {
585 use proptest::prop_assert;
586
587 let ts = FileTime::new(ft).to_unix_time_millis();
588 prop_assert!((-11_644_473_600_000..=1_833_029_933_770_955).contains(&ts));
589 }
590
591 #[test]
592 fn to_unix_time_micros() {
593 assert_eq!(
594 FileTime::NT_TIME_EPOCH.to_unix_time_micros(),
595 -11_644_473_600_000_000
596 );
597 assert_eq!(
598 FileTime::new(1).to_unix_time_micros(),
599 -11_644_473_600_000_000
600 );
601 assert_eq!(
602 FileTime::new(9).to_unix_time_micros(),
603 -11_644_473_600_000_000
604 );
605 assert_eq!(
606 FileTime::new(10).to_unix_time_micros(),
607 -11_644_473_599_999_999
608 );
609 assert_eq!(
610 (FileTime::UNIX_EPOCH - Duration::from_micros(1)).to_unix_time_micros(),
611 i64::default() - 1
612 );
613 assert_eq!(
614 (FileTime::UNIX_EPOCH - Duration::from_nanos(900)).to_unix_time_micros(),
615 i64::default() - 1
616 );
617 assert_eq!(
618 (FileTime::UNIX_EPOCH - Duration::from_nanos(100)).to_unix_time_micros(),
619 i64::default() - 1
620 );
621 assert_eq!(FileTime::UNIX_EPOCH.to_unix_time_micros(), i64::default());
622 assert_eq!(
623 (FileTime::UNIX_EPOCH + Duration::from_nanos(100)).to_unix_time_micros(),
624 i64::default()
625 );
626 assert_eq!(
627 (FileTime::UNIX_EPOCH + Duration::from_nanos(900)).to_unix_time_micros(),
628 i64::default()
629 );
630 assert_eq!(
631 (FileTime::UNIX_EPOCH + Duration::from_micros(1)).to_unix_time_micros(),
632 i64::default() + 1
633 );
634 assert_eq!(
635 FileTime::SIGNED_MAX.to_unix_time_micros(),
636 910_692_730_085_477_580
637 );
638 assert_eq!(
639 (FileTime::MAX - Duration::from_nanos(600)).to_unix_time_micros(),
640 1_833_029_933_770_955_160
641 );
642 assert_eq!(
643 (FileTime::MAX - Duration::from_nanos(500)).to_unix_time_micros(),
644 1_833_029_933_770_955_161
645 );
646 assert_eq!(
647 (FileTime::MAX - Duration::from_nanos(400)).to_unix_time_micros(),
648 1_833_029_933_770_955_161
649 );
650 assert_eq!(
651 FileTime::MAX.to_unix_time_micros(),
652 1_833_029_933_770_955_161
653 );
654 }
655
656 #[cfg(feature = "std")]
657 #[test_strategy::proptest]
658 fn to_unix_time_micros_roundtrip(ft: u64) {
659 use proptest::prop_assert;
660
661 let ts = FileTime::new(ft).to_unix_time_micros();
662 prop_assert!((-11_644_473_600_000_000..=1_833_029_933_770_955_161).contains(&ts));
663 }
664
665 #[test]
666 fn to_unix_time_nanos() {
667 assert_eq!(
668 FileTime::NT_TIME_EPOCH.to_unix_time_nanos(),
669 -11_644_473_600_000_000_000
670 );
671 assert_eq!(
672 FileTime::new(1).to_unix_time_nanos(),
673 -11_644_473_599_999_999_900
674 );
675 assert_eq!(
676 FileTime::new(FILE_TIMES_PER_SEC - 1).to_unix_time_nanos(),
677 -11_644_473_599_000_000_100
678 );
679 assert_eq!(
680 FileTime::new(FILE_TIMES_PER_SEC).to_unix_time_nanos(),
681 -11_644_473_599_000_000_000
682 );
683 assert_eq!(
684 (FileTime::UNIX_EPOCH - Duration::from_nanos(100)).to_unix_time_nanos(),
685 i128::default() - 100
686 );
687 assert_eq!(FileTime::UNIX_EPOCH.to_unix_time_nanos(), i128::default());
688 assert_eq!(
689 (FileTime::UNIX_EPOCH + Duration::from_nanos(100)).to_unix_time_nanos(),
690 i128::default() + 100
691 );
692 assert_eq!(
693 FileTime::SIGNED_MAX.to_unix_time_nanos(),
694 910_692_730_085_477_580_700
695 );
696 assert_eq!(
697 (FileTime::MAX - Duration::from_nanos(100)).to_unix_time_nanos(),
698 1_833_029_933_770_955_161_400
699 );
700 assert_eq!(
701 FileTime::MAX.to_unix_time_nanos(),
702 1_833_029_933_770_955_161_500
703 );
704 }
705
706 #[cfg(feature = "std")]
707 #[test_strategy::proptest]
708 fn to_unix_time_nanos_roundtrip(ft: u64) {
709 use proptest::prop_assert;
710
711 let ts = FileTime::new(ft).to_unix_time_nanos();
712 prop_assert!((-11_644_473_600_000_000_000..=1_833_029_933_770_955_161_500).contains(&ts));
713 }
714
715 #[test]
716 fn from_unix_time_before_nt_time_epoch() {
717 assert_eq!(
718 FileTime::from_unix_time(-11_644_473_601, u32::MAX).unwrap_err(),
719 FileTimeRangeErrorKind::Negative.into()
720 );
721 assert_eq!(
722 FileTime::from_unix_time(-11_644_473_601, NANOS_PER_SEC).unwrap_err(),
723 FileTimeRangeErrorKind::Negative.into()
724 );
725 assert_eq!(
726 FileTime::from_unix_time(-11_644_473_601, NANOS_PER_SEC - 1).unwrap_err(),
727 FileTimeRangeErrorKind::Negative.into()
728 );
729 assert_eq!(
730 FileTime::from_unix_time(-11_644_473_601, NANOS_PER_SEC - 99).unwrap_err(),
731 FileTimeRangeErrorKind::Negative.into()
732 );
733 assert_eq!(
734 FileTime::from_unix_time(-11_644_473_601, NANOS_PER_SEC - 100).unwrap_err(),
735 FileTimeRangeErrorKind::Negative.into()
736 );
737 assert_eq!(
738 FileTime::from_unix_time(-11_644_473_601, u32::MIN).unwrap_err(),
739 FileTimeRangeErrorKind::Negative.into()
740 );
741 assert_eq!(
742 FileTime::from_unix_time(i64::MIN, u32::MAX).unwrap_err(),
743 FileTimeRangeErrorKind::Negative.into()
744 );
745 assert_eq!(
746 FileTime::from_unix_time(i64::MIN, NANOS_PER_SEC).unwrap_err(),
747 FileTimeRangeErrorKind::Negative.into()
748 );
749 assert_eq!(
750 FileTime::from_unix_time(i64::MIN, NANOS_PER_SEC - 1).unwrap_err(),
751 FileTimeRangeErrorKind::Negative.into()
752 );
753 assert_eq!(
754 FileTime::from_unix_time(i64::MIN, u32::MIN).unwrap_err(),
755 FileTimeRangeErrorKind::Negative.into()
756 );
757 }
758
759 #[cfg(feature = "std")]
760 #[test_strategy::proptest]
761 fn from_unix_time_before_nt_time_epoch_roundtrip(
762 #[strategy(..=-11_644_473_601_i64)] secs: i64,
763 nanos: u32,
764 ) {
765 use proptest::prop_assert_eq;
766
767 prop_assert_eq!(
768 FileTime::from_unix_time(secs, nanos).unwrap_err(),
769 FileTimeRangeErrorKind::Negative.into()
770 );
771 }
772
773 #[test]
774 fn from_unix_time() {
775 assert_eq!(
776 FileTime::from_unix_time(-11_644_473_600, 0).unwrap(),
777 FileTime::NT_TIME_EPOCH
778 );
779 assert_eq!(
780 FileTime::from_unix_time(-11_644_473_600, 1).unwrap(),
781 FileTime::NT_TIME_EPOCH
782 );
783 assert_eq!(
784 FileTime::from_unix_time(-11_644_473_600, 99).unwrap(),
785 FileTime::NT_TIME_EPOCH
786 );
787 assert_eq!(
788 FileTime::from_unix_time(-11_644_473_600, 100).unwrap(),
789 FileTime::new(1)
790 );
791 assert_eq!(
792 FileTime::from_unix_time(-11_644_473_600, NANOS_PER_SEC - 100).unwrap(),
793 FileTime::new(FILE_TIMES_PER_SEC - 1)
794 );
795 assert_eq!(
796 FileTime::from_unix_time(-11_644_473_600, NANOS_PER_SEC - 99).unwrap(),
797 FileTime::new(FILE_TIMES_PER_SEC - 1)
798 );
799 assert_eq!(
800 FileTime::from_unix_time(-11_644_473_600, NANOS_PER_SEC - 1).unwrap(),
801 FileTime::new(FILE_TIMES_PER_SEC - 1)
802 );
803 assert_eq!(
804 FileTime::from_unix_time(-11_644_473_600, NANOS_PER_SEC).unwrap(),
805 FileTime::new(FILE_TIMES_PER_SEC)
806 );
807 assert_eq!(
808 FileTime::from_unix_time(-11_644_473_599, 0).unwrap(),
809 FileTime::new(FILE_TIMES_PER_SEC)
810 );
811 assert_eq!(
812 FileTime::from_unix_time(i64::default() - 1, NANOS_PER_SEC - 100).unwrap(),
813 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
814 );
815 assert_eq!(
816 FileTime::from_unix_time(i64::default() - 1, NANOS_PER_SEC - 99).unwrap(),
817 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
818 );
819 assert_eq!(
820 FileTime::from_unix_time(i64::default() - 1, NANOS_PER_SEC - 1).unwrap(),
821 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
822 );
823 assert_eq!(
824 FileTime::from_unix_time(i64::default() - 1, NANOS_PER_SEC).unwrap(),
825 FileTime::UNIX_EPOCH
826 );
827 assert_eq!(
828 FileTime::from_unix_time(i64::default(), u32::MIN).unwrap(),
829 FileTime::UNIX_EPOCH
830 );
831 assert_eq!(
832 FileTime::from_unix_time(i64::default(), 1).unwrap(),
833 FileTime::UNIX_EPOCH
834 );
835 assert_eq!(
836 FileTime::from_unix_time(i64::default(), 99).unwrap(),
837 FileTime::UNIX_EPOCH
838 );
839 assert_eq!(
840 FileTime::from_unix_time(i64::default(), 100).unwrap(),
841 FileTime::UNIX_EPOCH + Duration::from_nanos(100)
842 );
843 assert_eq!(
844 FileTime::from_unix_time(910_692_730_085, 477_580_700).unwrap(),
845 FileTime::SIGNED_MAX
846 );
847 assert_eq!(
848 FileTime::from_unix_time(1_833_029_933_770, 955_161_500).unwrap(),
849 FileTime::MAX
850 );
851 assert_eq!(
852 FileTime::from_unix_time(1_833_029_933_770, 955_161_501).unwrap(),
853 FileTime::MAX
854 );
855 assert_eq!(
856 FileTime::from_unix_time(1_833_029_933_770, 955_161_599).unwrap(),
857 FileTime::MAX
858 );
859 }
860
861 #[cfg(feature = "std")]
862 #[test_strategy::proptest]
863 fn from_unix_time_roundtrip(
864 #[strategy(-11_644_473_600..=1_833_029_933_770_i64)] secs: i64,
865 #[strategy(..NANOS_PER_SEC)] nanos: u32,
866 ) {
867 use proptest::{prop_assert, prop_assume};
868
869 if secs == 1_833_029_933_770 {
870 prop_assume!(nanos < 955_161_600);
871 }
872
873 prop_assert!(FileTime::from_unix_time(secs, nanos).is_ok());
874 }
875
876 #[test]
877 fn from_unix_time_with_too_big_date_time() {
878 assert_eq!(
879 FileTime::from_unix_time(1_833_029_933_770, 955_161_600).unwrap_err(),
880 FileTimeRangeErrorKind::Overflow.into()
881 );
882 assert_eq!(
883 FileTime::from_unix_time(1_833_029_933_770, NANOS_PER_SEC - 1).unwrap_err(),
884 FileTimeRangeErrorKind::Overflow.into()
885 );
886 assert_eq!(
887 FileTime::from_unix_time(1_833_029_933_770, NANOS_PER_SEC).unwrap_err(),
888 FileTimeRangeErrorKind::Overflow.into()
889 );
890 assert_eq!(
891 FileTime::from_unix_time(1_833_029_933_770, u32::MAX).unwrap_err(),
892 FileTimeRangeErrorKind::Overflow.into()
893 );
894 assert_eq!(
895 FileTime::from_unix_time(i64::MAX, u32::MIN).unwrap_err(),
896 FileTimeRangeErrorKind::Overflow.into()
897 );
898 assert_eq!(
899 FileTime::from_unix_time(i64::MAX, NANOS_PER_SEC - 1).unwrap_err(),
900 FileTimeRangeErrorKind::Overflow.into()
901 );
902 assert_eq!(
903 FileTime::from_unix_time(i64::MAX, NANOS_PER_SEC).unwrap_err(),
904 FileTimeRangeErrorKind::Overflow.into()
905 );
906 assert_eq!(
907 FileTime::from_unix_time(i64::MAX, u32::MAX).unwrap_err(),
908 FileTimeRangeErrorKind::Overflow.into()
909 );
910 }
911
912 #[cfg(feature = "std")]
913 #[test_strategy::proptest]
914 fn from_unix_time_with_too_big_date_time_roundtrip(
915 #[strategy(1_833_029_933_770_i64..)] secs: i64,
916 #[strategy(..NANOS_PER_SEC)] nanos: u32,
917 ) {
918 use proptest::{prop_assert_eq, prop_assume};
919
920 if secs == 1_833_029_933_770 {
921 prop_assume!(nanos >= 955_161_600);
922 }
923
924 prop_assert_eq!(
925 FileTime::from_unix_time(secs, nanos).unwrap_err(),
926 FileTimeRangeErrorKind::Overflow.into()
927 );
928 }
929
930 #[test]
931 fn from_unix_time_secs_before_nt_time_epoch() {
932 assert_eq!(
933 FileTime::from_unix_time_secs(-11_644_473_601).unwrap_err(),
934 FileTimeRangeErrorKind::Negative.into()
935 );
936 assert_eq!(
937 FileTime::from_unix_time_secs(i64::MIN).unwrap_err(),
938 FileTimeRangeErrorKind::Negative.into()
939 );
940 }
941
942 #[cfg(feature = "std")]
943 #[test_strategy::proptest]
944 fn from_unix_time_secs_before_nt_time_epoch_roundtrip(
945 #[strategy(..=-11_644_473_601_i64)] ts: i64,
946 ) {
947 use proptest::prop_assert_eq;
948
949 prop_assert_eq!(
950 FileTime::from_unix_time_secs(ts).unwrap_err(),
951 FileTimeRangeErrorKind::Negative.into()
952 );
953 }
954
955 #[test]
956 fn from_unix_time_secs() {
957 assert_eq!(
958 FileTime::from_unix_time_secs(-11_644_473_600).unwrap(),
959 FileTime::NT_TIME_EPOCH
960 );
961 assert_eq!(
962 FileTime::from_unix_time_secs(-11_644_473_599).unwrap(),
963 FileTime::new(FILE_TIMES_PER_SEC)
964 );
965 assert_eq!(
966 FileTime::from_unix_time_secs(i64::default() - 1).unwrap(),
967 FileTime::UNIX_EPOCH - Duration::from_secs(1)
968 );
969 assert_eq!(
970 FileTime::from_unix_time_secs(i64::default()).unwrap(),
971 FileTime::UNIX_EPOCH
972 );
973 assert_eq!(
974 FileTime::from_unix_time_secs(i64::default() + 1).unwrap(),
975 FileTime::UNIX_EPOCH + Duration::from_secs(1)
976 );
977 assert_eq!(
978 FileTime::from_unix_time_secs(910_692_730_085).unwrap(),
979 FileTime::SIGNED_MAX - Duration::from_nanos(477_580_700)
980 );
981 assert_eq!(
982 FileTime::from_unix_time_secs(1_833_029_933_770).unwrap(),
983 FileTime::MAX - Duration::from_nanos(955_161_500)
984 );
985 }
986
987 #[cfg(feature = "std")]
988 #[test_strategy::proptest]
989 fn from_unix_time_secs_roundtrip(#[strategy(-11_644_473_600..=1_833_029_933_770_i64)] ts: i64) {
990 use proptest::prop_assert;
991
992 prop_assert!(FileTime::from_unix_time_secs(ts).is_ok());
993 }
994
995 #[test]
996 fn from_unix_time_secs_with_too_big_date_time() {
997 assert_eq!(
998 FileTime::from_unix_time_secs(1_833_029_933_771).unwrap_err(),
999 FileTimeRangeErrorKind::Overflow.into()
1000 );
1001 assert_eq!(
1002 FileTime::from_unix_time_secs(i64::MAX).unwrap_err(),
1003 FileTimeRangeErrorKind::Overflow.into()
1004 );
1005 }
1006
1007 #[cfg(feature = "std")]
1008 #[test_strategy::proptest]
1009 fn from_unix_time_secs_with_too_big_date_time_roundtrip(
1010 #[strategy(1_833_029_933_771_i64..)] ts: i64,
1011 ) {
1012 use proptest::prop_assert_eq;
1013
1014 prop_assert_eq!(
1015 FileTime::from_unix_time_secs(ts).unwrap_err(),
1016 FileTimeRangeErrorKind::Overflow.into()
1017 );
1018 }
1019
1020 #[test]
1021 fn from_unix_time_millis_before_nt_time_epoch() {
1022 assert_eq!(
1023 FileTime::from_unix_time_millis(-11_644_473_600_001).unwrap_err(),
1024 FileTimeRangeErrorKind::Negative.into()
1025 );
1026 assert_eq!(
1027 FileTime::from_unix_time_millis(i64::MIN).unwrap_err(),
1028 FileTimeRangeErrorKind::Negative.into()
1029 );
1030 }
1031
1032 #[cfg(feature = "std")]
1033 #[test_strategy::proptest]
1034 fn from_unix_time_millis_before_nt_time_epoch_roundtrip(
1035 #[strategy(..=-11_644_473_600_001_i64)] ts: i64,
1036 ) {
1037 use proptest::prop_assert_eq;
1038
1039 prop_assert_eq!(
1040 FileTime::from_unix_time_millis(ts).unwrap_err(),
1041 FileTimeRangeErrorKind::Negative.into()
1042 );
1043 }
1044
1045 #[test]
1046 fn from_unix_time_millis() {
1047 assert_eq!(
1048 FileTime::from_unix_time_millis(-11_644_473_600_000).unwrap(),
1049 FileTime::NT_TIME_EPOCH
1050 );
1051 assert_eq!(
1052 FileTime::from_unix_time_millis(-11_644_473_599_999).unwrap(),
1053 FileTime::new(10000)
1054 );
1055 assert_eq!(
1056 FileTime::from_unix_time_millis(i64::default() - 1).unwrap(),
1057 FileTime::UNIX_EPOCH - Duration::from_millis(1)
1058 );
1059 assert_eq!(
1060 FileTime::from_unix_time_millis(i64::default()).unwrap(),
1061 FileTime::UNIX_EPOCH
1062 );
1063 assert_eq!(
1064 FileTime::from_unix_time_millis(i64::default() + 1).unwrap(),
1065 FileTime::UNIX_EPOCH + Duration::from_millis(1)
1066 );
1067 assert_eq!(
1068 FileTime::from_unix_time_millis(910_692_730_085_477).unwrap(),
1069 FileTime::SIGNED_MAX - Duration::from_nanos(580_700)
1070 );
1071 assert_eq!(
1072 FileTime::from_unix_time_millis(1_833_029_933_770_955).unwrap(),
1073 FileTime::MAX - Duration::from_nanos(161_500)
1074 );
1075 }
1076
1077 #[cfg(feature = "std")]
1078 #[test_strategy::proptest]
1079 fn from_unix_time_millis_roundtrip(
1080 #[strategy(-11_644_473_600_000..=1_833_029_933_770_955_i64)] ts: i64,
1081 ) {
1082 use proptest::prop_assert;
1083
1084 prop_assert!(FileTime::from_unix_time_millis(ts).is_ok());
1085 }
1086
1087 #[test]
1088 fn from_unix_time_millis_with_too_big_date_time() {
1089 assert_eq!(
1090 FileTime::from_unix_time_millis(1_833_029_933_770_956).unwrap_err(),
1091 FileTimeRangeErrorKind::Overflow.into()
1092 );
1093 assert_eq!(
1094 FileTime::from_unix_time_millis(i64::MAX).unwrap_err(),
1095 FileTimeRangeErrorKind::Overflow.into()
1096 );
1097 }
1098
1099 #[cfg(feature = "std")]
1100 #[test_strategy::proptest]
1101 fn from_unix_time_millis_with_too_big_date_time_roundtrip(
1102 #[strategy(1_833_029_933_770_956_i64..)] ts: i64,
1103 ) {
1104 use proptest::prop_assert_eq;
1105
1106 prop_assert_eq!(
1107 FileTime::from_unix_time_millis(ts).unwrap_err(),
1108 FileTimeRangeErrorKind::Overflow.into()
1109 );
1110 }
1111
1112 #[test]
1113 fn from_unix_time_micros_before_nt_time_epoch() {
1114 assert_eq!(
1115 FileTime::from_unix_time_micros(-11_644_473_600_000_001).unwrap_err(),
1116 FileTimeRangeErrorKind::Negative.into()
1117 );
1118 assert_eq!(
1119 FileTime::from_unix_time_micros(i64::MIN).unwrap_err(),
1120 FileTimeRangeErrorKind::Negative.into()
1121 );
1122 }
1123
1124 #[cfg(feature = "std")]
1125 #[test_strategy::proptest]
1126 fn from_unix_time_micros_before_nt_time_epoch_roundtrip(
1127 #[strategy(..=-11_644_473_600_000_001_i64)] ts: i64,
1128 ) {
1129 use proptest::prop_assert_eq;
1130
1131 prop_assert_eq!(
1132 FileTime::from_unix_time_micros(ts).unwrap_err(),
1133 FileTimeRangeErrorKind::Negative.into()
1134 );
1135 }
1136
1137 #[test]
1138 fn from_unix_time_micros() {
1139 assert_eq!(
1140 FileTime::from_unix_time_micros(-11_644_473_600_000_000).unwrap(),
1141 FileTime::NT_TIME_EPOCH
1142 );
1143 assert_eq!(
1144 FileTime::from_unix_time_micros(-11_644_473_599_999_999).unwrap(),
1145 FileTime::new(10)
1146 );
1147 assert_eq!(
1148 FileTime::from_unix_time_micros(i64::default() - 1).unwrap(),
1149 FileTime::UNIX_EPOCH - Duration::from_micros(1)
1150 );
1151 assert_eq!(
1152 FileTime::from_unix_time_micros(i64::default()).unwrap(),
1153 FileTime::UNIX_EPOCH
1154 );
1155 assert_eq!(
1156 FileTime::from_unix_time_micros(i64::default() + 1).unwrap(),
1157 FileTime::UNIX_EPOCH + Duration::from_micros(1)
1158 );
1159 assert_eq!(
1160 FileTime::from_unix_time_micros(910_692_730_085_477_580).unwrap(),
1161 FileTime::SIGNED_MAX - Duration::from_nanos(700)
1162 );
1163 assert_eq!(
1164 FileTime::from_unix_time_micros(1_833_029_933_770_955_161).unwrap(),
1165 FileTime::MAX - Duration::from_nanos(500)
1166 );
1167 }
1168
1169 #[cfg(feature = "std")]
1170 #[test_strategy::proptest]
1171 fn from_unix_time_micros_roundtrip(
1172 #[strategy(-11_644_473_600_000_000..=1_833_029_933_770_955_161_i64)] ts: i64,
1173 ) {
1174 use proptest::prop_assert;
1175
1176 prop_assert!(FileTime::from_unix_time_micros(ts).is_ok());
1177 }
1178
1179 #[test]
1180 fn from_unix_time_micros_with_too_big_date_time() {
1181 assert_eq!(
1182 FileTime::from_unix_time_micros(1_833_029_933_770_955_162).unwrap_err(),
1183 FileTimeRangeErrorKind::Overflow.into()
1184 );
1185 assert_eq!(
1186 FileTime::from_unix_time_micros(i64::MAX).unwrap_err(),
1187 FileTimeRangeErrorKind::Overflow.into()
1188 );
1189 }
1190
1191 #[cfg(feature = "std")]
1192 #[test_strategy::proptest]
1193 fn from_unix_time_micros_with_too_big_date_time_roundtrip(
1194 #[strategy(1_833_029_933_770_955_162_i64..)] ts: i64,
1195 ) {
1196 use proptest::prop_assert_eq;
1197
1198 prop_assert_eq!(
1199 FileTime::from_unix_time_micros(ts).unwrap_err(),
1200 FileTimeRangeErrorKind::Overflow.into()
1201 );
1202 }
1203
1204 #[test]
1205 fn from_unix_time_nanos_before_nt_time_epoch() {
1206 assert_eq!(
1207 FileTime::from_unix_time_nanos(-11_644_473_600_000_000_100).unwrap_err(),
1208 FileTimeRangeErrorKind::Negative.into()
1209 );
1210 assert_eq!(
1211 FileTime::from_unix_time_nanos(-11_644_473_600_000_000_099).unwrap_err(),
1212 FileTimeRangeErrorKind::Negative.into()
1213 );
1214 assert_eq!(
1215 FileTime::from_unix_time_nanos(-11_644_473_600_000_000_001).unwrap_err(),
1216 FileTimeRangeErrorKind::Negative.into()
1217 );
1218 assert_eq!(
1219 FileTime::from_unix_time_nanos(i128::MIN).unwrap_err(),
1220 FileTimeRangeErrorKind::Negative.into()
1221 );
1222 }
1223
1224 #[cfg(feature = "std")]
1225 #[test_strategy::proptest]
1226 fn from_unix_time_nanos_before_nt_time_epoch_roundtrip(
1227 #[strategy(..=-11_644_473_600_000_000_001_i128)] ts: i128,
1228 ) {
1229 use proptest::prop_assert_eq;
1230
1231 prop_assert_eq!(
1232 FileTime::from_unix_time_nanos(ts).unwrap_err(),
1233 FileTimeRangeErrorKind::Negative.into()
1234 );
1235 }
1236
1237 #[test]
1238 fn from_unix_time_nanos() {
1239 assert_eq!(
1240 FileTime::from_unix_time_nanos(-11_644_473_600_000_000_000).unwrap(),
1241 FileTime::NT_TIME_EPOCH
1242 );
1243 assert_eq!(
1244 FileTime::from_unix_time_nanos(-11_644_473_599_999_999_999).unwrap(),
1245 FileTime::NT_TIME_EPOCH
1246 );
1247 assert_eq!(
1248 FileTime::from_unix_time_nanos(-11_644_473_599_999_999_901).unwrap(),
1249 FileTime::NT_TIME_EPOCH
1250 );
1251 assert_eq!(
1252 FileTime::from_unix_time_nanos(-11_644_473_599_999_999_900).unwrap(),
1253 FileTime::new(1)
1254 );
1255 assert_eq!(
1256 FileTime::from_unix_time_nanos(-11_644_473_599_000_000_100).unwrap(),
1257 FileTime::new(FILE_TIMES_PER_SEC - 1)
1258 );
1259 assert_eq!(
1260 FileTime::from_unix_time_nanos(-11_644_473_599_000_000_099).unwrap(),
1261 FileTime::new(FILE_TIMES_PER_SEC - 1)
1262 );
1263 assert_eq!(
1264 FileTime::from_unix_time_nanos(-11_644_473_599_000_000_001).unwrap(),
1265 FileTime::new(FILE_TIMES_PER_SEC - 1)
1266 );
1267 assert_eq!(
1268 FileTime::from_unix_time_nanos(-11_644_473_599_000_000_000).unwrap(),
1269 FileTime::new(FILE_TIMES_PER_SEC)
1270 );
1271 assert_eq!(
1272 FileTime::from_unix_time_nanos(i128::default() - 100).unwrap(),
1273 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
1274 );
1275 assert_eq!(
1276 FileTime::from_unix_time_nanos(i128::default() - 99).unwrap(),
1277 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
1278 );
1279 assert_eq!(
1280 FileTime::from_unix_time_nanos(i128::default() - 1).unwrap(),
1281 FileTime::UNIX_EPOCH - Duration::from_nanos(100)
1282 );
1283 assert_eq!(
1284 FileTime::from_unix_time_nanos(i128::default()).unwrap(),
1285 FileTime::UNIX_EPOCH
1286 );
1287 assert_eq!(
1288 FileTime::from_unix_time_nanos(i128::default() + 1).unwrap(),
1289 FileTime::UNIX_EPOCH
1290 );
1291 assert_eq!(
1292 FileTime::from_unix_time_nanos(i128::default() + 99).unwrap(),
1293 FileTime::UNIX_EPOCH
1294 );
1295 assert_eq!(
1296 FileTime::from_unix_time_nanos(i128::default() + 100).unwrap(),
1297 FileTime::UNIX_EPOCH + Duration::from_nanos(100)
1298 );
1299 assert_eq!(
1300 FileTime::from_unix_time_nanos(910_692_730_085_477_580_700).unwrap(),
1301 FileTime::SIGNED_MAX
1302 );
1303 assert_eq!(
1304 FileTime::from_unix_time_nanos(1_833_029_933_770_955_161_500).unwrap(),
1305 FileTime::MAX
1306 );
1307 }
1308
1309 #[cfg(feature = "std")]
1310 #[test_strategy::proptest]
1311 fn from_unix_time_nanos_roundtrip(
1312 #[strategy(-11_644_473_600_000_000_000..=1_833_029_933_770_955_161_500_i128)] ts: i128,
1313 ) {
1314 use proptest::prop_assert;
1315
1316 prop_assert!(FileTime::from_unix_time_nanos(ts).is_ok());
1317 }
1318
1319 #[test]
1320 fn from_unix_time_nanos_with_too_big_date_time() {
1321 assert_eq!(
1322 FileTime::from_unix_time_nanos(1_833_029_933_770_955_161_501).unwrap_err(),
1323 FileTimeRangeErrorKind::Overflow.into()
1324 );
1325 assert_eq!(
1326 FileTime::from_unix_time_nanos(i128::MAX).unwrap_err(),
1327 FileTimeRangeErrorKind::Overflow.into()
1328 );
1329 }
1330
1331 #[cfg(feature = "std")]
1332 #[test_strategy::proptest]
1333 fn from_unix_time_nanos_with_too_big_date_time_roundtrip(
1334 #[strategy(1_833_029_933_770_955_161_501_i128..)] ts: i128,
1335 ) {
1336 use proptest::prop_assert_eq;
1337
1338 prop_assert_eq!(
1339 FileTime::from_unix_time_nanos(ts).unwrap_err(),
1340 FileTimeRangeErrorKind::Overflow.into()
1341 );
1342 }
1343}