diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/date.rs | 112 | ||||
-rw-r--r-- | src/event.rs | 108 | ||||
-rw-r--r-- | src/events.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 1 |
4 files changed, 116 insertions, 108 deletions
diff --git a/src/date.rs b/src/date.rs new file mode 100644 index 0000000..185a817 --- /dev/null +++ b/src/date.rs @@ -0,0 +1,112 @@ +use std::cmp::{Ordering, Ord, PartialEq, PartialOrd}; +use std::str::FromStr; + +use errors::EventError; + +use chrono; +use chrono::TimeZone; +use chrono_tz::{Tz, UTC}; + + +#[derive(Debug, Copy, Clone, Eq)] +pub enum Date { + Time(chrono::DateTime<Tz>), + AllDay(chrono::Date<Tz>), +} + + +impl Date { + pub fn empty() -> Date { + Date::Time(UTC.timestamp(0, 0)) + } + + pub fn parse(date: &String, time_zone: &String) -> Result<Self, EventError> { + let absolute_time = date.chars().rev().next().unwrap() == 'Z'; + let tz: Tz = if absolute_time { + UTC + } else { + // FIXME: this should not be UTC but local timezone + time_zone.parse().unwrap_or(UTC) + }; + + let date = match date.find("T") { + Some(_) => { + let date_pattern = if absolute_time { + "%Y%m%dT%H%M%SZ" + } else { + "%Y%m%dT%H%M%S" + }; + let time = tz.datetime_from_str(&date, date_pattern).unwrap_or( + UTC.timestamp(0, 0), + ); + Date::Time(time) + } + None => { + Date::AllDay(tz.ymd( + i32::from_str(&date[0..4])?, + u32::from_str(&date[4..6])?, + u32::from_str(&date[6..8])?, + )) + } + }; + Ok(date) + } +} + +impl Ord for Date { + fn cmp(&self, other: &Self) -> Ordering { + match *self { + Date::Time(t1) => { + match *other { + Date::Time(t2) => t1.cmp(&t2), + Date::AllDay(d) => cmp_date_time(&d, &t1).reverse(), + } + } + Date::AllDay(d1) => { + match *other { + Date::Time(t) => cmp_date_time(&d1, &t), + Date::AllDay(d2) => d1.cmp(&d2), + } + } + } + } +} + +impl PartialOrd for Date { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl PartialEq for Date { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +fn cmp_date_time<T: TimeZone>(date: &chrono::Date<T>, time: &chrono::DateTime<T>) -> Ordering { + let d2 = time.date(); + if date.eq(&d2) { + return Ordering::Less; + } + date.cmp(&d2) +} + +#[cfg(test)] +mod tests { + use super::Date; + use chrono::Datelike; + use chrono::Timelike; + + #[test] + fn date_parse_time() { + match Date::parse(&String::from("19361020T120000"), &String::new()).unwrap() { + Date::Time(time) => { + assert_eq!(time.year(), 1936); + assert_eq!(time.hour(), 12); + assert_eq!(time.day(), 20); + } + _ => assert!(true), + } + } +} diff --git a/src/event.rs b/src/event.rs index bf97727..904b718 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,11 +1,7 @@ -use std::cmp::{Ordering, Ord, PartialEq, PartialOrd}; use std::fmt; use std::str::FromStr; -use chrono; -use chrono::TimeZone; -use chrono_tz::{Tz, UTC}; - +use date::Date; use errors::EventError; @@ -19,12 +15,6 @@ pub struct Event { pub status: Status, } -#[derive(Debug, Copy, Clone, Eq)] -pub enum Date { - Time(chrono::DateTime<Tz>), - AllDay(chrono::Date<Tz>), -} - #[derive(Debug, Copy, Clone)] pub enum Status { Confirmed, @@ -59,75 +49,6 @@ impl fmt::Display for Event { } } -impl Date { - pub fn empty() -> Date { - Date::Time(UTC.timestamp(0, 0)) - } - - pub fn parse(date: &String, time_zone: &String) -> Result<Self, EventError> { - let absolute_time = date.chars().rev().next().unwrap() == 'Z'; - let tz: Tz = if absolute_time { - UTC - } else { - // FIXME: this should not be UTC but local timezone - time_zone.parse().unwrap_or(UTC) - }; - - let date = match date.find("T") { - Some(_) => { - let date_pattern = if absolute_time { - "%Y%m%dT%H%M%SZ" - } else { - "%Y%m%dT%H%M%S" - }; - let time = tz.datetime_from_str(&date, date_pattern).unwrap_or( - UTC.timestamp(0, 0), - ); - Date::Time(time) - } - None => { - Date::AllDay(tz.ymd( - i32::from_str(&date[0..4])?, - u32::from_str(&date[4..6])?, - u32::from_str(&date[6..8])?, - )) - } - }; - Ok(date) - } -} - -impl Ord for Date { - fn cmp(&self, other: &Self) -> Ordering { - match *self { - Date::Time(t1) => { - match *other { - Date::Time(t2) => t1.cmp(&t2), - Date::AllDay(d) => cmp_date_time(&d, &t1).reverse(), - } - } - Date::AllDay(d1) => { - match *other { - Date::Time(t) => cmp_date_time(&d1, &t), - Date::AllDay(d2) => d1.cmp(&d2), - } - } - } - } -} - -impl PartialOrd for Date { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl PartialEq for Date { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} - impl FromStr for Status { type Err = EventError; @@ -140,30 +61,3 @@ impl FromStr for Status { } } } - -fn cmp_date_time<T: TimeZone>(date: &chrono::Date<T>, time: &chrono::DateTime<T>) -> Ordering { - let d2 = time.date(); - if date.eq(&d2) { - return Ordering::Less; - } - date.cmp(&d2) -} - -#[cfg(test)] -mod tests { - use super::Date; - use chrono::Datelike; - use chrono::Timelike; - - #[test] - fn date_parse_time() { - match Date::parse(&String::from("19361020T120000"), &String::new()).unwrap() { - Date::Time(time) => { - assert_eq!(time.year(), 1936); - assert_eq!(time.hour(), 12); - assert_eq!(time.day(), 20); - } - _ => assert!(true), - } - } -} diff --git a/src/events.rs b/src/events.rs index 948e86a..b0111e7 100644 --- a/src/events.rs +++ b/src/events.rs @@ -2,7 +2,8 @@ use std::io::BufRead; use std::fmt; use ical::IcalParser; -use event::{Event, Date}; +use date::Date; +use event::Event; use periodic::Periodic; use errors::EventError; diff --git a/src/main.rs b/src/main.rs index 6b011bd..022b811 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate ical; extern crate chrono; extern crate chrono_tz; +mod date; mod event; mod periodic; mod events; |