deep-time 0.1.0-alpha.2

High-precision time types, time scale conversions, relativistic time, and a flexible date and duration parser
Documentation
use crate::{Dt, TSpan};
use core::cmp::Ordering;
use core::ops::{Add, AddAssign, Sub, SubAssign};

impl Add<TSpan> for Dt {
    type Output = Self;

    #[inline]
    fn add(self, rhs: TSpan) -> Self {
        self.add(rhs)
    }
}

impl AddAssign<TSpan> for Dt {
    #[inline]
    fn add_assign(&mut self, rhs: TSpan) {
        *self = self.add(rhs);
    }
}

impl Sub<TSpan> for Dt {
    type Output = Self;

    #[inline]
    fn sub(self, rhs: TSpan) -> Self {
        self.sub(rhs)
    }
}

impl SubAssign<TSpan> for Dt {
    #[inline]
    fn sub_assign(&mut self, rhs: TSpan) {
        *self = self.sub(rhs);
    }
}

impl Sub<Dt> for Dt {
    type Output = TSpan;

    #[inline]
    fn sub(self, rhs: Dt) -> TSpan {
        self.to_tai_since(rhs)
    }
}

impl Dt {
    /// Compares this `Dt` with another by converting both to the TAI timescale
    /// (the library's canonical physical-time reference) and then comparing their
    /// `(sec, attos)` pairs.
    ///
    /// This is a `const fn` so it can be used in const contexts and is allocation-free.
    /// It provides the total order used by `<`, `>`, `<=`, `>=`, `cmp`, etc.
    ///
    /// Two `Dt`s that represent the exact same physical instant (after all
    /// leap-second, relativistic, and scale conversions) compare as `Equal`, even if
    /// they were constructed with different [`Scale`]s.
    pub const fn cmp(self, other: Self) -> Ordering {
        if self.sec < other.sec {
            Ordering::Less
        } else if self.sec > other.sec {
            Ordering::Greater
        } else if self.attos < other.attos {
            Ordering::Less
        } else if self.attos > other.attos {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    }

    /// Returns the smaller of two `Dt`s according to the total physical-time order
    /// defined by [`Self::cmp`].
    ///
    /// Both instants are converted to TAI internally, so the result is the physically
    /// earlier instant even when the two `Dt`s belong to different [`Scale`]s
    /// (leap seconds, relativistic offsets, etc. are all taken into account).
    ///
    /// This is a `const fn` and can be used in const contexts.
    #[inline]
    pub const fn min(self, other: Self) -> Self {
        match self.cmp(other) {
            Ordering::Greater => other,
            _ => self,
        }
    }

    /// Returns the larger of two `Dt`s according to the total physical-time order
    /// defined by [`Self::cmp`].
    ///
    /// See [`Self::min`] for more details.
    #[inline]
    pub const fn max(self, other: Self) -> Self {
        match self.cmp(other) {
            Ordering::Less => other,
            _ => self,
        }
    }

    #[inline]
    pub const fn eq(&self, other: &Self) -> bool {
        match Dt::cmp(*self, *other) {
            Ordering::Equal => true,
            _ => false,
        }
    }
}

impl PartialEq for Dt {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        Dt::eq(self, other)
    }
}

impl Eq for Dt {}

impl PartialOrd for Dt {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(Dt::cmp(*self, *other))
    }
}

impl Ord for Dt {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        Dt::cmp(*self, *other)
    }
}

impl core::hash::Hash for Dt {
    /// Hashes the canonical TAI representation so that two `Dt`s that are
    /// physically equal (after conversion) produce the same hash, regardless of
    /// the original [`Scale`].
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
        self.sec.hash(state);
        self.attos.hash(state);
    }
}