use crate::Serializable;
use crate::Serializer;
#[derive(Default, Clone, Copy, PartialEq, PartialOrd, Debug)]
pub struct AbsoluteDate {
pub year: u16,
pub month: u8,
pub day: u8
}
impl AbsoluteDate {
pub fn to_relative_date(self, start_date: &AbsoluteDate) -> Result<RelativeDate, Box<dyn std::error::Error>> {
let yd: u32 = self.year.checked_sub(start_date.year)
.map(|x| x as u32)
.ok_or("year is before start date")?;
let mf: i32 = self.month as i32 - start_date.month as i32;
let df: i32 = self.day as i32 - start_date.day as i32;
let md: u32 = [12 + mf, mf][(mf >= 0) as usize].try_into()?;
let dd: u32 = [30 + df, df][(df >= 0) as usize].try_into()?;
Ok(RelativeDate(yd * 365 + md * 30 + dd))
}
pub fn parse(ident: &str) -> Result<Self, Box<dyn std::error::Error>> {
let mut parts = ident.split(".");
let mut f = Self::default();
f.year = parts.next().unwrap_or_else(|| &"1499").parse::<u16>().unwrap_or_default();
f.month = parts.next().unwrap_or_else(|| &"1").parse::<u8>().unwrap_or_default();
f.day = parts.next().unwrap_or_else(|| &"1").parse::<u8>().unwrap_or_default();
Ok(f)
}
}
impl Serializable for AbsoluteDate {
fn serialize(&self, s: &mut Serializer) {
self.year.serialize(s);
self.month.serialize(s);
self.day.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.year.deserialize(s);
self.month.deserialize(s);
self.day.deserialize(s);
}
}
#[derive(Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct RelativeDate(u32);
impl std::ops::Add<u32> for RelativeDate {
type Output = RelativeDate;
fn add(self, rhs: u32) -> Self::Output {
RelativeDate(self.0.add(rhs))
}
}
impl std::ops::Sub<u32> for RelativeDate {
type Output = RelativeDate;
fn sub(self, rhs: u32) -> Self::Output {
RelativeDate(self.0.sub(rhs))
}
}
impl From<u8> for RelativeDate { fn from(v: u8) -> Self { Self(v as u32) } }
impl From<u16> for RelativeDate { fn from(v: u16) -> Self { Self(v as u32) } }
impl From<u32> for RelativeDate { fn from(v: u32) -> Self { Self(v as u32) } }
impl From<i8> for RelativeDate { fn from(v: i8) -> Self { Self(v as u32) } }
impl From<i16> for RelativeDate { fn from(v: i16) -> Self { Self(v as u32) } }
impl From<i32> for RelativeDate { fn from(v: i32) -> Self { Self(v as u32) } }
impl Serializable for RelativeDate {
fn serialize(&self, s: &mut Serializer) {
self.0.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.0.deserialize(s);
}
}
impl RelativeDate {
pub fn to_raw_value(&self) -> u32 {
self.0
}
pub fn to_absolute_date(self, start_date: &AbsoluteDate) -> AbsoluteDate {
let year = start_date.year as u32 + self.0 / 365;
let month = (start_date.month as u32 + self.0 / 30) % 12 + 1;
let day = (start_date.day as u32 + self.0) % 30 + 1;
AbsoluteDate{
year: unsafe { year.try_into().unwrap_unchecked() },
month: unsafe { month.try_into().unwrap_unchecked() },
day: unsafe { day.try_into().unwrap_unchecked() },
}
}
}