Skip to main content

time/interop/
offsetdatetime_timestamp.rs

1use core::cmp::Ordering;
2use core::ops::Sub;
3
4#[allow(unused_imports)] // MSRV of 1.87
5use num_conv::prelude::*;
6
7use crate::{Duration, OffsetDateTime, Timestamp};
8
9impl Sub<OffsetDateTime> for Timestamp {
10    type Output = Duration;
11
12    #[inline]
13    fn sub(self, rhs: OffsetDateTime) -> Self::Output {
14        Duration::new(
15            self.as_seconds() - rhs.unix_timestamp(),
16            self.nanosecond().cast_signed() - rhs.nanosecond().cast_signed(),
17        )
18    }
19}
20
21impl Sub<Timestamp> for OffsetDateTime {
22    type Output = Duration;
23
24    #[inline]
25    fn sub(self, rhs: Timestamp) -> Self::Output {
26        Duration::new(
27            self.unix_timestamp() - rhs.as_seconds(),
28            self.nanosecond().cast_signed() - rhs.nanosecond().cast_signed(),
29        )
30    }
31}
32
33impl PartialEq<OffsetDateTime> for Timestamp {
34    #[expect(clippy::suspicious_operation_groupings, reason = "false positive")]
35    #[inline]
36    fn eq(&self, other: &OffsetDateTime) -> bool {
37        self.as_seconds() == other.unix_timestamp() && self.nanosecond() == other.nanosecond()
38    }
39}
40
41impl PartialEq<Timestamp> for OffsetDateTime {
42    #[inline]
43    fn eq(&self, other: &Timestamp) -> bool {
44        other == self
45    }
46}
47
48impl PartialOrd<OffsetDateTime> for Timestamp {
49    #[inline]
50    fn partial_cmp(&self, other: &OffsetDateTime) -> Option<Ordering> {
51        (self.as_seconds(), self.nanosecond())
52            .partial_cmp(&(other.unix_timestamp(), other.nanosecond()))
53    }
54}
55
56impl PartialOrd<Timestamp> for OffsetDateTime {
57    #[inline]
58    fn partial_cmp(&self, other: &Timestamp) -> Option<Ordering> {
59        other.partial_cmp(self).map(Ordering::reverse)
60    }
61}
62
63impl From<OffsetDateTime> for Timestamp {
64    /// # Panics
65    ///
66    /// This may panic if an overflow occurs.
67    #[inline]
68    #[track_caller]
69    fn from(datetime: OffsetDateTime) -> Self {
70        // Safety: Nanoseconds have the same range.
71        unsafe {
72            Self::from_seconds(datetime.unix_timestamp())
73                .expect("local datetime out of valid range for `Timestamp`")
74                .replace_nanosecond(datetime.nanosecond())
75                .unwrap_unchecked()
76        }
77    }
78}
79
80impl From<Timestamp> for OffsetDateTime {
81    #[inline]
82    fn from(timestamp: Timestamp) -> Self {
83        // Safety: The valid range of `Timestamp` is less than that of `OffsetDateTime` (due to edge
84        // cases of `OffsetDateTime`). Nanoseconds have the same range.
85        unsafe {
86            Self::from_unix_timestamp(timestamp.as_seconds())
87                .unwrap_unchecked()
88                .replace_nanosecond(timestamp.nanosecond())
89                .unwrap_unchecked()
90        }
91    }
92}