Skip to main content

deep_time/dt/
to_gps.rs

1use crate::{ATTOS_PER_SEC_I128, ATTOS_PER_WEEK, Dt, Real, SEC_PER_DAYI64, Scale};
2
3impl Dt {
4    /// Returns the GPS week number and the exact Time of Week (TOW) for this instant
5    /// when expressed in **GPS Time**.
6    ///
7    /// - GPS Time is continuous (no leap seconds) and starts at the
8    ///   [`Dt::GPS_EPOCH`] (1980-01-06 00:00:00 UTC).
9    /// - The returned TOW is a full-precision `Dt` (attosecond resolution) on the
10    ///   TAI scale.
11    ///
12    /// This is the most precise way to obtain GPS week + TOW information.
13    pub const fn to_gps_wk_and_tow(&self, current: Scale) -> (i64, Dt) {
14        let total_attos = self.to_gps(current).to_attos();
15
16        let wk = total_attos.div_euclid(ATTOS_PER_WEEK) as i64;
17        let tow_attos = total_attos.rem_euclid(ATTOS_PER_WEEK);
18
19        (wk, Dt::from_attos(tow_attos, Scale::TAI))
20    }
21
22    /// Returns the day of the GPS week (0 = Sunday, 1 = Monday, …, 6 = Saturday).
23    ///
24    /// This value is computed directly from the GPS Time of Week and is
25    /// independent of the Gregorian calendar or civil time.
26    pub const fn to_gps_day_of_wk(&self, current: Scale) -> u8 {
27        let (_, tow) = self.to_gps_wk_and_tow(current);
28        let secs = tow.to_attos() / ATTOS_PER_SEC_I128;
29
30        (secs / SEC_PER_DAYI64 as i128) as u8
31    }
32
33    /// Returns the Time of Week (TOW) as a floating-point value in seconds.
34    ///
35    /// This is a convenience method for code that prefers `f64` / `Real`.
36    /// For full attosecond precision use [`Self::to_gps_wk_and_tow`].
37    #[inline]
38    pub const fn to_gps_tow_f(&self, current: Scale) -> Real {
39        let (_, tow) = self.to_gps_wk_and_tow(current);
40        tow.to_sec_f()
41    }
42
43    /// Returns only the GPS week number.
44    ///
45    /// Convenience method. For both the week number and the Time of Week, use
46    /// [`Self::to_gps_wk_and_tow`].
47    #[inline]
48    pub const fn to_gps_wk(&self, current: Scale) -> i64 {
49        self.to_gps_wk_and_tow(current).0
50    }
51
52    /// Returns the elapsed time since the GPS/Galileo Experiment (GALEX) epoch
53    /// as a [`Dt`] on the TAI scale.
54    ///
55    /// The GALEX epoch is [`Self::GPS_EPOCH`].
56    #[inline]
57    pub const fn to_galexsec(&self, current: Scale) -> Dt {
58        self.to(current, Scale::UTC)
59            .to_diff_raw(Dt::GPS_EPOCH.to(Scale::TAI, Scale::UTC))
60    }
61
62    /// Returns the elapsed time since the GPS epoch as a [`Dt`] on the GPS scale.
63    ///
64    /// The GPS epoch is [`Dt::GPS_EPOCH`].
65    #[inline]
66    pub const fn to_gps(&self, current: Scale) -> Dt {
67        self.to(current, Scale::GPS)
68            .to_diff_raw(Dt::GPS_EPOCH.to(Scale::TAI, Scale::GPS))
69    }
70
71    /// Returns the elapsed time since the Chandra X-ray Center (CXC) epoch
72    /// as a [`Dt`] on the TT scale.
73    ///
74    /// The CXC epoch is [`Dt::CXC_EPOCH`].
75    #[inline]
76    pub const fn to_cxcsec(&self, current: Scale) -> Dt {
77        self.to(current, Scale::TT)
78            .to_diff_raw(Dt::CXC_EPOCH.to(Scale::TAI, Scale::TT))
79    }
80}