diff options
Diffstat (limited to 'src/primitive/datetime.rs')
| -rw-r--r-- | src/primitive/datetime.rs | 171 |
1 files changed, 112 insertions, 59 deletions
diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs index e6946b9..cbcdd51 100644 --- a/src/primitive/datetime.rs +++ b/src/primitive/datetime.rs @@ -1,107 +1,160 @@ use crate::Deserialize; use crate::Serialize; -/// The DateTime struct represents a DateTime as received in IRC -/// -/// DateTime is, like all other struct based types, serialized sequentially. -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct DateTime { - /// Day in Julian calendar, unknown if signed or unsigned - julian_day: i32, - /// Milliseconds since start of day - millis_of_day: i32, - /// Timezone of DateTime, 0x00 is local, 0x01 is UTC - zone: u8, +use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset}; + +// The DateTime struct represents a DateTime as received in IRC +// +// DateTime is, like all other struct based types, serialized sequentially. +// #[derive(Clone, Debug, std::cmp::PartialEq)] +// pub struct DateTime { +// /// Day in Julian calendar, unknown if signed or unsigned +// julian_day: i32, +// /// Milliseconds since start of day +// millis_of_day: i32, +// /// Timezone of DateTime, 0x00 is local, 0x01 is UTC +// zone: u8, +// } + +pub type DateTime = OffsetDateTime; +pub use time::{Date, Time}; + +/// TimeSpec specifies whether the time is a local time, daylightsaving local time or a form of UTC Offset +#[repr(i8)] +#[derive(Copy, Clone, Debug, std::cmp::PartialEq)] +pub enum TimeSpec { + LocalUnknown = -0x01, + LocalStandard = 0x00, + LocalDST = 0x01, + UTC = 0x02, + OffsetFromUTC = 0x03, } -impl Serialize for DateTime { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { +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.append(&mut i32::serialize(&self.julian_day)?); - values.append(&mut i32::serialize(&self.millis_of_day)?); - values.append(&mut u8::serialize(&(self.zone))?); + 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 DateTime { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> - where - Self: Sized, - { +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])?; - return Ok(( - 9, - DateTime { - julian_day, - millis_of_day, - zone, - }, - )); - } -} + 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) + } + } -/// The Date struct represents a Date as received in IRC -/// -/// Date is, like all other struct based types, serialized sequentially. -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct Date { - /// Day in Julian calendar, unknown if signed or unsigned - julian_day: i32, + 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.append(&mut i32::serialize(&self.julian_day)?); + 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> - where - Self: Sized, - { + 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); - return Ok((9, Date { julian_day })); + Ok((4, date)) } } -/// The Time struct represents a Time as received in IRC -/// -/// Time is, like all other struct based types, serialized sequentially. -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct Time { - /// Milliseconds since start of day - millis_of_day: i32, -} - impl Serialize for Time { fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { let mut values: Vec<u8> = Vec::new(); - values.append(&mut i32::serialize(&self.millis_of_day)?); + 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> - where - Self: Sized, - { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { let (_, millis_of_day) = i32::parse(&b[0..4])?; - return Ok((4, Time { millis_of_day })); + 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)) } } |
