use crate::constats::GPS_EPOCH_JD_TAI;
use crate::context::TimeContext;
use crate::error::ConversionError;
use crate::representation::{JulianDate, ModifiedJulianDate, UnixTime};
use crate::scale::{TAI, TCB, TCG, TDB, TT, UT1, UTC};
use crate::time::Time;
use qtty::{Day, Second};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScaleKind {
JdTt,
MjdTt,
Tdb,
Tai,
Tcg,
Tcb,
GpsDays,
Ut1,
Unix,
}
#[inline]
pub fn time_tt_from_scalar(
value: f64,
kind: ScaleKind,
ctx: &TimeContext,
) -> Result<Time<TT>, ConversionError> {
match kind {
ScaleKind::JdTt => JulianDate::<TT>::try_new(Day::new(value)).map(|e| e.to_time()),
ScaleKind::MjdTt => ModifiedJulianDate::<TT>::try_new(Day::new(value)).map(|e| e.to_time()),
ScaleKind::Tdb => {
JulianDate::<TDB>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::Tai => {
JulianDate::<TAI>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::Tcg => {
JulianDate::<TCG>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::Tcb => {
JulianDate::<TCB>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::GpsDays => JulianDate::<TAI>::try_new(GPS_EPOCH_JD_TAI + Day::new(value))
.map(|e| e.to_time().to_scale::<TT>()),
ScaleKind::Ut1 => JulianDate::<UT1>::try_new(Day::new(value))
.and_then(|e| e.to_time().to_scale_with::<TT>(ctx)),
ScaleKind::Unix => UnixTime::try_new(Second::new(value))
.and_then(|e| e.to_time_with(ctx))
.map(|t| t.to_scale::<TT>()),
}
}
#[inline]
pub fn time_tt_to_scalar(
tt: Time<TT>,
kind: ScaleKind,
ctx: &TimeContext,
) -> Result<f64, ConversionError> {
use crate::representation::{JD, MJD};
match kind {
ScaleKind::JdTt => Ok(tt.to::<JD>().raw() / Day::new(1.0)),
ScaleKind::MjdTt => Ok(tt.to::<MJD>().raw() / Day::new(1.0)),
ScaleKind::Tdb => Ok(tt.to_scale::<TDB>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::Tai => Ok(tt.to_scale::<TAI>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::Tcg => Ok(tt.to_scale::<TCG>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::Tcb => Ok(tt.to_scale::<TCB>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::GpsDays => {
Ok((tt.to_scale::<TAI>().to::<JD>().raw() - GPS_EPOCH_JD_TAI) / Day::new(1.0))
}
ScaleKind::Ut1 => Ok(tt.to_scale_with::<UT1>(ctx)?.to::<JD>().raw() / Day::new(1.0)),
ScaleKind::Unix => tt
.to_scale::<UTC>()
.raw_unix_seconds_with(ctx)
.map(|s| s / Second::new(1.0)),
}
}
#[inline]
pub fn scalar_difference_in_days(lhs: f64, rhs: f64, kind: ScaleKind) -> f64 {
match kind {
ScaleKind::Unix => Second::new(lhs - rhs).to::<qtty::unit::Day>() / Day::new(1.0),
_ => lhs - rhs,
}
}
#[inline]
pub fn scalar_add_days(value: f64, days: Day, kind: ScaleKind) -> f64 {
match kind {
ScaleKind::Unix => value + days.to::<qtty::unit::Second>() / Second::new(1.0),
_ => value + days / Day::new(1.0),
}
}