use crate::Deserialize;
use crate::Serialize;
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
pub type DateTime = OffsetDateTime;
pub use time::{Date, Time};
#[repr(i8)]
#[derive(Copy, Clone, Debug, std::cmp::PartialEq)]
pub enum TimeSpec {
LocalUnknown = -0x01,
LocalStandard = 0x00,
LocalDST = 0x01,
UTC = 0x02,
OffsetFromUTC = 0x03,
}
impl From<i8> for TimeSpec {
fn from(val: i8) -> Self {
match val {
-0x01 => TimeSpec::LocalUnknown,
0x00 => TimeSpec::LocalStandard,
0x01 => TimeSpec::LocalDST,
0x02 => TimeSpec::UTC,
0x03 => TimeSpec::OffsetFromUTC,
_ => unimplemented!(),
}
}
}
impl Serialize for OffsetDateTime {
fn serialize(&self) -> Result<Vec<u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
values.extend(i32::serialize(&(self.date().julian_day() as i32))?);
let time: i32 = {
let hour: i32 = self.time().hour() as i32;
let minute: i32 = self.time().minute() as i32;
let second: i32 = self.time().second() as i32;
let milli: i32 = self.time().millisecond() as i32;
milli + (second * 1000) + (minute * 60000) + (hour * 60 * 60000)
};
values.extend(i32::serialize(&time)?);
values.extend(u8::serialize(&(TimeSpec::OffsetFromUTC as u8))?);
values.extend(i32::serialize(&self.offset().as_seconds())?);
Ok(values)
}
}
impl Deserialize for OffsetDateTime {
fn parse(b: &[u8]) -> Result<(usize, Self), failure::Error> {
let (_, julian_day) = i32::parse(&b[0..4])?;
let (_, millis_of_day) = i32::parse(&b[4..8])?;
let (_, zone) = u8::parse(&b[8..9])?;
let mut pos = 9;
let zone = TimeSpec::from(zone as i8);
let offset: UtcOffset;
match zone {
TimeSpec::LocalUnknown | TimeSpec::LocalStandard | TimeSpec::LocalDST => {
offset = UtcOffset::current_local_offset()
}
TimeSpec::UTC => offset = UtcOffset::UTC,
TimeSpec::OffsetFromUTC => {
let (_, tmp_offset) = i32::parse(&b[9..13])?;
pos += 4;
offset = UtcOffset::seconds(tmp_offset)
}
}
let date = Date::from_julian_day(julian_day as i64);
let hour = millis_of_day / 60 / 60000;
let minute = (millis_of_day - (hour * 60 * 60000)) / 60000;
let seconds = (millis_of_day - (hour * 60 * 60000) - (minute * 60000)) / 1000;
let millis = millis_of_day - (hour * 60 * 60000) - (minute * 60000) - (seconds * 1000);
let time =
Time::try_from_hms_milli(hour as u8, minute as u8, seconds as u8, millis as u16)?;
let primitivedatetime = PrimitiveDateTime::new(date, time);
let datetime = primitivedatetime.assume_offset(offset);
Ok((pos, datetime))
}
}
impl Serialize for Date {
fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
values.extend(i32::serialize(&(self.julian_day() as i32))?);
Ok(values)
}
}
impl Deserialize for Date {
fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> {
let (_, julian_day) = i32::parse(&b[0..4])?;
let date = Date::from_julian_day(julian_day as i64);
Ok((4, date))
}
}
impl Serialize for Time {
fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
let time: i32 = {
let hour: i32 = self.hour() as i32;
let minute: i32 = self.minute() as i32;
let second: i32 = self.second() as i32;
let milli: i32 = self.millisecond() as i32;
milli + (second * 1000) + (minute * 60000) + (hour * 60 * 60000)
};
values.extend(i32::serialize(&time)?);
Ok(values)
}
}
impl Deserialize for Time {
fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> {
let (_, millis_of_day) = i32::parse(&b[0..4])?;
let hour = millis_of_day / 60 / 60000;
let minute = (millis_of_day - (hour * 60 * 60000)) / 60000;
let seconds = (millis_of_day - (hour * 60 * 60000) - (minute * 60000)) / 1000;
let millis = millis_of_day - (hour * 60 * 60000) - (minute * 60000) - (seconds * 1000);
let time =
Time::try_from_hms_milli(hour as u8, minute as u8, seconds as u8, millis as u16)?;
Ok((4, time))
}
}