Skip to content

Commit

Permalink
Hot fix for #187
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
  • Loading branch information
ChristopherRabotin committed Dec 6, 2022
1 parent e5604f1 commit 704fbff
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 33 deletions.
58 changes: 29 additions & 29 deletions src/epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::parser::Token;
use crate::{
Errors, TimeScale, BDT_REF_EPOCH, DAYS_PER_YEAR_NLD, ET_EPOCH_S, GPST_REF_EPOCH, GST_REF_EPOCH,
J1900_OFFSET, J2000_TO_J1900_DURATION, MJD_OFFSET, NANOSECONDS_PER_MICROSECOND,
NANOSECONDS_PER_MILLISECOND, NANOSECONDS_PER_SECOND_U32, SECONDS_PER_DAY, UNIX_REF_EPOCH,
NANOSECONDS_PER_MILLISECOND, NANOSECONDS_PER_SECOND_U32, UNIX_REF_EPOCH,
};
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::fmt;
Expand Down Expand Up @@ -1191,15 +1191,20 @@ impl Epoch {
/// Builds an Epoch from given `week`: elapsed weeks counter into the desired Time scale, and "ns" amount of nanoseconds since closest Sunday Midnight.
/// For example, this is how GPS vehicles describe a GPST epoch.
#[must_use]
pub fn from_time_of_week(week: u32, ns: u64, ts: TimeScale) -> Self {
let week = Duration::from_seconds(week as f64 * SECONDS_PER_DAY * Weekday::DAYS_PER_WEEK);
Self::from_duration(week + (ns as f64) * Unit::Nanosecond, ts)
pub fn from_time_of_week(week: u32, nanoseconds: u64, ts: TimeScale) -> Self {
let duration = i64::from(week) * Weekday::DAYS_PER_WEEK_I64 * Unit::Day
+ Duration::from_parts(0, nanoseconds);
let gh_187 = match ts {
TimeScale::UTC | TimeScale::TT | TimeScale::TAI => 1.0 * Unit::Day,
_ => Duration::ZERO,
};
Self::from_duration(duration - gh_187, ts)
}

#[must_use]
/// Builds an UTC Epoch from given `week`: elapsed weeks counter and "ns" amount of nanoseconds since closest Sunday Midnight.
pub fn from_time_of_week_utc(week: u32, ns: u64) -> Self {
Self::from_time_of_week(week, ns, TimeScale::UTC)
pub fn from_time_of_week_utc(week: u32, nanoseconds: u64) -> Self {
Self::from_time_of_week(week, nanoseconds, TimeScale::UTC)
}
}

Expand Down Expand Up @@ -2173,6 +2178,7 @@ impl Epoch {
Self::compute_gregorian(self.to_tai_duration())
}

#[must_use]
/// Floors this epoch to the closest provided duration
///
/// # Example
Expand All @@ -2195,6 +2201,7 @@ impl Epoch {
Self::from_duration(self.to_duration().floor(duration), self.time_scale)
}

#[must_use]
/// Ceils this epoch to the closest provided duration in the TAI time system
///
/// # Example
Expand All @@ -2218,6 +2225,7 @@ impl Epoch {
Self::from_duration(self.to_duration().ceil(duration), self.time_scale)
}

#[must_use]
/// Rounds this epoch to the closest provided duration in TAI
///
/// # Example
Expand All @@ -2234,54 +2242,46 @@ impl Epoch {
Self::from_duration(self.to_duration().round(duration), self.time_scale)
}

#[must_use]
/// Copies this epoch and sets it to the new time scale provided.
pub fn in_time_scale(&self, new_time_scale: TimeScale) -> Self {
let mut me = *self;
me.time_scale = new_time_scale;
me
}

#[must_use]
/// Converts this epoch into the time of week, represented as a rolling week counter into that time scale and the number of nanoseconds since closest Sunday midnight into that week.
/// This is usually how GNSS receivers describe a timestamp.
pub fn to_time_of_week(&self) -> (u32, u64) {
// wk: rolling week counter into timescale
// fractional days in this time scale
let days = self.to_duration().to_unit(Unit::Day);
let wk = (days / Weekday::DAYS_PER_WEEK).floor() as u32;
// tow: number of nanoseconds between self and previous sunday midnight / start of week
let wk = div_euclid_f64(
self.to_duration().to_unit(Unit::Day),
Weekday::DAYS_PER_WEEK,
);
let mut start_of_week = self.previous_weekday_at_midnight(Weekday::Sunday);
let ref_epoch = self.time_scale.ref_epoch();
// restrict start of week/sunday to the start of the time scale
if start_of_week < ref_epoch {
start_of_week = ref_epoch;
}
let dw = *self - start_of_week; // difference in weekdays [0..6]
(wk, dw.nanoseconds)
(wk as u32, dw.nanoseconds)
}

#[must_use]
/// Returns the weekday in provided time scale **ASSUMING** that the reference epoch of that time scale is a Monday.
/// You _probably_ do not want to use this. You probably either want `weekday()` or `weekday_utc()`.
/// Several time scales do _not_ have a reference day that's on a Monday, e.g. BDT.
pub fn weekday_in_time_scale(&self, time_scale: TimeScale) -> Weekday {
#[cfg(feature = "std")]
{
(self
.to_duration_in_time_scale(time_scale)
.to_unit(Unit::Day)
.rem_euclid(Weekday::DAYS_PER_WEEK)
.floor() as u8)
.into()
}
#[cfg(not(feature = "std"))]
{
// The rem_euclid call of num_traits requires a pointer not a value.
(self
.to_duration_in_time_scale(time_scale)
.to_unit(Unit::Day)
.rem_euclid(&Weekday::DAYS_PER_WEEK)
.floor() as u8)
.into()
}
(rem_euclid_f64(
self.to_duration_in_time_scale(time_scale)
.to_unit(Unit::Day),
Weekday::DAYS_PER_WEEK,
)
.floor() as u8)
.into()
}

/// Returns weekday (uses the TAI representation for this calculation).
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ pub const J2000_TO_J1900_DURATION: Duration = Duration {
nanoseconds: 3_155_716_800_000_000_000,
};

/// The Ephemeris Time reference epoch J2000.
pub const J2000_REF_EPOCH_ET: Epoch = Epoch {
duration_since_j1900_tai: Duration {
centuries: 0,
nanoseconds: 3_155_716_767_816_072_748,
},
time_scale: TimeScale::ET,
};

/// The Dynamic Barycentric Time reference epoch J2000.
pub const J2000_REF_EPOCH_TDB: Epoch = Epoch {
duration_since_j1900_tai: Duration {
centuries: 0,
nanoseconds: 3_155_716_767_816_072_704,
},
time_scale: TimeScale::ET,
};

mod parser;

mod epoch;
Expand Down
11 changes: 9 additions & 2 deletions src/timescale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use serde_derive::{Deserialize, Serialize};
use core::fmt;
use core::str::FromStr;

use crate::{Duration, Epoch, Errors, ParsingErrors, J2000_TO_J1900_DURATION, SECONDS_PER_DAY};
use crate::{
Duration, Epoch, Errors, ParsingErrors, J2000_REF_EPOCH_ET, J2000_REF_EPOCH_TDB,
J2000_TO_J1900_DURATION, SECONDS_PER_DAY,
};

/// The J1900 reference epoch (1900-01-01 at noon) TAI.
pub const J1900_REF_EPOCH: Epoch = Epoch::from_tai_duration(Duration::ZERO);
Expand Down Expand Up @@ -105,13 +108,17 @@ impl TimeScale {
pub const fn is_gnss(&self) -> bool {
matches!(self, Self::GPST | Self::GST | Self::BDT)
}

/// Returns Reference Epoch (t(0)) for given timescale
pub const fn ref_epoch(&self) -> Epoch {
match self {
Self::GPST => GPST_REF_EPOCH,
Self::GST => GST_REF_EPOCH,
Self::BDT => BDT_REF_EPOCH,
_ => J1900_REF_EPOCH,
Self::ET => J2000_REF_EPOCH_ET,
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,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/weekday.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ impl Weekday {
const MAX: u8 = 7;
/// Trivial, but avoid magic numbers.
pub(crate) const DAYS_PER_WEEK: f64 = 7.0;
/// Trivial, but avoid magic numbers.
pub(crate) const DAYS_PER_WEEK_I64: i64 = 7;
}

impl From<u8> for Weekday {
Expand Down
7 changes: 5 additions & 2 deletions tests/epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1473,9 +1473,12 @@ fn test_time_of_week() {
assert_eq!(epoch.to_gregorian_utc(), (2022, 12, 01, 00, 00, 00, 00));
assert_eq!(epoch.to_time_of_week(), (2238, 345_618_000_000_000));

let epoch_utc = epoch.in_time_scale(TimeScale::UTC);
let epoch_utc = epoch.in_time_scale(TimeScale::TT);
let (utc_wk, utc_tow) = epoch_utc.to_time_of_week();
assert_eq!(Epoch::from_time_of_week_utc(utc_wk, utc_tow), epoch_utc);
assert_eq!(
Epoch::from_time_of_week(utc_wk, utc_tow, TimeScale::TT),
epoch_utc
);

// 06/01/1980 01:00:00 = 1H into GPST <=> (0, 3_618_000_000_000)
let epoch = Epoch::from_time_of_week(0, 3_618_000_000_000, TimeScale::GPST);
Expand Down

0 comments on commit 704fbff

Please sign in to comment.