Skip to content

Commit

Permalink
Merge pull request #277 from nyx-space/4.0.0-dev
Browse files Browse the repository at this point in the history
BREAKING CHANGE: 4.0.0-dev branch become 3.10.0
  • Loading branch information
ChristopherRabotin authored Jan 13, 2024
2 parents 7e05365 + 8ef79ee commit da8e406
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/asn1der.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl<'a> Decode<'a> for Epoch {
TimeScale::TDB => Self::from_tdb_duration(duration),
TimeScale::UTC => Self::from_utc_duration(duration),
TimeScale::GPST => Self::from_gpst_duration(duration),
TimeScale::QZSST => Self::from_qzsst_duration(duration),
TimeScale::GST => Self::from_gst_duration(duration),
TimeScale::BDT => Self::from_bdt_duration(duration),
})
Expand Down Expand Up @@ -92,7 +93,7 @@ impl<'a> Decode<'a> for Unit {
// Testing the encoding and decoding of an Epoch inherently also tests the encoding and decoding of a Duration
#[test]
fn test_encdec() {
for ts_u8 in 0..=7 {
for ts_u8 in 0..=8 {
let ts: TimeScale = ts_u8.into();

let epoch = if ts == TimeScale::UTC {
Expand All @@ -110,6 +111,7 @@ fn test_encdec() {
TimeScale::GPST => epoch.to_gpst_duration(),
TimeScale::GST => epoch.to_gst_duration(),
TimeScale::BDT => epoch.to_bdt_duration(),
TimeScale::QZSST => epoch.to_qzsst_duration(),
};

let e_dur = epoch.to_duration();
Expand All @@ -130,7 +132,7 @@ fn test_encdec() {
// Check that the time scale used is preserved
assert_eq!(
encdec_epoch.time_scale, ts,
"Decoded time system incorrect {ts:?}"
"Decoded time system incorrect {ts:?}",
);
}

Expand Down
128 changes: 117 additions & 11 deletions src/epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ impl Epoch {
TimeScale::TDB => Self::from_tdb_duration(new_duration),
TimeScale::UTC => Self::from_utc_duration(new_duration),
TimeScale::GPST => Self::from_gpst_duration(new_duration),
TimeScale::QZSST => Self::from_qzsst_duration(new_duration),
TimeScale::GST => Self::from_gst_duration(new_duration),
TimeScale::BDT => Self::from_bdt_duration(new_duration),
}
Expand Down Expand Up @@ -345,6 +346,15 @@ impl Epoch {
me
}

#[must_use]
/// Initialize an Epoch from the provided duration since 1980 January 6 at midnight
pub fn from_qzsst_duration(duration: Duration) -> Self {
// QZSST and GPST share the same reference epoch
let mut me = Self::from_tai_duration(GPST_REF_EPOCH.to_tai_duration() + duration);
me.time_scale = TimeScale::QZSST;
me
}

#[must_use]
/// Initialize an Epoch from the provided duration since August 21st 1999 midnight
pub fn from_gst_duration(duration: Duration) -> Self {
Expand Down Expand Up @@ -389,6 +399,10 @@ impl Epoch {
Self::from_mjd_in_time_scale(days, TimeScale::GPST)
}
#[must_use]
pub fn from_mjd_qzsst(days: f64) -> Self {
Self::from_mjd_in_time_scale(days, TimeScale::QZSST)
}
#[must_use]
pub fn from_mjd_gst(days: f64) -> Self {
Self::from_mjd_in_time_scale(days, TimeScale::GST)
}
Expand Down Expand Up @@ -425,6 +439,10 @@ impl Epoch {
Self::from_jde_in_time_scale(days, TimeScale::GPST)
}
#[must_use]
pub fn from_jde_qzsst(days: f64) -> Self {
Self::from_jde_in_time_scale(days, TimeScale::QZSST)
}
#[must_use]
pub fn from_jde_gst(days: f64) -> Self {
Self::from_jde_in_time_scale(days, TimeScale::GST)
}
Expand Down Expand Up @@ -571,6 +589,34 @@ impl Epoch {
)
}

#[must_use]
/// Initialize an Epoch from the number of seconds since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
pub fn from_qzsst_seconds(seconds: f64) -> Self {
Self::from_duration(Duration::from_f64(seconds, Unit::Second), TimeScale::QZSST)
}

#[must_use]
/// Initialize an Epoch from the number of days since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
pub fn from_qzsst_days(days: f64) -> Self {
Self::from_duration(Duration::from_f64(days, Unit::Day), TimeScale::QZSST)
}

#[must_use]
/// Initialize an Epoch from the number of nanoseconds since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
/// This may be useful for time keeping devices that use QZSS as a time source.
pub fn from_qzsst_nanoseconds(nanoseconds: u64) -> Self {
Self::from_duration(
Duration {
centuries: 0,
nanoseconds,
},
TimeScale::QZSST,
)
}

#[must_use]
/// Initialize an Epoch from the number of seconds since the GST Time Epoch,
/// starting August 21st 1999 midnight (UTC)
Expand Down Expand Up @@ -737,6 +783,10 @@ impl Epoch {
TimeScale::GPST => {
Self::from_gpst_duration(duration_wrt_1900 - GPST_REF_EPOCH.to_tai_duration())
}
// QZSS and GPST share the same reference epoch
TimeScale::QZSST => {
Self::from_qzsst_duration(duration_wrt_1900 - GPST_REF_EPOCH.to_tai_duration())
}
TimeScale::GST => {
Self::from_gst_duration(duration_wrt_1900 - GST_REF_EPOCH.to_tai_duration())
}
Expand Down Expand Up @@ -1441,6 +1491,31 @@ impl Epoch {
Self::from_gpst_nanoseconds(nanoseconds)
}

#[cfg(feature = "python")]
#[classmethod]
/// Initialize an Epoch from the number of seconds since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
fn init_from_qzsst_seconds(_cls: &PyType, seconds: f64) -> Self {
Self::from_qzsst_seconds(seconds)
}

#[cfg(feature = "python")]
#[classmethod]
/// Initialize an Epoch from the number of days since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
fn init_from_qzsst_days(_cls: &PyType, days: f64) -> Self {
Self::from_qzsst_days(days)
}

#[cfg(feature = "python")]
#[classmethod]
/// Initialize an Epoch from the number of nanoseconds since the QZSS Time Epoch,
/// defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
/// This may be useful for time keeping devices that use QZSS as a time source.
fn init_from_qzsst_nanoseconds(_cls: &PyType, nanoseconds: u64) -> Self {
Self::from_qzsst_nanoseconds(nanoseconds)
}

#[cfg(feature = "python")]
#[classmethod]
/// Initialize an Epoch from the number of seconds since the Galileo Time Epoch,
Expand Down Expand Up @@ -1744,9 +1819,10 @@ impl Epoch {
TimeScale::ET => self.to_et_duration(),
TimeScale::TDB => self.to_tdb_duration(),
TimeScale::UTC => self.to_utc_duration(),
TimeScale::GPST => self.to_gpst_duration(),
TimeScale::BDT => self.to_bdt_duration(),
TimeScale::GST => self.to_gst_duration(),
// GPST and QZSST share the same properties
TimeScale::GPST | TimeScale::QZSST => self.to_gpst_duration(),
}
}

Expand Down Expand Up @@ -1779,7 +1855,10 @@ impl Epoch {
TimeScale::TT => self.to_tt_duration(),
TimeScale::TDB => self.to_tdb_duration_since_j1900(),
TimeScale::UTC => self.to_utc_duration(),
TimeScale::GPST => self.to_gpst_duration() + GPST_REF_EPOCH.to_tai_duration(),
// GPST and QZSST share the same properties
TimeScale::GPST | TimeScale::QZSST => {
self.to_gpst_duration() + GPST_REF_EPOCH.to_tai_duration()
}
TimeScale::GST => self.to_gst_duration() + GST_REF_EPOCH.to_tai_duration(),
TimeScale::BDT => self.to_bdt_duration() + BDT_REF_EPOCH.to_tai_duration(),
}
Expand All @@ -1794,7 +1873,8 @@ impl Epoch {
TimeScale::ET => Self::from_et_duration(new_duration),
TimeScale::TDB => Self::from_tdb_duration(new_duration),
TimeScale::UTC => Self::from_utc_duration(new_duration),
TimeScale::GPST => Self::from_gpst_duration(new_duration),
// GPST and QZSST share the same properties
TimeScale::GPST | TimeScale::QZSST => Self::from_gpst_duration(new_duration),
TimeScale::GST => Self::from_gst_duration(new_duration),
TimeScale::BDT => Self::from_bdt_duration(new_duration),
}
Expand Down Expand Up @@ -2012,6 +2092,31 @@ impl Epoch {
self.to_gpst_duration().to_unit(Unit::Day)
}

#[must_use]
/// Returns seconds past QZSS Time Epoch, defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
pub fn to_qzsst_seconds(&self) -> f64 {
self.to_qzsst_duration().to_seconds()
}

#[must_use]
/// Returns `Duration` past QZSS time Epoch.
pub fn to_qzsst_duration(&self) -> Duration {
// GPST and QZSST share the same reference epoch
self.duration_since_j1900_tai - GPST_REF_EPOCH.to_tai_duration()
}

/// Returns nanoseconds past QZSS Time Epoch, defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
/// NOTE: This function will return an error if the centuries past QZSST time are not zero.
pub fn to_qzsst_nanoseconds(&self) -> Result<u64, Errors> {
self.to_nanoseconds_in_time_scale(TimeScale::QZSST)
}

#[must_use]
/// Returns days past QZSS Time Epoch, defined as UTC midnight of January 5th to 6th 1980 (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS#GPS_Time_.28GPST.29>).
pub fn to_qzsst_days(&self) -> f64 {
self.to_gpst_duration().to_unit(Unit::Day)
}

#[must_use]
/// Returns seconds past GST (Galileo) Time Epoch
pub fn to_gst_seconds(&self) -> f64 {
Expand All @@ -2024,6 +2129,13 @@ impl Epoch {
self.duration_since_j1900_tai - GST_REF_EPOCH.to_tai_duration()
}

/// Returns nanoseconds past GST (Galileo) Time Epoch, starting on August 21st 1999 Midnight UT
/// (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS>).
/// NOTE: This function will return an error if the centuries past GST time are not zero.
pub fn to_gst_nanoseconds(&self) -> Result<u64, Errors> {
self.to_nanoseconds_in_time_scale(TimeScale::GST)
}

#[must_use]
/// Returns days past GST (Galileo) Time Epoch,
/// starting on August 21st 1999 Midnight UT
Expand All @@ -2032,13 +2144,6 @@ impl Epoch {
self.to_gst_duration().to_unit(Unit::Day)
}

/// Returns nanoseconds past GST (Galileo) Time Epoch, starting on August 21st 1999 Midnight UT
/// (cf. <https://gssc.esa.int/navipedia/index.php/Time_References_in_GNSS>).
/// NOTE: This function will return an error if the centuries past GST time are not zero.
pub fn to_gst_nanoseconds(&self) -> Result<u64, Errors> {
self.to_nanoseconds_in_time_scale(TimeScale::GST)
}

#[must_use]
/// Returns seconds past BDT (BeiDou) Time Epoch
pub fn to_bdt_seconds(&self) -> f64 {
Expand Down Expand Up @@ -2776,7 +2881,8 @@ impl Epoch {
TimeScale::ET => self.to_et_duration_since_j1900(),
TimeScale::TDB => self.to_tdb_duration_since_j1900(),
TimeScale::UTC => self.to_utc_duration(),
TimeScale::GPST => self.to_utc_duration(),
// GPST and QZSST share the same properties
TimeScale::GPST | TimeScale::QZSST => self.to_utc_duration(),
TimeScale::GST => self.to_utc_duration(),
TimeScale::BDT => self.to_utc_duration(),
});
Expand Down
24 changes: 18 additions & 6 deletions src/timescale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub const UNIX_REF_EPOCH: Epoch = Epoch::from_tai_duration(Duration {
});

/// Enum of the different time systems available
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "python", pyclass)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand All @@ -78,20 +79,22 @@ pub enum TimeScale {
TDB,
/// Universal Coordinated Time
UTC,
/// GPST Time also applies to QZSS, IRNSS and GAL constellations
/// GPS Time scale
GPST,
/// Galileo Time scale
GST,
/// BeiDou Time scale
BDT,
/// QZSS Time scale has the same properties as GPST,
/// but with dedicated clocks
QZSST,
}

#[cfg(kani)]
impl Arbitrary for TimeScale {
#[inline(always)]
fn any() -> Self {
let ts_u8: u8 = kani::any();

Self::from(ts_u8)
}
}
Expand All @@ -111,6 +114,7 @@ impl Default for TimeScale {
impl TimeScale {
pub(crate) const fn formatted_len(&self) -> usize {
match &self {
Self::QZSST => 5,
Self::GPST => 4,
Self::TAI | Self::TDB | Self::UTC | Self::GST | Self::BDT => 3,
Self::ET | Self::TT => 2,
Expand All @@ -119,7 +123,7 @@ impl TimeScale {

/// Returns true if Self is based off a GNSS constellation
pub const fn is_gnss(&self) -> bool {
matches!(self, Self::GPST | Self::GST | Self::BDT)
matches!(self, Self::GPST | Self::GST | Self::BDT | Self::QZSST)
}

/// Returns Reference Epoch (t(0)) for given timescale
Expand All @@ -132,6 +136,8 @@ impl TimeScale {
Self::TDB => J2000_REF_EPOCH_TDB,
// Explicit on purpose in case more time scales end up being supported.
Self::TT | Self::TAI | Self::UTC => J1900_REF_EPOCH,
// QZSS time shares the same starting point as GPST
Self::QZSST => GPST_REF_EPOCH,
}
}
}
Expand All @@ -148,6 +154,7 @@ impl fmt::Display for TimeScale {
Self::GPST => write!(f, "GPST"),
Self::GST => write!(f, "GST"),
Self::BDT => write!(f, "BDT"),
Self::QZSST => write!(f, "QZSST"),
}
}
}
Expand All @@ -160,6 +167,7 @@ impl fmt::LowerHex for TimeScale {
Self::GPST => write!(f, "GPS"),
Self::GST => write!(f, "GAL"),
Self::BDT => write!(f, "BDS"),
Self::QZSST => write!(f, "QZSS"),
_ => write!(f, "{self}"),
}
}
Expand All @@ -174,7 +182,7 @@ impl TimeScale {
}

/// Allows conversion of a TimeSystem into a u8
/// Mapping: TAI: 0; TT: 1; ET: 2; TDB: 3; UTC: 4; GPST: 5; GST: 6; BDT: 7;
/// Mapping: TAI: 0; TT: 1; ET: 2; TDB: 3; UTC: 4; GPST: 5; GST: 6; BDT: 7; QZSST: 8;
impl From<TimeScale> for u8 {
fn from(ts: TimeScale) -> Self {
match ts {
Expand All @@ -186,12 +194,13 @@ impl From<TimeScale> for u8 {
TimeScale::GPST => 5,
TimeScale::GST => 6,
TimeScale::BDT => 7,
TimeScale::QZSST => 8,
}
}
}

/// Allows conversion of a u8 into a TimeSystem.
/// Mapping: 1: TT; 2: ET; 3: TDB; 4: UTC; 5: GPST; 6: GST; 7: BDT; anything else: TAI
/// Mapping: 1: TT; 2: ET; 3: TDB; 4: UTC; 5: GPST; 6: GST; 7: BDT; 8: QZSST; anything else: TAI
impl From<u8> for TimeScale {
fn from(val: u8) -> Self {
match val {
Expand All @@ -202,6 +211,7 @@ impl From<u8> for TimeScale {
5 => Self::GPST,
6 => Self::GST,
7 => Self::BDT,
8 => Self::QZSST,
_ => Self::TAI,
}
}
Expand All @@ -228,6 +238,8 @@ impl FromStr for TimeScale {
Ok(Self::GST)
} else if val == "BDT" || val == "BDS" {
Ok(Self::BDT)
} else if val == "QZSST" || val == "QZSS" {
Ok(Self::QZSST)
} else {
Err(Errors::ParseError(ParsingErrors::TimeSystem))
}
Expand All @@ -250,7 +262,7 @@ fn test_ts() {
let ts = TimeScale::from(ts_u8);
let ts_u8_back: u8 = ts.into();
// If the u8 is greater than 5, it isn't valid and necessarily encoded as TAI.
if ts_u8 < 8 {
if ts_u8 < 9 {
assert_eq!(ts_u8_back, ts_u8, "got {ts_u8_back} want {ts_u8}");
} else {
assert_eq!(ts, TimeScale::TAI);
Expand Down
Loading

0 comments on commit da8e406

Please sign in to comment.