Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking change: renamed Julian date constants and removed other Julian date constants #307

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 11 additions & 26 deletions src/epoch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ use crate::leap_seconds::{LatestLeapSeconds, LeapSecondProvider};
use crate::Weekday;
use crate::{
EpochError, MonthName, TimeScale, TimeUnits, BDT_REF_EPOCH, ET_EPOCH_S, GPST_REF_EPOCH,
GST_REF_EPOCH, J1900_OFFSET, J2000_TO_J1900_DURATION, MJD_OFFSET, NANOSECONDS_PER_DAY,
QZSST_REF_EPOCH, UNIX_REF_EPOCH,
GST_REF_EPOCH, MJD_J1900, MJD_OFFSET, NANOSECONDS_PER_DAY, QZSST_REF_EPOCH, UNIX_REF_EPOCH,
};
use core::cmp::Eq;
use core::str::FromStr;
Expand Down Expand Up @@ -356,7 +355,7 @@ impl Epoch {
days.is_finite(),
"Attempted to initialize Epoch with non finite number"
);
Self::from_tai_duration((days - J1900_OFFSET) * Unit::Day)
Self::from_tai_duration((days - MJD_J1900) * Unit::Day)
}

fn from_mjd_in_time_scale(days: f64, time_scale: TimeScale) -> Self {
Expand Down Expand Up @@ -396,7 +395,7 @@ impl Epoch {
days.is_finite(),
"Attempted to initialize Epoch with non finite number"
);
Self::from_tai_duration((days - J1900_OFFSET - MJD_OFFSET) * Unit::Day)
Self::from_tai_duration((days - MJD_J1900 - MJD_OFFSET) * Unit::Day)
}

