diff --git a/src/datetime.rs b/src/datetime.rs index fb02339..a9b035a 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -48,6 +48,7 @@ impl DateTime { // days plus some remainder. So we use self.days - 1 for our calculations seconds += i64::from(self.day - 1) * SECONDS_PER_DAY; seconds += i64::from(self.hour) * SECONDS_PER_HOUR; + seconds += i64::from(self.minute) * SECONDS_PER_MINUTE; seconds += i64::from(self.second); seconds += self.zone.as_seconds(); seconds @@ -138,6 +139,29 @@ impl DateTime { } } } + + pub fn weekday(&self) -> Weekday { + let ts = self.timestamp(); + let days = ts / SECONDS_PER_DAY; + let rem = days % 7; + rem.try_into().unwrap() + } +} + +impl fmt::Display for DateTime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}-{:0>2}-{:0>2}T{:0>2}:{:0>2}:{:0>2}{}", + self.year.get(), + self.month as u8, + self.day, + self.hour, + self.minute, + self.second, + self.zone, + ) + } } impl Ord for DateTime { @@ -153,3 +177,87 @@ impl PartialOrd for DateTime { Some(self.cmp(other)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn weekday() { + let mut dt = DateTime { + year: Year::new(2024), + month: Month::Janurary, + day: 29, + hour: 18, + minute: 14, + second: 42, + zone: TimeZone::Utc, + }; + assert_eq!(dt.weekday(), Weekday::Monday); + dt = DateTime { + year: Year::new(2024), + month: Month::Janurary, + day: 27, + hour: 12, + minute: 42, + second: 14, + zone: TimeZone::Offset { + sign: crate::zone::Sign::Positive, + hours: 3, + minutes: 15, + }, + }; + assert_eq!(dt.weekday(), Weekday::Saturday); + } + + #[test] + fn ord() { + let a = DateTime { + year: Year::new(2024), + month: Month::Janurary, + day: 29, + hour: 18, + minute: 28, + second: 42, + zone: TimeZone::new(Some(4), None).unwrap(), + }; + let b = DateTime { + year: Year::new(2024), + month: Month::Janurary, + day: 29, + hour: 18, + minute: 05, + second: 42, + zone: TimeZone::new(Some(5), None).unwrap(), + }; + assert!(a < b); + } + + #[test] + fn ts() { + let ts: i64 = 1706571482; + let dt = DateTime { + year: Year::new(2024), + month: Month::Janurary, + day: 29, + hour: 23, + minute: 38, + second: 02, + zone: TimeZone::Utc, + }; + assert_eq!(dt.timestamp(), ts); + assert_eq!(dt, DateTime::from_timestamp(ts)); + } + + #[test] + fn fmt() { + let mut dt = DateTime::from_timestamp(1706571482); + assert_eq!(dt.to_string(), "2024-01-29T23:38:02Z"); + dt.zone = TimeZone::Offset { + sign: crate::zone::Sign::Positive, + hours: 4, + minutes: 15, + }; + assert_eq!(dt.to_string(), "2024-01-29T23:38:02+04:15") + } +} diff --git a/src/weekday.rs b/src/weekday.rs index d6dd97f..3c285bb 100644 --- a/src/weekday.rs +++ b/src/weekday.rs @@ -11,3 +11,23 @@ pub enum Weekday { Tuesday, Wednesday, } + +impl TryFrom for Weekday { + type Error = ParseWeekdayError; + + fn try_from(value: i64) -> Result { + match value { + 0 => Ok(Self::Thursday), + 1 => Ok(Self::Friday), + 2 => Ok(Self::Saturday), + 3 => Ok(Self::Sunday), + 4 => Ok(Self::Monday), + 5 => Ok(Self::Tuesday), + 6 => Ok(Self::Wednesday), + _ => Err(ParseWeekdayError), + } + } +} + +#[derive(Debug)] +pub struct ParseWeekdayError; diff --git a/src/zone.rs b/src/zone.rs index e2d45e3..2432671 100644 --- a/src/zone.rs +++ b/src/zone.rs @@ -105,7 +105,7 @@ impl fmt::Display for TimeZone { hours, minutes, } => { - write!(f, "{sign}{hours}:{minutes}") + write!(f, "{sign}{hours:0>2}:{minutes:0>2}") } } }