use crate::constats::GPS_EPOCH_JD_TAI;
use crate::context::TimeContext;
use crate::error::ConversionError;
use crate::format::{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,
JdTdb,
JdTai,
JdTcg,
JdTcb,
JdGps,
JdUt1,
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::JdTdb => {
JulianDate::<TDB>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::JdTai => {
JulianDate::<TAI>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::JdTcg => {
JulianDate::<TCG>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::JdTcb => {
JulianDate::<TCB>::try_new(Day::new(value)).map(|e| e.to_time().to_scale::<TT>())
}
ScaleKind::JdGps => JulianDate::<TAI>::try_new(GPS_EPOCH_JD_TAI.raw() + Day::new(value))
.map(|e| e.to_time().to_scale::<TT>()),
ScaleKind::JdUt1 => 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::format::{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::JdTdb => Ok(tt.to_scale::<TDB>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::JdTai => Ok(tt.to_scale::<TAI>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::JdTcg => Ok(tt.to_scale::<TCG>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::JdTcb => Ok(tt.to_scale::<TCB>().to::<JD>().raw() / Day::new(1.0)),
ScaleKind::JdGps => {
Ok((tt.to_scale::<TAI>().to::<JD>().raw() - GPS_EPOCH_JD_TAI.raw()) / Day::new(1.0))
}
ScaleKind::JdUt1 => 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),
}
}