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