nt_time/file_time/
cmp.rs

1// SPDX-FileCopyrightText: 2023 Shun Sakai
2//
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Utilities for comparing and ordering values.
6
7use core::cmp::Ordering;
8
9use time::OffsetDateTime;
10
11use super::FileTime;
12
13#[cfg(feature = "std")]
14impl PartialEq<FileTime> for std::time::SystemTime {
15    #[inline]
16    fn eq(&self, other: &FileTime) -> bool {
17        self == &Self::from(*other)
18    }
19}
20
21#[cfg(feature = "std")]
22impl PartialEq<std::time::SystemTime> for FileTime {
23    #[inline]
24    fn eq(&self, other: &std::time::SystemTime) -> bool {
25        use std::time::SystemTime;
26
27        &SystemTime::from(*self) == other
28    }
29}
30
31impl PartialEq<FileTime> for OffsetDateTime {
32    #[inline]
33    fn eq(&self, other: &FileTime) -> bool {
34        self == &Self::try_from(*other).expect("`other` is out of range for `OffsetDateTime`")
35    }
36}
37
38impl PartialEq<OffsetDateTime> for FileTime {
39    #[inline]
40    fn eq(&self, other: &OffsetDateTime) -> bool {
41        &OffsetDateTime::try_from(*self).expect("`self` is out of range for `OffsetDateTime`")
42            == other
43    }
44}
45
46#[cfg(feature = "chrono")]
47impl PartialEq<FileTime> for chrono::DateTime<chrono::Utc> {
48    #[inline]
49    fn eq(&self, other: &FileTime) -> bool {
50        self == &Self::from(*other)
51    }
52}
53
54#[cfg(feature = "chrono")]
55impl PartialEq<chrono::DateTime<chrono::Utc>> for FileTime {
56    #[inline]
57    fn eq(&self, other: &chrono::DateTime<chrono::Utc>) -> bool {
58        use chrono::{DateTime, Utc};
59
60        &DateTime::<Utc>::from(*self) == other
61    }
62}
63
64#[cfg(feature = "std")]
65impl PartialOrd<FileTime> for std::time::SystemTime {
66    #[inline]
67    fn partial_cmp(&self, other: &FileTime) -> Option<Ordering> {
68        self.partial_cmp(&Self::from(*other))
69    }
70}
71
72#[cfg(feature = "std")]
73impl PartialOrd<std::time::SystemTime> for FileTime {
74    #[inline]
75    fn partial_cmp(&self, other: &std::time::SystemTime) -> Option<Ordering> {
76        use std::time::SystemTime;
77
78        SystemTime::from(*self).partial_cmp(other)
79    }
80}
81
82impl PartialOrd<FileTime> for OffsetDateTime {
83    #[inline]
84    fn partial_cmp(&self, other: &FileTime) -> Option<Ordering> {
85        self.partial_cmp(
86            &Self::try_from(*other).expect("`other` is out of range for `OffsetDateTime`"),
87        )
88    }
89}
90
91impl PartialOrd<OffsetDateTime> for FileTime {
92    #[inline]
93    fn partial_cmp(&self, other: &OffsetDateTime) -> Option<Ordering> {
94        OffsetDateTime::try_from(*self)
95            .expect("`self` is out of range for `OffsetDateTime`")
96            .partial_cmp(other)
97    }
98}
99
100#[cfg(feature = "chrono")]
101impl PartialOrd<FileTime> for chrono::DateTime<chrono::Utc> {
102    #[inline]
103    fn partial_cmp(&self, other: &FileTime) -> Option<Ordering> {
104        self.partial_cmp(&Self::from(*other))
105    }
106}
107
108#[cfg(feature = "chrono")]
109impl PartialOrd<chrono::DateTime<chrono::Utc>> for FileTime {
110    #[inline]
111    fn partial_cmp(&self, other: &chrono::DateTime<chrono::Utc>) -> Option<Ordering> {
112        use chrono::{DateTime, Utc};
113
114        DateTime::<Utc>::from(*self).partial_cmp(other)
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use time::macros::datetime;
121
122    use super::*;
123
124    #[test]
125    fn equality() {
126        assert_eq!(FileTime::NT_TIME_EPOCH, FileTime::NT_TIME_EPOCH);
127        assert_ne!(FileTime::NT_TIME_EPOCH, FileTime::UNIX_EPOCH);
128        assert_ne!(FileTime::NT_TIME_EPOCH, FileTime::MAX);
129        assert_ne!(FileTime::UNIX_EPOCH, FileTime::NT_TIME_EPOCH);
130        assert_eq!(FileTime::UNIX_EPOCH, FileTime::UNIX_EPOCH);
131        assert_ne!(FileTime::UNIX_EPOCH, FileTime::MAX);
132        assert_ne!(FileTime::MAX, FileTime::NT_TIME_EPOCH);
133        assert_ne!(FileTime::MAX, FileTime::UNIX_EPOCH);
134        assert_eq!(FileTime::MAX, FileTime::MAX);
135    }
136
137    #[test]
138    fn order() {
139        assert!(FileTime::UNIX_EPOCH < FileTime::MAX);
140        assert_eq!(
141            FileTime::UNIX_EPOCH.cmp(&FileTime::UNIX_EPOCH),
142            Ordering::Equal
143        );
144        assert!(FileTime::UNIX_EPOCH > FileTime::NT_TIME_EPOCH);
145    }
146
147    #[cfg(feature = "std")]
148    #[test]
149    fn equality_system_time_and_file_time() {
150        use std::time::{Duration, SystemTime};
151
152        assert_eq!(
153            (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700)),
154            FileTime::new(9_223_372_036_854_775_807)
155        );
156        assert_ne!(
157            (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700)),
158            FileTime::new(9_223_372_036_854_775_806)
159        );
160        assert_eq!(SystemTime::UNIX_EPOCH, FileTime::UNIX_EPOCH);
161        assert_ne!(SystemTime::UNIX_EPOCH, FileTime::NT_TIME_EPOCH);
162    }
163
164    #[cfg(feature = "std")]
165    #[test]
166    fn equality_file_time_and_system_time() {
167        use std::time::{Duration, SystemTime};
168
169        assert_eq!(
170            FileTime::new(9_223_372_036_854_775_807),
171            (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
172        );
173        assert_ne!(
174            FileTime::new(9_223_372_036_854_775_806),
175            (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
176        );
177        assert_eq!(FileTime::UNIX_EPOCH, SystemTime::UNIX_EPOCH);
178        assert_ne!(FileTime::NT_TIME_EPOCH, SystemTime::UNIX_EPOCH);
179    }
180
181    #[test]
182    fn equality_offset_date_time_and_file_time() {
183        assert_eq!(
184            datetime!(9999-12-31 23:59:59.999_999_900 UTC),
185            FileTime::new(2_650_467_743_999_999_999)
186        );
187        assert_ne!(
188            datetime!(9999-12-31 23:59:59.999_999_900 UTC),
189            FileTime::NT_TIME_EPOCH
190        );
191        assert_ne!(
192            datetime!(1601-01-01 00:00 UTC),
193            FileTime::new(2_650_467_743_999_999_999)
194        );
195        assert_eq!(datetime!(1601-01-01 00:00 UTC), FileTime::NT_TIME_EPOCH);
196    }
197
198    #[test]
199    fn equality_file_time_and_offset_date_time() {
200        assert_eq!(
201            FileTime::new(2_650_467_743_999_999_999),
202            datetime!(9999-12-31 23:59:59.999_999_900 UTC)
203        );
204        assert_ne!(
205            FileTime::NT_TIME_EPOCH,
206            datetime!(9999-12-31 23:59:59.999_999_900 UTC)
207        );
208        assert_ne!(
209            FileTime::new(2_650_467_743_999_999_999),
210            datetime!(1601-01-01 00:00 UTC)
211        );
212        assert_eq!(FileTime::NT_TIME_EPOCH, datetime!(1601-01-01 00:00 UTC));
213    }
214
215    #[cfg(feature = "chrono")]
216    #[test]
217    fn equality_chrono_date_time_and_file_time() {
218        use chrono::{DateTime, Utc};
219
220        assert_eq!(
221            "+60056-05-28 05:36:10.955161500 UTC"
222                .parse::<DateTime<Utc>>()
223                .unwrap(),
224            FileTime::MAX
225        );
226        assert_ne!(
227            "+60056-05-28 05:36:10.955161500 UTC"
228                .parse::<DateTime<Utc>>()
229                .unwrap(),
230            FileTime::NT_TIME_EPOCH
231        );
232        assert_ne!(
233            "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap(),
234            FileTime::MAX
235        );
236        assert_eq!(
237            "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap(),
238            FileTime::NT_TIME_EPOCH
239        );
240    }
241
242    #[cfg(feature = "chrono")]
243    #[test]
244    fn equality_file_time_and_chrono_date_time() {
245        use chrono::{DateTime, Utc};
246
247        assert_eq!(
248            FileTime::MAX,
249            "+60056-05-28 05:36:10.955161500 UTC"
250                .parse::<DateTime<Utc>>()
251                .unwrap()
252        );
253        assert_ne!(
254            FileTime::NT_TIME_EPOCH,
255            "+60056-05-28 05:36:10.955161500 UTC"
256                .parse::<DateTime<Utc>>()
257                .unwrap()
258        );
259        assert_ne!(
260            FileTime::MAX,
261            "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap()
262        );
263        assert_eq!(
264            FileTime::NT_TIME_EPOCH,
265            "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap()
266        );
267    }
268
269    #[cfg(feature = "std")]
270    #[test]
271    fn order_system_time_and_file_time() {
272        use std::time::SystemTime;
273
274        assert!(SystemTime::UNIX_EPOCH < FileTime::new(9_223_372_036_854_775_807));
275        assert_eq!(
276            SystemTime::UNIX_EPOCH.partial_cmp(&FileTime::UNIX_EPOCH),
277            Some(Ordering::Equal)
278        );
279        assert!(SystemTime::UNIX_EPOCH > FileTime::NT_TIME_EPOCH);
280    }
281
282    #[cfg(feature = "std")]
283    #[test]
284    fn order_file_time_and_system_time() {
285        use std::time::{Duration, SystemTime};
286
287        assert!(
288            FileTime::UNIX_EPOCH
289                < (SystemTime::UNIX_EPOCH + Duration::new(910_692_730_085, 477_580_700))
290        );
291        assert_eq!(
292            FileTime::UNIX_EPOCH.partial_cmp(&SystemTime::UNIX_EPOCH),
293            Some(Ordering::Equal)
294        );
295        assert!(
296            FileTime::UNIX_EPOCH
297                > (SystemTime::UNIX_EPOCH - (FileTime::UNIX_EPOCH - FileTime::NT_TIME_EPOCH))
298        );
299    }
300
301    #[test]
302    fn order_offset_date_time_and_file_time() {
303        assert!(OffsetDateTime::UNIX_EPOCH < FileTime::new(2_650_467_743_999_999_999));
304        assert_eq!(
305            OffsetDateTime::UNIX_EPOCH.partial_cmp(&FileTime::UNIX_EPOCH),
306            Some(Ordering::Equal)
307        );
308        assert!(OffsetDateTime::UNIX_EPOCH > FileTime::NT_TIME_EPOCH);
309    }
310
311    #[test]
312    fn order_file_time_and_offset_date_time() {
313        assert!(FileTime::UNIX_EPOCH < datetime!(9999-12-31 23:59:59.999_999_900 UTC));
314        assert_eq!(
315            FileTime::UNIX_EPOCH.partial_cmp(&OffsetDateTime::UNIX_EPOCH),
316            Some(Ordering::Equal)
317        );
318        assert!(FileTime::UNIX_EPOCH > datetime!(1601-01-01 00:00 UTC));
319    }
320
321    #[cfg(feature = "chrono")]
322    #[test]
323    fn order_chrono_date_time_and_file_time() {
324        use chrono::{DateTime, Utc};
325
326        assert!(DateTime::<Utc>::UNIX_EPOCH < FileTime::MAX);
327        assert_eq!(
328            DateTime::<Utc>::UNIX_EPOCH.partial_cmp(&FileTime::UNIX_EPOCH),
329            Some(Ordering::Equal)
330        );
331        assert!(DateTime::<Utc>::UNIX_EPOCH > FileTime::NT_TIME_EPOCH);
332    }
333
334    #[cfg(feature = "chrono")]
335    #[test]
336    fn order_file_time_and_chrono_date_time() {
337        use chrono::{DateTime, Utc};
338
339        assert!(
340            FileTime::UNIX_EPOCH
341                < "+60056-05-28 05:36:10.955161500 UTC"
342                    .parse::<DateTime<Utc>>()
343                    .unwrap()
344        );
345        assert_eq!(
346            FileTime::UNIX_EPOCH.partial_cmp(&DateTime::<Utc>::UNIX_EPOCH),
347            Some(Ordering::Equal)
348        );
349        assert!(FileTime::UNIX_EPOCH > "1601-01-01 00:00:00 UTC".parse::<DateTime<Utc>>().unwrap());
350    }
351}