use core::{
convert::From,
ops::{Add, Sub},
};
use crate::{
ConvertUnit, Duration, FromTimeScale, TimePoint, TryFromExact, time_scale::AbsoluteTimeScale,
units::SecondsPerDay,
};
pub trait TerrestrialTime: AbsoluteTimeScale {
type Representation;
type Period;
const TAI_OFFSET: Duration<Self::Representation, Self::Period>;
}
impl<ScaleFrom, ScaleInto, Representation, Period> FromTimeScale<ScaleFrom, Representation, Period>
for TimePoint<ScaleInto, Representation, Period>
where
ScaleFrom: TerrestrialTime,
ScaleInto: TerrestrialTime,
Representation: Copy
+ Add<Representation, Output = Representation>
+ Sub<Representation, Output = Representation>
+ From<ScaleFrom::Representation>
+ From<ScaleInto::Representation>
+ TryFromExact<i32>
+ ConvertUnit<ScaleFrom::Period, Period>
+ ConvertUnit<ScaleInto::Period, Period>
+ ConvertUnit<SecondsPerDay, Period>
+ PartialOrd,
{
fn from_time_scale(time_point: TimePoint<ScaleFrom, Representation, Period>) -> Self {
let epoch_offset = ScaleFrom::EPOCH.elapsed_calendar_days_since(ScaleInto::EPOCH);
let epoch_offset = epoch_offset
.try_cast()
.unwrap_or_else(|_| panic!())
.into_unit();
let from_offset: Duration<Representation, Period> =
ScaleFrom::TAI_OFFSET.cast().into_unit();
let into_offset: Duration<Representation, Period> =
ScaleInto::TAI_OFFSET.cast().into_unit();
let time_since_epoch = if from_offset >= into_offset {
let scale_offset = from_offset - into_offset;
time_point.time_since_epoch() - scale_offset + epoch_offset
} else {
let scale_offset = into_offset - from_offset;
time_point.time_since_epoch() + scale_offset + epoch_offset
};
Self::from_time_since_epoch(time_since_epoch)
}
}