use crate::{
Date, Duration, MilliSeconds, Month, TimePoint,
time_scale::{AbsoluteTimeScale, TerrestrialTime, TimeScale, datetime::UniformDateTimeScale},
units::{Milli, Second},
};
pub type TtTime<Representation = i64, Period = Second> = TimePoint<Tt, Representation, Period>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Tt;
impl TimeScale for Tt {
const NAME: &'static str = "Terrestrial Time";
const ABBREVIATION: &'static str = "TT";
}
impl AbsoluteTimeScale for Tt {
const EPOCH: Date<i32> = match Date::from_historic_date(1977, Month::January, 1) {
Ok(epoch) => epoch,
Err(_) => unreachable!(),
};
}
impl UniformDateTimeScale for Tt {}
impl TerrestrialTime for Tt {
type Representation = u16;
type Period = Milli;
const TAI_OFFSET: Duration<Self::Representation, Self::Period> = MilliSeconds::new(32_184);
}
#[test]
fn known_timestamps() {
use crate::{IntoTimeScale, Month, TaiTime};
let tai = TaiTime::from_historic_datetime(2004, Month::May, 14, 16, 43, 32).unwrap();
let tt = TtTime::from_fine_historic_datetime(
2004,
Month::May,
14,
16,
44,
4,
crate::MilliSeconds::new(184i64),
)
.unwrap();
assert_eq!(tai.into_unit(), tt.into_time_scale());
}
#[test]
fn date_decomposition() {
let time =
TtTime::<i64, Second>::from_historic_datetime(2004, Month::May, 14, 16, 44, 4).unwrap();
let (date, hour, minute, second) = time.into_historic_datetime();
assert_eq!(date.year(), 2004);
assert_eq!(date.month(), Month::May);
assert_eq!(date.day(), 14);
assert_eq!(hour, 16);
assert_eq!(minute, 44);
assert_eq!(second, 4);
}
#[cfg(kani)]
mod proof_harness {
use super::*;
use crate::TaiTime;
#[kani::proof]
fn from_datetime_never_panics() {
use crate::FromDateTime;
let date: Date<i32> = kani::any();
let hour: u8 = kani::any();
let minute: u8 = kani::any();
let second: u8 = kani::any();
let _ = TtTime::from_datetime(date, hour, minute, second);
}
#[kani::proof]
fn datetime_tai_roundtrip() {
use crate::{FromDateTime, IntoTimeScale, units::Milli};
let date: Date<i32> = kani::any();
let hour: u8 = kani::any();
let minute: u8 = kani::any();
let second: u8 = kani::any();
kani::assume(hour < 24);
kani::assume(minute < 60);
kani::assume(second < 60);
let time1 = TtTime::from_datetime(date, hour, minute, second);
if let Ok(time1) = time1 {
let time1: TtTime<_, Milli> = time1.into_unit();
let tai: TaiTime<i64, _> = time1.into_time_scale();
let time2: TtTime<i64, _> = tai.into_time_scale();
assert_eq!(time1, time2);
}
}
}