diff options
author | Fredrik Meringdal <fmeringdal@hotmail.com> | 2020-10-20 22:08:19 +0200 |
---|---|---|
committer | Fredrik Meringdal <fmeringdal@hotmail.com> | 2020-10-20 22:08:19 +0200 |
commit | eac4ef5fe5f0b86b576736ea49b53043c24c1357 (patch) | |
tree | 900d6ef011340e424949de496fd59dbf64bfd7a1 /src | |
parent | cda2ac25b9e5f091f354dccabd86d97c19c4ccde (diff) | |
download | rust_rrule-eac4ef5fe5f0b86b576736ea49b53043c24c1357.zip |
some refactoring and it works
Diffstat (limited to 'src')
-rw-r--r-- | src/iter.rs | 11 | ||||
-rw-r--r-- | src/iter_set.rs | 405 | ||||
-rw-r--r-- | src/options.rs | 4 | ||||
-rw-r--r-- | src/rrule.rs | 3 | ||||
-rw-r--r-- | src/rruleset.rs | 348 |
5 files changed, 361 insertions, 410 deletions
diff --git a/src/iter.rs b/src/iter.rs index d777df7..8a47002 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -18,8 +18,7 @@ pub struct IterArgs { pub inc: bool, pub before: DateTime<Tz>, pub after: DateTime<Tz>, - pub dt: DateTime<Tz>, - pub _value: Option<Vec<DateTime<Utc>>>, + pub dt: DateTime<Tz> } pub struct IterResult { @@ -27,7 +26,7 @@ pub struct IterResult { pub args: IterArgs, pub min_date: Option<DateTime<Tz>>, pub max_date: Option<DateTime<Tz>>, - pub _result: Vec<DateTime<Tz>>, + pub result: Vec<DateTime<Tz>>, pub total: usize, } @@ -52,7 +51,7 @@ impl IterResult { min_date, max_date, total: 0, - _result: vec![], + result: vec![], } } @@ -75,12 +74,12 @@ impl IterResult { } pub fn add(&mut self, date: DateTime<Tz>) -> bool { - self._result.push(date); + self.result.push(date); true } pub fn get_value(&self) -> Vec<DateTime<Tz>> { - self._result.clone() + self.result.clone() //match self.method { //QueryMethodTypes::BETWEEN => Some(self._result.clone()), //_ => { diff --git a/src/iter_set.rs b/src/iter_set.rs index 4cc864c..a8a7e48 100644 --- a/src/iter_set.rs +++ b/src/iter_set.rs @@ -9,122 +9,12 @@ use chrono::{DateTime, Duration, Utc}; use chrono_tz::*; use std::collections::HashMap; -pub fn eval_exdate( - after: &DateTime<Tz>, - before: &DateTime<Tz>, - exrule: &mut Vec<RRule>, - exdate_hash: &mut HashMap<i64, bool>, -) { - for rrule in exrule.iter_mut() { - for date in rrule.between(after, before, true) { - exdate_hash.insert(date.timestamp(), true); - } - } -} - -fn accept_1( - date: DateTime<Tz>, - exdate_hash: &mut HashMap<i64, bool>, - exrule: &mut Vec<RRule>, - iter_res: &mut IterResult, -) -> bool { - println!("Accept 1"); - println!("Exdates: {:?}", exdate_hash); - let dt = date.timestamp(); - if !exdate_hash.contains_key(&dt) { - eval_exdate( - &UTC.timestamp(dt - 1, 0), - &UTC.timestamp(dt + 1, 0), - exrule, - exdate_hash, - ); - if !exdate_hash.contains_key(&dt) { - exdate_hash.insert(dt, true); - return iter_res.accept(date.clone()); - } - } - - true -} - -fn accept_2( - date: DateTime<Tz>, - exdate_hash: &mut HashMap<i64, bool>, - iter_res: &mut IterResult, -) -> bool { - let dt = date.timestamp(); - if !exdate_hash.contains_key(&dt) { - if !exdate_hash.contains_key(&dt) { - exdate_hash.insert(dt, true); - return iter_res.accept(date.clone()); - } - } - - true -} - -pub fn iter_set( - iter_res: &mut IterResult, - mut rrule: Vec<RRule>, - mut exrule: Vec<RRule>, - rdate: Vec<DateTime<Utc>>, - exdate: Vec<DateTime<Utc>>, - tzid: Option<String>, -) -> Vec<DateTime<Tz>> { - let tzid: Tz = tzid.unwrap_or(String::from("UTC")).parse().unwrap_or(UTC); - - let mut exdate_hash = HashMap::new(); - - for date in &exdate { - let zoned_date = date.with_timezone(&tzid); - exdate_hash.insert(zoned_date.timestamp(), true); - } - - match iter_res.method { - QueryMethodTypes::BETWEEN => { - eval_exdate( - &iter_res.args.after, - &iter_res.args.before, - &mut exrule, - &mut exdate_hash, - ); - } - _ => (), - }; - - for date in &rdate { - let zoned_date = date.with_timezone(&tzid); - println!("Zoned date: {:?}", zoned_date); - - match iter_res.method { - QueryMethodTypes::BETWEEN => { - if !accept_2(zoned_date, &mut exdate_hash, iter_res) { - break; - } - } - _ => { - if !accept_1(zoned_date, &mut exdate_hash, &mut exrule, iter_res) { - break; - } - } - }; - } - - for rule in rrule.iter_mut() { - iter_v2(iter_res, &mut rule.options, &mut exdate_hash, &mut exrule); - } - - let mut res = iter_res._result.clone(); - res.sort(); - res -} - -pub fn iter_v2( +pub fn iter_v2<F: FnMut(DateTime<Tz>, &mut IterResult) -> bool>( iter_result: &mut IterResult, options: &mut ParsedOptions, - exdate_hash: &mut HashMap<i64, bool>, - exrule: &mut Vec<RRule>, + mut accept: F ) -> Vec<DateTime<Tz>> { + if (options.count.is_some() && options.count.unwrap() == 0) || options.interval == 0 { return iter_result.get_value(); } @@ -167,14 +57,7 @@ pub fn iter_v2( //let rezoned_date = rezone_if_needed(&res, &options); let rezoned_date = UTC.timestamp(res.timestamp(), 0); - let accepted = match iter_result.method { - QueryMethodTypes::BETWEEN => { - accept_2(rezoned_date, exdate_hash, iter_result) - } - _ => accept_1(rezoned_date, exdate_hash, exrule, iter_result), - }; - - if !accepted { + if !accept(rezoned_date, iter_result) { return iter_result.get_value(); } @@ -208,19 +91,7 @@ pub fn iter_v2( //let rezoned_date = rezone_if_needed(&res, &options); let rezoned_date = UTC.timestamp(res.timestamp(), 0); - if rezoned_date.day() == 2 { - println!("yoooooooooooooooooooooooo"); - println!("iter date ts: {}", rezoned_date.timestamp()); - println!("Ex dates: {:?}", exdate_hash); - } - - let accepted = match iter_result.method { - QueryMethodTypes::BETWEEN => { - accept_2(rezoned_date, exdate_hash, iter_result) - } - _ => accept_1(rezoned_date, exdate_hash, exrule, iter_result), - }; - if !accepted { + if !accept(rezoned_date, iter_result) { return iter_result.get_value(); } if count > 0 { @@ -262,269 +133,3 @@ pub fn iter_v2( } } -#[cfg(test)] -mod test_iter_set { - use super::*; - - fn ymd_hms( - year: i32, - month: u32, - day: u32, - hour: u32, - minute: u32, - second: u32, - ) -> DateTime<Utc> { - Utc.ymd(year, month, day).and_hms(hour, minute, second) - } - - fn ymd_hms_2( - year: i32, - month: u32, - day: u32, - hour: u32, - minute: u32, - second: u32, - ) -> DateTime<Tz> { - UTC.ymd(year, month, day).and_hms(hour, minute, second) - } - - fn test_recurring(actual_dates: Vec<DateTime<Tz>>, expected_dates: Vec<DateTime<Tz>>) { - assert_eq!( - actual_dates.len(), - expected_dates.len(), - "Expected number of returned dates to be equal to the expected" - ); - - println!("Acutal: {:?}", actual_dates); - for (actual, exptected) in actual_dates.into_iter().zip(expected_dates) { - assert_eq!(actual, exptected); - } - } - - #[test] - fn rrule_and_exrule() { - let iter_args = IterArgs { - inc: true, - before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), - }; - let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); - - let mut options1 = ParsedOptions { - freq: Frequenzy::YEARLY, - count: Some(6), - bymonth: vec![], - dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), - byweekday: vec![1, 3], - byhour: vec![9], - bysetpos: vec![], - byweekno: vec![], - byminute: vec![0], - bysecond: vec![0], - byyearday: vec![], - bymonthday: vec![], - bynweekday: vec![], - bynmonthday: vec![], - until: None, - wkst: 0, - tzid: None, - interval: 1, - byeaster: None, - }; - let rrule1 = RRule::new(options1); - let mut options2 = ParsedOptions { - freq: Frequenzy::YEARLY, - count: Some(3), - bymonth: vec![], - dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), - byweekday: vec![3], - byhour: vec![9], - bysetpos: vec![], - byweekno: vec![], - byminute: vec![0], - bysecond: vec![0], - byyearday: vec![], - bymonthday: vec![], - bynweekday: vec![], - bynmonthday: vec![], - until: None, - wkst: 0, - tzid: None, - interval: 1, - byeaster: None, - }; - let rrule2 = RRule::new(options2); - - let res = iter_set( - &mut iter_res, - vec![rrule1], - vec![rrule2], - vec![], - vec![], - None, - ); - test_recurring( - res, - vec![ - ymd_hms_2(1997, 9, 2, 9, 0, 0), - ymd_hms_2(1997, 9, 9, 9, 0, 0), - ymd_hms_2(1997, 9, 16, 9, 0, 0), - ], - ); - } - - #[test] - fn setdate_and_exdate() { - let iter_args = IterArgs { - inc: true, - before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), - }; - let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); - - let res = iter_set( - &mut iter_res, - vec![], - vec![], - vec![ - ymd_hms(1997, 9, 2, 9, 0, 0), - ymd_hms(1997, 9, 4, 9, 0, 0), - ymd_hms(1997, 9, 9, 9, 0, 0), - ymd_hms(1997, 9, 11, 9, 0, 0), - ymd_hms(1997, 9, 16, 9, 0, 0), - ymd_hms(1997, 9, 18, 9, 0, 0), - ], - vec![ - ymd_hms(1997, 9, 4, 9, 0, 0), - ymd_hms(1997, 9, 11, 9, 0, 0), - ymd_hms(1997, 9, 18, 9, 0, 0), - ], - None, - ); - test_recurring( - res, - vec![ - ymd_hms_2(1997, 9, 2, 9, 0, 0), - ymd_hms_2(1997, 9, 9, 9, 0, 0), - ymd_hms_2(1997, 9, 16, 9, 0, 0), - ], - ); - } - - #[test] - fn setdate_and_exrule() { - let iter_args = IterArgs { - inc: true, - before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), - }; - let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); - - let mut options = ParsedOptions { - freq: Frequenzy::YEARLY, - count: Some(3), - bymonth: vec![], - dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), - byweekday: vec![3], - byhour: vec![9], - bysetpos: vec![], - byweekno: vec![], - byminute: vec![0], - bysecond: vec![0], - byyearday: vec![], - bymonthday: vec![], - bynweekday: vec![], - bynmonthday: vec![], - until: None, - wkst: 0, - tzid: None, - interval: 1, - byeaster: None, - }; - let exrrule = RRule::new(options); - let res = iter_set( - &mut iter_res, - vec![], - vec![exrrule], - vec![ - ymd_hms(1997, 9, 2, 9, 0, 0), - ymd_hms(1997, 9, 4, 9, 0, 0), - ymd_hms(1997, 9, 9, 9, 0, 0), - ymd_hms(1997, 9, 11, 9, 0, 0), - ymd_hms(1997, 9, 16, 9, 0, 0), - ymd_hms(1997, 9, 18, 9, 0, 0), - ], - vec![], - None, - ); - test_recurring( - res, - vec![ - ymd_hms_2(1997, 9, 2, 9, 0, 0), - ymd_hms_2(1997, 9, 9, 9, 0, 0), - ymd_hms_2(1997, 9, 16, 9, 0, 0), - ], - ); - } - - #[test] - fn rrule_and_exdate() { - let iter_args = IterArgs { - inc: true, - before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), - }; - let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); - - let mut options = ParsedOptions { - freq: Frequenzy::YEARLY, - count: Some(6), - bymonth: vec![], - dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), - byweekday: vec![1, 3], - byhour: vec![9], - bysetpos: vec![], - byweekno: vec![], - byminute: vec![0], - bysecond: vec![0], - byyearday: vec![], - bymonthday: vec![], - bynweekday: vec![], - bynmonthday: vec![], - until: None, - wkst: 0, - tzid: None, - interval: 1, - byeaster: None, - }; - let rrule = RRule::new(options); - let res = iter_set( - &mut iter_res, - vec![rrule], - vec![], - vec![], - vec![ - ymd_hms(1997, 9, 2, 9, 0, 0), - ymd_hms(1997, 9, 4, 9, 0, 0), - ymd_hms(1997, 9, 9, 9, 0, 0), - ], - None, - ); - test_recurring( - res, - vec![ - ymd_hms_2(1997, 9, 11, 9, 0, 0), - ymd_hms_2(1997, 9, 16, 9, 0, 0), - ymd_hms_2(1997, 9, 18, 9, 0, 0), - ], - ); - } -} diff --git a/src/options.rs b/src/options.rs index 59f1c43..c3aeff3 100644 --- a/src/options.rs +++ b/src/options.rs @@ -14,7 +14,7 @@ pub struct YearInfo { pub wnomask: Option<Vec<usize>>, } -#[derive(Debug, PartialEq, PartialOrd)] +#[derive(Debug, PartialEq, PartialOrd, Clone)] pub enum Frequenzy { YEARLY = 0, MONTHLY = 1, @@ -25,7 +25,7 @@ pub enum Frequenzy { SECONDLY = 6, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ParsedOptions { pub freq: Frequenzy, pub interval: usize, diff --git a/src/rrule.rs b/src/rrule.rs index 92b2ba5..53ccf39 100644 --- a/src/rrule.rs +++ b/src/rrule.rs @@ -3,6 +3,7 @@ use crate::options::*; use chrono::prelude::*; use chrono_tz::{Tz, UTC}; +#[derive(Clone, Debug)] pub struct RRule { cache: bool, pub options: ParsedOptions, @@ -26,7 +27,6 @@ impl RRule { before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), }; let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); @@ -45,7 +45,6 @@ impl RRule { before: before.clone(), after: after.clone(), dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), - _value: Some(vec![]), }; let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); diff --git a/src/rruleset.rs b/src/rruleset.rs index fe8a723..a725ae5 100644 --- a/src/rruleset.rs +++ b/src/rruleset.rs @@ -1,5 +1,10 @@ use crate::rrule::*; use chrono::prelude::*; +use chrono_tz::{Tz, UTC}; +use crate::options::*; +use crate::iter_set::iter_v2; +use crate::iter::*; +use std::collections::HashMap; struct RRuleSet { rrule: Vec<RRule>, @@ -7,6 +12,11 @@ struct RRuleSet { exrule: Vec<RRule>, exdate: Vec<DateTime<Utc>>, dtstart: Option<DateTime<Utc>>, + exdate_hash: HashMap<i64, ()> +} + +struct RRuleIter { + } impl RRuleSet { @@ -17,6 +27,7 @@ impl RRuleSet { exrule: vec![], exdate: vec![], dtstart: None, + exdate_hash: HashMap::new() } } @@ -36,6 +47,19 @@ impl RRuleSet { self.exdate.push(exdate); } + pub fn all(&mut self) -> Vec<DateTime<Tz>> { + + let iter_args = IterArgs { + inc: true, + before: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), + after: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), + dt: UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), + }; + let mut iter_res = IterResult::new(QueryMethodTypes::ALL, iter_args); + + self.iter(&mut iter_res, None) + } + pub fn value_of(&mut self) -> Vec<String> { let mut result = vec![]; @@ -72,4 +96,328 @@ impl RRuleSet { result } + + pub fn eval_exdate( + &mut self, + after: &DateTime<Tz>, + before: &DateTime<Tz>, + ) { + for rrule in self.exrule.iter_mut() { + for date in rrule.between(after, before, true) { + self.exdate_hash.insert(date.timestamp(), ()); + } + } + } + + + fn accept_2( + &mut self, + date: DateTime<Tz>, + iter_res: &mut IterResult, + ) -> bool { + let dt = date.timestamp(); + if !self.exdate_hash.contains_key(&dt) { + self.eval_exdate( + &UTC.timestamp(dt - 1, 0), + &UTC.timestamp(dt + 1, 0), + ); + if !self.exdate_hash.contains_key(&dt) { + self.exdate_hash.insert(dt, ()); + return iter_res.accept(date.clone()); + } + } + + true + } + + fn accept_1( + &mut self, + date: DateTime<Tz>, + iter_res: &mut IterResult, + ) -> bool { + let dt = date.timestamp(); + if !self.exdate_hash.contains_key(&dt) { + if !self.exdate_hash.contains_key(&dt) { + self.exdate_hash.insert(dt, ()); + return iter_res.accept(date.clone()); + } + } + + true + } + + fn accept( + &mut self, + date: DateTime<Tz>, + iter_res: &mut IterResult) -> bool { + match &iter_res.method { + QueryMethodTypes::BETWEEN => self.accept_1(date, iter_res), + _ => self.accept_2(date, iter_res), + } + } + + + fn iter( + &mut self, + iter_res: &mut IterResult, + tzid: Option<String>, + ) -> Vec<DateTime<Tz>> { + let tzid: Tz = tzid.unwrap_or(String::from("UTC")).parse().unwrap_or(UTC); + + for date in &self.exdate { + let zoned_date = date.with_timezone(&tzid); + self.exdate_hash.insert(zoned_date.timestamp(), ()); + } + + match iter_res.method { + QueryMethodTypes::BETWEEN => { + self.eval_exdate( + &iter_res.args.after, + &iter_res.args.before, + ); + } + _ => (), + }; + + for date in &self.rdate.clone() { + let zoned_date = date.with_timezone(&tzid); + if !self.accept(zoned_date, iter_res){ + break; + } + } + + for rule in self.rrule.clone().iter_mut() { + iter_v2(iter_res, &mut rule.options, |date: DateTime<Tz>, iter_res: &mut IterResult| { + self.accept(date, iter_res) + }); + } + + let mut res = iter_res.get_value(); + res.sort(); + res + } +} + + +#[cfg(test)] +mod test_iter_set { + use super::*; + + fn ymd_hms( + year: i32, + month: u32, + day: u32, + hour: u32, + minute: u32, + second: u32, + ) -> DateTime<Utc> { + Utc.ymd(year, month, day).and_hms(hour, minute, second) + } + + fn ymd_hms_2( + year: i32, + month: u32, + day: u32, + hour: u32, + minute: u32, + second: u32, + ) -> DateTime<Tz> { + UTC.ymd(year, month, day).and_hms(hour, minute, second) + } + + fn test_recurring(actual_dates: Vec<DateTime<Tz>>, expected_dates: Vec<DateTime<Tz>>) { + assert_eq!( + actual_dates.len(), + expected_dates.len(), + "Expected number of returned dates to be equal to the expected" + ); + + println!("Acutal: {:?}", actual_dates); + for (actual, exptected) in actual_dates.into_iter().zip(expected_dates) { + assert_eq!(actual, exptected); + } + } + + #[test] + fn rrule_and_exrule() { + + let mut set = RRuleSet::new(); + + let mut options1 = ParsedOptions { + freq: Frequenzy::YEARLY, + count: Some(6), + bymonth: vec![], + dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), + byweekday: vec![1, 3], + byhour: vec![9], + bysetpos: vec![], + byweekno: vec![], + byminute: vec![0], + bysecond: vec![0], + byyearday: vec![], + bymonthday: vec![], + bynweekday: vec![], + bynmonthday: vec![], + until: None, + wkst: 0, + tzid: None, + interval: 1, + byeaster: None, + }; + let rrule = RRule::new(options1); + set.rrule(rrule); + let mut options2 = ParsedOptions { + freq: Frequenzy::YEARLY, + count: Some(3), + bymonth: vec![], + dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), + byweekday: vec![3], + byhour: vec![9], + bysetpos: vec![], + byweekno: vec![], + byminute: vec![0], + bysecond: vec![0], + byyearday: vec![], + bymonthday: vec![], + bynweekday: vec![], + bynmonthday: vec![], + until: None, + wkst: 0, + tzid: None, + interval: 1, + byeaster: None, + }; + let exrule = RRule::new(options2); + set.exrule(exrule); + + test_recurring( + set.all(), + vec![ + ymd_hms_2(1997, 9, 2, 9, 0, 0), + ymd_hms_2(1997, 9, 9, 9, 0, 0), + ymd_hms_2(1997, 9, 16, 9, 0, 0), + ], + ); + } + + #[test] + fn setdate_and_exdate() { + + let mut set = RRuleSet::new(); + + set.rdate(ymd_hms(1997, 9, 2, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 4, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 9, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 11, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 16, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 18, 9, 0, 0)); + + set.exdate(ymd_hms(1997, 9, 4, 9, 0, 0)); + set.exdate(ymd_hms(1997, 9, 11, 9, 0, 0)); + set.exdate(ymd_hms(1997, 9, 18, 9, 0, 0)); + + + test_recurring( + set.all(), + vec![ + ymd_hms_2(1997, 9, 2, 9, 0, 0), + ymd_hms_2(1997, 9, 9, 9, 0, 0), + ymd_hms_2(1997, 9, 16, 9, 0, 0), + ], + ); + } + + #[test] + fn setdate_and_exrule() { + + + + let mut set = RRuleSet::new(); + + set.rdate(ymd_hms(1997, 9, 2, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 4, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 9, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 11, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 16, 9, 0, 0)); + set.rdate(ymd_hms(1997, 9, 18, 9, 0, 0)); + + + let mut options = ParsedOptions { + freq: Frequenzy::YEARLY, + count: Some(3), + bymonth: vec![], + dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), + byweekday: vec![3], + byhour: vec![9], + bysetpos: vec![], + byweekno: vec![], + byminute: vec![0], + bysecond: vec![0], + byyearday: vec![], + bymonthday: vec![], + bynweekday: vec![], + bynmonthday: vec![], + until: None, + wkst: 0, + tzid: None, + interval: 1, + byeaster: None, + }; + let exrrule = RRule::new(options); + set.exrule(exrrule); + + test_recurring( + set.all(), + vec![ + ymd_hms_2(1997, 9, 2, 9, 0, 0), + ymd_hms_2(1997, 9, 9, 9, 0, 0), + ymd_hms_2(1997, 9, 16, 9, 0, 0), + ], + ); + } + + #[test] + fn rrule_and_exdate() { + + + let mut set = RRuleSet::new(); + + let mut options = ParsedOptions { + freq: Frequenzy::YEARLY, + count: Some(6), + bymonth: vec![], + dtstart: Utc.ymd(1997, 9, 2).and_hms(9, 0, 0), + byweekday: vec![1, 3], + byhour: vec![9], + bysetpos: vec![], + byweekno: vec![], + byminute: vec![0], + bysecond: vec![0], + byyearday: vec![], + bymonthday: vec![], + bynweekday: vec![], + bynmonthday: vec![], + until: None, + wkst: 0, + tzid: None, + interval: 1, + byeaster: None, + }; + let rrule = RRule::new(options); + set.rrule(rrule); + + set.exdate(ymd_hms(1997, 9, 2, 9, 0, 0)); + set.exdate(ymd_hms(1997, 9, 4, 9, 0, 0)); + set.exdate(ymd_hms(1997, 9, 9, 9, 0, 0)); + + + test_recurring( + set.all(), + vec![ + ymd_hms_2(1997, 9, 11, 9, 0, 0), + ymd_hms_2(1997, 9, 16, 9, 0, 0), + ymd_hms_2(1997, 9, 18, 9, 0, 0), + ], + ); + } } |