Skip to main content

satkit/time/
timelike.rs

1use super::{Instant, TimeScale};
2
3/// Trait for time-like types usable by satkit APIs that require time scale conversions.
4///
5/// Implementors provide Modified Julian Date (MJD) and Julian Date (JD) conversions
6/// for a given `TimeScale`, plus a conversion to satkit's `Instant` in UTC.
7///
8/// This trait enables interoperability with external time types (for example
9/// `chrono::DateTime`) while preserving satkit's time-scale aware calculations.
10///
11/// # Examples
12///
13/// ```
14/// use satkit::{TimeLike, TimeScale, Instant};
15///
16/// let t = Instant::from_datetime(2024, 1, 1, 0, 0, 0.0).unwrap();
17/// let mjd = t.as_mjd_with_scale(TimeScale::UTC);
18/// let jd = t.as_jd_with_scale(TimeScale::UTC);
19/// assert!((jd - (mjd + 2400000.5)).abs() < 1.0e-12);
20/// ```
21pub trait TimeLike {
22    /// Modified Julian Date with the provided time scale.
23    fn as_mjd_with_scale(&self, scale: TimeScale) -> f64;
24
25    /// Julian Date with the provided time scale.
26    fn as_jd_with_scale(&self, scale: TimeScale) -> f64 {
27        self.as_mjd_with_scale(scale) + 2400000.5
28    }
29
30    /// Convert to a satkit `Instant` in UTC.
31    ///
32    /// The default implementation converts through MJD (UTC).
33    ///
34    /// Note: this is needed, as other time-like types may not accurately
35    /// keep track of leap seconds, (e.g., for TAI or TT), so usage in
36    /// functions such as sgp4 may be inaccurate
37    fn as_instant(&self) -> Instant;
38}
39
40impl TimeLike for Instant {
41    #[inline]
42    fn as_mjd_with_scale(&self, scale: TimeScale) -> f64 {
43        Self::as_mjd_with_scale(self, scale)
44    }
45
46    #[inline]
47    fn as_jd_with_scale(&self, scale: TimeScale) -> f64 {
48        Self::as_jd_with_scale(self, scale)
49    }
50
51    #[inline]
52    fn as_instant(&self) -> Instant {
53        *self
54    }
55}
56