use crate::Result;
use crate::error::ensure_finite;
const JD_MINUS_MJD: f64 = 2_400_000.5;
const JD_AT_MJD2000_ZERO: f64 = 2_451_544.5;
const MJD_AT_MJD2000_ZERO: f64 = 51_544.0;
pub fn jd_to_mjd(julian_date: f64) -> Result<f64> {
ensure_finite("julian_date", julian_date)?;
Ok(julian_date - JD_MINUS_MJD)
}
pub fn jd_to_mjd2000(julian_date: f64) -> Result<f64> {
ensure_finite("julian_date", julian_date)?;
Ok(julian_date - JD_AT_MJD2000_ZERO)
}
pub fn mjd_to_jd(modified_julian_date: f64) -> Result<f64> {
ensure_finite("modified_julian_date", modified_julian_date)?;
Ok(modified_julian_date + JD_MINUS_MJD)
}
pub fn mjd_to_mjd2000(modified_julian_date: f64) -> Result<f64> {
ensure_finite("modified_julian_date", modified_julian_date)?;
Ok(modified_julian_date - MJD_AT_MJD2000_ZERO)
}
pub fn mjd2000_to_jd(mjd2000: f64) -> Result<f64> {
ensure_finite("mjd2000", mjd2000)?;
Ok(mjd2000 + JD_AT_MJD2000_ZERO)
}
pub fn mjd2000_to_mjd(mjd2000: f64) -> Result<f64> {
ensure_finite("mjd2000", mjd2000)?;
Ok(mjd2000 + MJD_AT_MJD2000_ZERO)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::PykepError;
#[test]
fn reference_epoch_conversions_are_exact() {
assert_eq!(jd_to_mjd(2_451_544.5), Ok(51_544.0));
assert_eq!(jd_to_mjd2000(2_451_544.5), Ok(0.0));
assert_eq!(mjd_to_jd(51_544.0), Ok(2_451_544.5));
assert_eq!(mjd_to_mjd2000(51_544.0), Ok(0.0));
assert_eq!(mjd2000_to_jd(0.0), Ok(2_451_544.5));
assert_eq!(mjd2000_to_mjd(0.0), Ok(51_544.0));
}
#[test]
fn finite_conversions_round_trip() {
for value in [-100_000.25, 0.0, 51_544.5, 1_000_000.75] {
assert_eq!(mjd_to_jd(jd_to_mjd(value).unwrap()).unwrap(), value);
assert_eq!(mjd2000_to_jd(jd_to_mjd2000(value).unwrap()).unwrap(), value);
}
}
#[test]
fn non_finite_day_counts_are_rejected() {
assert_eq!(
jd_to_mjd(f64::NAN),
Err(PykepError::NonFiniteInput {
parameter: "julian_date"
})
);
assert!(mjd2000_to_jd(f64::INFINITY).is_err());
}
}