#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TimeScale {
Utc,
Tai,
Tt,
Tdb,
Gpst,
Gst,
Bdt,
}
impl TimeScale {
pub fn abbrev(self) -> &'static str {
match self {
TimeScale::Utc => "UTC",
TimeScale::Tai => "TAI",
TimeScale::Tt => "TT",
TimeScale::Tdb => "TDB",
TimeScale::Gpst => "GPST",
TimeScale::Gst => "GST",
TimeScale::Bdt => "BDT",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct JulianDateSplit {
pub jd_whole: f64,
pub fraction: f64,
}
impl JulianDateSplit {
pub fn new(jd_whole: f64, fraction: f64) -> Self {
Self { jd_whole, fraction }
}
pub fn to_jd(self) -> f64 {
self.jd_whole + self.fraction
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum InstantRepr {
Nanos(i128),
JulianDate(JulianDateSplit),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Instant {
pub scale: TimeScale,
pub repr: InstantRepr,
}
impl Instant {
pub fn from_julian_date(scale: TimeScale, jd: JulianDateSplit) -> Self {
Self {
scale,
repr: InstantRepr::JulianDate(jd),
}
}
pub fn from_nanos(scale: TimeScale, nanos: i128) -> Self {
Self {
scale,
repr: InstantRepr::Nanos(nanos),
}
}
pub fn julian_date(&self) -> Option<JulianDateSplit> {
match self.repr {
InstantRepr::JulianDate(jd) => Some(jd),
InstantRepr::Nanos(_) => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Duration {
pub nanos: i128,
}
impl Duration {
pub const ZERO: Duration = Duration { nanos: 0 };
pub fn from_nanos(nanos: i128) -> Self {
Self { nanos }
}
pub fn from_seconds(seconds: f64) -> Self {
Self {
nanos: (seconds * 1e9) as i128,
}
}
pub fn as_seconds(self) -> f64 {
self.nanos as f64 / 1e9
}
}
pub const SECONDS_PER_WEEK: f64 = 604_800.0;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GnssWeekTow {
pub system: TimeScale,
pub week: u32,
pub tow_s: f64,
}
impl GnssWeekTow {
pub fn new(system: TimeScale, week: u32, tow_s: f64) -> Self {
Self {
system,
week,
tow_s,
}
}
pub fn normalized(self) -> Self {
let mut week = self.week as i64;
let mut tow = self.tow_s;
let weeks_carry = (tow / SECONDS_PER_WEEK).floor();
week += weeks_carry as i64;
tow -= weeks_carry * SECONDS_PER_WEEK;
if week < 0 {
week = 0;
tow = 0.0;
}
Self {
system: self.system,
week: week as u32,
tow_s: tow,
}
}
pub fn unrolled_week(self, rollovers: u32) -> u32 {
self.week + rollovers * 1024
}
}