use crate::{
Dt, MARS_REF_TT, MARS_REF_TT_ATTOS, MARS_SOL_ATTOS, MARS_SOL_LENGTH_SEC, Real, Scale,
clamp_i128_to_i64, floor_f, to_sec_f,
};
impl Dt {
#[inline]
pub(crate) const fn to_attos_since_mars_msd_epoch(numerical_tt: Dt) -> i128 {
numerical_tt.to_attos() - MARS_REF_TT_ATTOS
}
pub const fn to_msd_exact(&self, current: Scale) -> (i64, u128) {
let tt = self.to(current, Scale::TT);
let elapsed = Self::to_attos_since_mars_msd_epoch(tt);
let whole_sols = elapsed.div_euclid(MARS_SOL_ATTOS);
let frac_attos = elapsed.rem_euclid(MARS_SOL_ATTOS) as u128;
(clamp_i128_to_i64(whole_sols), frac_attos)
}
#[inline]
pub const fn to_mtc(&self, current: Scale) -> Dt {
let (_, frac_attos) = self.to_msd_exact(current);
Dt::from_attos(frac_attos as i128, Scale::TAI)
}
pub const fn from_msd_exact(whole_sols: i64, frac_attos: u128) -> Self {
let elapsed_attos = (whole_sols as i128) * MARS_SOL_ATTOS + frac_attos as i128;
let tt = MARS_REF_TT.add(Dt::from_attos(elapsed_attos, Scale::TAI));
Self::from(tt.sec, tt.attos, Scale::TT)
}
pub const fn from_msd(msd: Real) -> Self {
let whole = floor_f(msd) as i64;
let frac = msd - f!(whole);
let frac_span = Dt::from_sec_f(frac * MARS_SOL_LENGTH_SEC);
Self::from_msd_exact(whole, frac_span.to_attos() as u128)
}
#[inline]
pub const fn to_msd(&self, current: Scale) -> Real {
let (whole, frac) = self.to_msd_exact(current);
f!(whole) + to_sec_f(frac) / MARS_SOL_LENGTH_SEC
}
}