fn from_jde_in_time_scale(days: f64, time_scale: TimeScale) -> Self {
Expand Down Expand Up @@ -820,7 +819,7 @@ impl Epoch {
#[must_use]
/// Returns this epoch as a duration in the requested units in MJD TAI
pub fn to_mjd_tai(&self, unit: Unit) -> f64 {
(self.to_tai_duration() + Unit::Day * J1900_OFFSET).to_unit(unit)
(self.to_tai_duration() + Unit::Day * MJD_J1900).to_unit(unit)
}

#[must_use]
Expand All @@ -832,7 +831,7 @@ impl Epoch {
#[must_use]
/// Returns the Modified Julian Date in the provided unit in UTC.
pub fn to_mjd_utc(&self, unit: Unit) -> f64 {
(self.to_utc_duration() + Unit::Day * J1900_OFFSET).to_unit(unit)
(self.to_utc_duration() + Unit::Day * MJD_J1900).to_unit(unit)
}

#[must_use]
Expand All @@ -858,7 +857,7 @@ impl Epoch {
#[must_use]
/// Returns the Julian Days from epoch 01 Jan -4713 12:00 (noon) as a Duration
pub fn to_jde_tai_duration(&self) -> Duration {
self.to_tai_duration() + Unit::Day * J1900_OFFSET + Unit::Day * MJD_OFFSET
self.to_tai_duration() + Unit::Day * MJD_J1900 + Unit::Day * MJD_OFFSET
}

#[must_use]
Expand All @@ -876,7 +875,7 @@ impl Epoch {
#[must_use]
/// Returns the Julian days in UTC as a `Duration`
pub fn to_jde_utc_duration(&self) -> Duration {
self.to_utc_duration() + Unit::Day * (J1900_OFFSET + MJD_OFFSET)
self.to_utc_duration() + Unit::Day * (MJD_J1900 + MJD_OFFSET)
}

#[must_use]
Expand Down Expand Up @@ -923,7 +922,7 @@ impl Epoch {

#[must_use]
pub fn to_jde_tt_duration(&self) -> Duration {
self.to_tt_duration() + Unit::Day * (J1900_OFFSET + MJD_OFFSET)
self.to_tt_duration() + Unit::Day * (MJD_J1900 + MJD_OFFSET)
}

#[must_use]
Expand All @@ -934,7 +933,7 @@ impl Epoch {

#[must_use]
pub fn to_mjd_tt_duration(&self) -> Duration {
self.to_tt_duration() + Unit::Day * J1900_OFFSET
self.to_tt_duration() + Unit::Day * MJD_J1900
}

#[must_use]
Expand Down Expand Up @@ -1075,13 +1074,6 @@ impl Epoch {
self.to_et_duration().to_seconds()
}

#[must_use]
/// Returns the Ephemeris Time in duration past 1900 JAN 01 at noon.
/// **Only** use this if the subsequent computation expect J1900 seconds.
pub fn to_et_duration_since_j1900(&self) -> Duration {
self.to_et_duration() + J2000_TO_J1900_DURATION
}

#[must_use]
/// Returns the duration between J2000 and the current epoch as per NAIF SPICE.
///
Expand Down Expand Up @@ -1120,13 +1112,6 @@ impl Epoch {
self.to_tdb_duration().to_seconds()
}

#[must_use]
/// Returns the Dynamics Barycentric Time (TDB) as a high precision Duration with reference epoch of 1900 JAN 01 at noon.
/// **Only** use this if the subsequent computation expect J1900 seconds.
pub fn to_tdb_duration_since_j1900(&self) -> Duration {
self.to_tdb_duration() + J2000_TO_J1900_DURATION
}

#[must_use]
/// Returns the Ephemeris Time JDE past epoch
pub fn to_jde_et_days(&self) -> f64 {
Expand All @@ -1136,7 +1121,7 @@ impl Epoch {
#[must_use]
pub fn to_jde_et_duration(&self) -> Duration {
self.to_et_duration()
+ Unit::Day * (J1900_OFFSET + MJD_OFFSET)
+ Unit::Day * (MJD_J1900 + MJD_OFFSET)
+ TimeScale::ET.prime_epoch_offset()
}

Expand All @@ -1148,7 +1133,7 @@ impl Epoch {
#[must_use]
pub fn to_jde_tdb_duration(&self) -> Duration {
self.to_tdb_duration()
+ Unit::Day * (J1900_OFFSET + MJD_OFFSET)
+ Unit::Day * (MJD_J1900 + MJD_OFFSET)
+ TimeScale::TDB.prime_epoch_offset()
}

Expand Down
29 changes: 8 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,18 @@
* Documentation: https://nyxspace.com/
*/

pub const J1900_NAIF: f64 = 2_415_020.0;
pub const J2000_NAIF: f64 = 2_451_545.0;
/// `J1900_OFFSET` determines the offset in julian days between 01 Jan 1900 at midnight and the
/// Modified Julian Day at 17 November 1858.
/// NOTE: Julian days "start" at noon so that astronomical observations throughout the night
/// happen at the same Julian day. Note however that the Modified Julian Date (MJD) starts at
/// midnight, not noon, cf. <http://tycho.usno.navy.mil/mjd.html>.
pub const J1900_OFFSET: f64 = 15_020.0;
/// `J2000_OFFSET` determines the offset in julian days between 01 Jan 2000 at **noon** and the
/// Modified Julian Day at 17 November 1858.
pub const J2000_OFFSET: f64 = 51_544.5;
/// Julian date for the J1900 epoch, as per NAIF SPICE.
pub const JD_J1900: f64 = 2_415_020.0;
/// Julian date for the J2000 epoch, as per NAIF SPICE.
pub const JD_J2000: f64 = 2_451_545.0;
/// Julian days between 01 Jan 1900 at midnight and the Modified Julian Day at 17 November 1858.
pub const MJD_J1900: f64 = 15_020.0;
/// Julian days between 01 Jan 2000 at **noon** and the Modified Julian Day at 17 November 1858.
pub const MJD_J2000: f64 = 51_544.5;
/// The Ephemeris Time epoch, in seconds
pub const ET_EPOCH_S: i64 = 3_155_716_800;
/// Modified Julian Date in seconds as defined [here](http://tycho.usno.navy.mil/mjd.html). MJD epoch is Modified Julian Day at 17 November 1858 at midnight.
pub const MJD_OFFSET: f64 = 2_400_000.5;
/// The JDE offset in days
pub const JDE_OFFSET_DAYS: f64 = J1900_OFFSET + MJD_OFFSET;
/// The JDE offset in seconds
pub const JDE_OFFSET_SECONDS: f64 = JDE_OFFSET_DAYS * SECONDS_PER_DAY;
/// `DAYS_PER_YEAR` corresponds to the number of days per year in the Julian calendar.
pub const DAYS_PER_YEAR: f64 = 365.25;
/// `DAYS_PER_YEAR_NLD` corresponds to the number of days per year **without leap days**.
Expand All @@ -55,12 +48,6 @@ pub const SECONDS_PER_TROPICAL_YEAR: f64 = 31_556_925.974_7;
/// `SECONDS_PER_SIDEREAL_YEAR` corresponds to the number of seconds per sidereal year from [NIST](https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors/nist-guide-si-appendix-b9#TIME).
pub const SECONDS_PER_SIDEREAL_YEAR: f64 = 31_558_150.0;

/// The duration between J2000 and J1900 is exactly one century, both references start at noon.
pub const J2000_TO_J1900_DURATION: Duration = Duration {
centuries: 1,
nanoseconds: 0,
};

// Epoch formatting module is called `efmt` to avoid collision with `std::fmt` and `core::fmt`.
pub mod efmt;
mod parser;
Expand Down
45 changes: 32 additions & 13 deletions tests/epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ extern crate core;
use hifitime::{
is_gregorian_valid, Duration, Epoch, EpochError, ParsingError, TimeScale, TimeUnits, Unit,
Weekday, BDT_REF_EPOCH, DAYS_GPS_TAI_OFFSET, DAYS_PER_YEAR, GPST_REF_EPOCH, GST_REF_EPOCH,
J1900_OFFSET, J1900_REF_EPOCH, J2000_OFFSET, J2000_REF_EPOCH, J2000_TO_J1900_DURATION,
MJD_OFFSET, SECONDS_BDT_TAI_OFFSET, SECONDS_GPS_TAI_OFFSET, SECONDS_GST_TAI_OFFSET,
SECONDS_PER_DAY,
J1900_REF_EPOCH, J2000_REF_EPOCH, JD_J2000, MJD_J1900, MJD_J2000, MJD_OFFSET,
SECONDS_BDT_TAI_OFFSET, SECONDS_GPS_TAI_OFFSET, SECONDS_GST_TAI_OFFSET, SECONDS_PER_DAY,
};

use hifitime::efmt::{Format, Formatter};
Expand All @@ -25,15 +24,15 @@ fn test_const_ops() {
// Tests that multiplying a constant with a unit returns the correct number in that same unit
let mjd_offset = MJD_OFFSET * Unit::Day;
assert!((mjd_offset.to_unit(Unit::Day) - MJD_OFFSET).abs() < f64::EPSILON);
let j2000_offset = J2000_OFFSET * Unit::Day;
assert!((j2000_offset.to_unit(Unit::Day) - J2000_OFFSET).abs() < f64::EPSILON);
let j2000_mjd = MJD_J2000 * Unit::Day;
assert!((j2000_mjd.to_unit(Unit::Day) - MJD_J2000).abs() < f64::EPSILON);
}

#[allow(clippy::float_equality_without_abs)]
#[test]
fn utc_epochs() {
assert!(Epoch::from_mjd_tai(J1900_OFFSET).to_tai_seconds() < EPSILON);
assert!((Epoch::from_mjd_tai(J1900_OFFSET).to_mjd_tai_days() - J1900_OFFSET).abs() < EPSILON);
assert!(Epoch::from_mjd_tai(MJD_J1900).to_tai_seconds() < EPSILON);
assert!((Epoch::from_mjd_tai(MJD_J1900).to_mjd_tai_days() - MJD_J1900).abs() < EPSILON);

// Tests are chronological dates.
// All of the following examples are cross validated against NASA HEASARC,
Expand Down Expand Up @@ -422,11 +421,6 @@ fn gpst() {
GPST_REF_EPOCH.duration
);

// assert_eq!(
// GPST_REF_EPOCH.to_utc_seconds(),
// Epoch::from_gregorian_utc_at_midnight(1980, 1, 6).to_tai_seconds()
// );

assert!(
GPST_REF_EPOCH.to_gpst_seconds().abs() < EPSILON,
"The number of seconds from the GPS epoch was not 0: {}",
Expand Down Expand Up @@ -1918,7 +1912,7 @@ fn test_to_tai_time_scale() {
let j2000_ref = J2000_REF_EPOCH;
assert_eq!(j2000_ref, j2000_ref.to_time_scale(TimeScale::TAI));
let j2000_to_j1900 = j2000_ref - j1900_ref;
assert_eq!(j2000_to_j1900, J2000_TO_J1900_DURATION);
assert_eq!(j2000_to_j1900, Duration::from_parts(1, 0));
}

#[cfg(feature = "std")]
Expand Down Expand Up @@ -2044,3 +2038,28 @@ fn regression_test_gh_209() {
let t = Epoch::from_time_of_week(1982, 604800000000000 - 19000000000, TimeScale::GPST);
println!("{t}");
}

#[cfg(feature = "std")]
#[test]
fn regression_test_gh_282() {
assert_eq!(
"1900-01-01T00:00:00 UTC",
format!("{}", Epoch::from_utc_duration(0_f64.nanoseconds()))
);
// NOTE: Hifitime's prime epoch is midnight on 1900-01-01, but the Julian date J1900 is at noon.
// This explains why the calculation returns `0.5` with a zero duration UTC epoch.
assert_eq!(
"2415020.5",
format!(
"{}",
Epoch::from_utc_duration(0_f64.nanoseconds()).to_jde_utc_days()
)
);
assert_eq!(
"2000-01-01T12:00:00 TAI",
format!(
"{}",
Epoch::from_jde_tai(JD_J2000).to_gregorian_str(hifitime::TimeScale::TAI)
)
);
}
Loading