nt_time/file_time/
ops.rs

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