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}