summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/datetime.rs16
-rw-r--r--src/iter/iterinfo.rs (renamed from src/iterinfo.rs)4
-rw-r--r--src/iter/mod.rs (renamed from src/iter.rs)213
-rw-r--r--src/iter/monthinfo.rs (renamed from src/monthinfo.rs)2
-rw-r--r--src/iter/poslist.rs (renamed from src/poslist.rs)11
-rw-r--r--src/iter/yearinfo.rs (renamed from src/yearinfo.rs)6
-rw-r--r--src/iter_set.rs138
-rw-r--r--src/lib.rs7
-rw-r--r--src/rrule.rs12
-rw-r--r--src/rrule_iter.rs93
-rw-r--r--src/rruleset.rs170
-rw-r--r--src/rruleset_iter.rs161
12 files changed, 424 insertions, 409 deletions
diff --git a/src/datetime.rs b/src/datetime.rs
index 871ccfa..2e06d24 100644
--- a/src/datetime.rs
+++ b/src/datetime.rs
@@ -1,3 +1,19 @@
+use chrono::prelude::*;
+use chrono_tz::Tz;
+
+
+pub type DTime = DateTime<Tz>;
+
+pub fn from_ordinal(ordinal: isize) -> DateTime<Utc> {
+ let timestamp = ordinal * 24 * 60 * 60;
+ let naive = NaiveDateTime::from_timestamp(timestamp as i64, 0);
+ DateTime::from_utc(naive, Utc)
+}
+
+pub fn to_ordinal(date: &DateTime<Utc>) -> isize {
+ (date.timestamp() / 60 / 60 / 24) as isize
+}
+
#[derive(Debug)]
pub struct Time {
pub hour: usize,
diff --git a/src/iterinfo.rs b/src/iter/iterinfo.rs
index 6f3044e..09090f1 100644
--- a/src/iterinfo.rs
+++ b/src/iter/iterinfo.rs
@@ -1,8 +1,8 @@
use crate::datetime::*;
use crate::easter::*;
-use crate::monthinfo::*;
+use crate::iter::monthinfo::{MonthInfo, rebuild_month};
+use crate::iter::yearinfo::{YearInfo, rebuild_year};
use crate::options::*;
-use crate::yearinfo::*;
use chrono::prelude::*;
pub struct IterInfo<'a> {
diff --git a/src/iter.rs b/src/iter/mod.rs
index 6922ed4..d426a98 100644
--- a/src/iter.rs
+++ b/src/iter/mod.rs
@@ -1,101 +1,152 @@
-use crate::datetime::*;
-use crate::iter_set::IterResult;
-use crate::iterinfo::*;
+mod yearinfo;
+use yearinfo::get_weekday_val;
+
+mod monthinfo;
+
+mod iterinfo;
+use iterinfo::IterInfo;
+
+mod poslist;
+use poslist::build_poslist;
+
use crate::options::*;
-use crate::yearinfo::*;
+use crate::datetime::{Time, from_ordinal};
+use chrono::offset::TimeZone;
use chrono::prelude::*;
-use chrono::Duration;
-use chrono_tz::Tz;
-
-pub enum QueryMethodTypes {
- All,
- Between,
- Before,
- After,
-}
+use chrono::{DateTime, Duration};
+use chrono_tz::*;
-pub struct IterArgs {
- pub inc: bool,
- pub before: Option<DateTime<Tz>>,
- pub after: Option<DateTime<Tz>>,
- pub dt: Option<DateTime<Tz>>,
+pub trait IterResult {
+ fn accept(&mut self, date: DateTime<Tz>) -> bool;
+ fn get_value(&self) -> Vec<DateTime<Tz>>;
}
-pub struct RRuleIterRes {
- pub method: QueryMethodTypes,
- pub args: IterArgs,
- pub min_date: Option<DateTime<Tz>>,
- pub max_date: Option<DateTime<Tz>>,
- pub result: Vec<DateTime<Tz>>,
- pub total: usize,
-}
+pub fn iter<T: IterResult>(
+ iter_result: &mut T,
+ options: &mut ParsedOptions,
+) -> Vec<DateTime<Tz>> {
-impl RRuleIterRes {
- pub fn new(method: QueryMethodTypes, args: IterArgs) -> Self {
- let (max_date, min_date) = match method {
- QueryMethodTypes::Between if args.inc => {
- (Some(args.before.unwrap()), Some(args.after.unwrap()))
- }
- QueryMethodTypes::Between => (
- Some(args.before.unwrap() - Duration::milliseconds(1)),
- Some(args.after.unwrap() + Duration::milliseconds(1)),
- ),
- QueryMethodTypes::Before if args.inc => (Some(args.dt.unwrap()), None),
- QueryMethodTypes::Before => (Some(args.dt.unwrap() - Duration::milliseconds(1)), None),
- QueryMethodTypes::After if args.inc => (None, Some(args.dt.unwrap())),
- QueryMethodTypes::After => (None, Some(args.dt.unwrap() + Duration::milliseconds(1))),
- _ => (None, None),
- };
-
- Self {
- method,
- args,
- min_date,
- max_date,
- total: 0,
- result: vec![],
- }
+ if (options.count.is_some() && options.count.unwrap() == 0) || options.interval == 0 {
+ return iter_result.get_value();
}
- pub fn add(&mut self, date: DateTime<Tz>) -> bool {
- self.result.push(date);
- true
- }
-}
+ let mut counter_date = options.dtstart;
+ let mut ii = IterInfo::new(options);
+ ii.rebuild(counter_date.year() as isize, counter_date.month() as usize);
+
+ let mut timeset = make_timeset(&ii, &counter_date, options);
+ let mut count = match options.count {
+ Some(count) => count,
+ _ => 0,
+ };
+
+ loop {
+ let (dayset, start, end) = ii.getdayset(
+ &options.freq,
+ counter_date.year() as isize,
+ counter_date.month() as usize,
+ counter_date.day() as usize,
+ );
+
+ let mut dayset = dayset
+ .into_iter()
+ .map(|s| Some(s as isize))
+ .collect::<Vec<Option<isize>>>();
+
+ let filtered = remove_filtered_days(&mut dayset, start, end, &ii, options);
+
+ if not_empty(&options.bysetpos) {
+ let poslist = build_poslist(&options.bysetpos, &timeset, start, end, &ii, &dayset, &options.tzid);
+
+ for j in 0..poslist.len() {
+ let res = poslist[j];
+ if options.until.is_some() && res > options.until.unwrap() {
+ return iter_result.get_value();
+ }
-impl IterResult for RRuleIterRes {
- fn accept(&mut self, date: DateTime<Tz>) -> bool {
- self.total += 1;
- let too_early = self.min_date.is_some() && date < self.min_date.unwrap();
- let too_late = self.max_date.is_some() && date > self.max_date.unwrap();
-
- match self.method {
- QueryMethodTypes::Between if too_early => true,
- QueryMethodTypes::Between if too_late => false,
- QueryMethodTypes::Before if too_late => false,
- QueryMethodTypes::After if too_early => true,
- QueryMethodTypes::After => {
- self.add(date);
- false
+ if res >= options.dtstart {
+ //let rezoned_date = rezone_if_needed(&res, &options);
+ // let rezoned_date = UTC.timestamp(res.timestamp(), 0);
+
+ if !iter_result.accept(res) {
+ return iter_result.get_value();
+ }
+
+ if count > 0 {
+ count -= 1;
+ if count == 0 {
+ return iter_result.get_value();
+ }
+ }
+ }
}
- _ => self.add(date),
- }
- }
+ } else {
+ for j in start..end {
+ let current_day = dayset[j];
+ if current_day.is_none() {
+ continue;
+ }
- // before and after returns only one date whereas all and between an array
- fn get_value(&self) -> Vec<DateTime<Tz>> {
- match self.method {
- QueryMethodTypes::Between | QueryMethodTypes::All => self.result.clone(),
- _ => {
- if self.result.is_empty() {
- return vec![];
+ let current_day = current_day.unwrap();
+ let date = from_ordinal(ii.yearordinal().unwrap() + current_day);
+ for k in 0..timeset.len() {
+ let res = options.tzid.ymd(date.year(), date.month(), date.day()).and_hms(
+ timeset[k].hour as u32,
+ timeset[k].minute as u32,
+ timeset[k].second as u32,
+ );
+ if options.until.is_some() && res > options.until.unwrap() {
+ return iter_result.get_value();
+ }
+ if res >= options.dtstart {
+ //let rezoned_date = rezone_if_needed(&res, &options);
+ // let rezoned_date = UTC.timestamp(res.timestamp(), 0);
+ // let rezoned_date = tzid.from_utc_datetime(&res.naive_utc());
+ // let rezoned_date = res.with_timezone(&options.tzid);
+
+ if !iter_result.accept(res) {
+ return iter_result.get_value();
+ }
+ if count > 0 {
+ count -= 1;
+ if count == 0 {
+ return iter_result.get_value();
+ }
+ }
+ }
}
- vec![self.result[self.result.len() - 1].clone()]
}
}
+
+ if options.interval == 0 {
+ return iter_result.get_value();
+ }
+
+ // Handle frequency and interval
+ counter_date = increment_counter_date(counter_date, options, filtered);
+
+ if counter_date.year() > 2200 {
+ return iter_result.get_value();
+ }
+
+ if options.freq == Frequenzy::Hourly
+ || options.freq == Frequenzy::Minutely
+ || options.freq == Frequenzy::Secondly
+ {
+ timeset = ii.gettimeset(
+ &options.freq,
+ counter_date.hour() as usize,
+ counter_date.minute() as usize,
+ counter_date.second() as usize,
+ 0,
+ );
+ }
+
+ ii.rebuild(counter_date.year() as isize, counter_date.month() as usize);
}
}
+
pub fn increment_counter_date(
counter_date: DateTime<Utc>,
options: &ParsedOptions,
diff --git a/src/monthinfo.rs b/src/iter/monthinfo.rs
index c0af98a..c89bfc3 100644
--- a/src/monthinfo.rs
+++ b/src/iter/monthinfo.rs
@@ -1,5 +1,5 @@
use crate::options::*;
-use crate::yearinfo::*;
+use crate::iter::yearinfo::pymod;
#[derive(Debug)]
pub struct MonthInfo {
diff --git a/src/poslist.rs b/src/iter/poslist.rs
index 94ad6e9..fa9fbd8 100644
--- a/src/poslist.rs
+++ b/src/iter/poslist.rs
@@ -1,15 +1,10 @@
use crate::datetime::*;
-use crate::iterinfo::*;
-use crate::yearinfo::*;
+use crate::iter::iterinfo::IterInfo;
+use crate::iter::yearinfo::pymod;
+use crate::datetime::from_ordinal;
use chrono::prelude::*;
use chrono_tz::Tz;
-pub fn from_ordinal(ordinal: isize) -> DateTime<Utc> {
- let timestamp = ordinal * 24 * 60 * 60;
- let naive = NaiveDateTime::from_timestamp(timestamp as i64, 0);
- DateTime::from_utc(naive, Utc)
-}
-
pub fn build_poslist(
bysetpost: &Vec<isize>,
timeset: &Vec<Time>,
diff --git a/src/yearinfo.rs b/src/iter/yearinfo.rs
index 9bc0906..8a944f7 100644
--- a/src/yearinfo.rs
+++ b/src/iter/yearinfo.rs
@@ -1,7 +1,7 @@
use crate::masks::MASKS;
use crate::options::*;
use chrono::prelude::*;
-use chrono::DateTime;
+use crate::datetime::to_ordinal;
#[derive(Debug)]
@@ -29,10 +29,6 @@ fn get_year_len(year: i32) -> usize {
365
}
-pub fn to_ordinal(date: &DateTime<Utc>) -> isize {
- (date.timestamp() / 60 / 60 / 24) as isize
-}
-
pub fn get_weekday_val(wk: &Weekday) -> usize {
match wk {
Weekday::Mon => 0,
diff --git a/src/iter_set.rs b/src/iter_set.rs
deleted file mode 100644
index 60eced6..0000000
--- a/src/iter_set.rs
+++ /dev/null
@@ -1,138 +0,0 @@
-use crate::iter::*;
-use crate::iterinfo::*;
-use crate::options::*;
-use crate::poslist::*;
-use chrono::offset::TimeZone;
-use chrono::prelude::*;
-use chrono::DateTime;
-use chrono_tz::*;
-
-pub trait IterResult {
- fn accept(&mut self, date: DateTime<Tz>) -> bool;
- fn get_value(&self) -> Vec<DateTime<Tz>>;
-}
-
-pub fn iter_v2<T: IterResult>(
- iter_result: &mut T,
- options: &mut ParsedOptions,
-) -> Vec<DateTime<Tz>> {
-
- if (options.count.is_some() && options.count.unwrap() == 0) || options.interval == 0 {
- return iter_result.get_value();
- }
-
- let mut counter_date = options.dtstart;
- let mut ii = IterInfo::new(options);
- ii.rebuild(counter_date.year() as isize, counter_date.month() as usize);
-
- let mut timeset = make_timeset(&ii, &counter_date, options);
- let mut count = match options.count {
- Some(count) => count,
- _ => 0,
- };
-
- loop {
- let (dayset, start, end) = ii.getdayset(
- &options.freq,
- counter_date.year() as isize,
- counter_date.month() as usize,
- counter_date.day() as usize,
- );
-
- let mut dayset = dayset
- .into_iter()
- .map(|s| Some(s as isize))
- .collect::<Vec<Option<isize>>>();
-
- let filtered = remove_filtered_days(&mut dayset, start, end, &ii, options);
-
- if not_empty(&options.bysetpos) {
- let poslist = build_poslist(&options.bysetpos, &timeset, start, end, &ii, &dayset, &options.tzid);
-
- for j in 0..poslist.len() {
- let res = poslist[j];
- if options.until.is_some() && res > options.until.unwrap() {
- return iter_result.get_value();
- }
-
- if res >= options.dtstart {
- //let rezoned_date = rezone_if_needed(&res, &options);
- // let rezoned_date = UTC.timestamp(res.timestamp(), 0);
-
- if !iter_result.accept(res) {
- return iter_result.get_value();
- }
-
- if count > 0 {
- count -= 1;
- if count == 0 {
- return iter_result.get_value();
- }
- }
- }
- }
- } else {
- for j in start..end {
- let current_day = dayset[j];
- if current_day.is_none() {
- continue;
- }
-
- let current_day = current_day.unwrap();
- let date = from_ordinal(ii.yearordinal().unwrap() + current_day);
- for k in 0..timeset.len() {
- let res = options.tzid.ymd(date.year(), date.month(), date.day()).and_hms(
- timeset[k].hour as u32,
- timeset[k].minute as u32,
- timeset[k].second as u32,
- );
- if options.until.is_some() && res > options.until.unwrap() {
- return iter_result.get_value();
- }
- if res >= options.dtstart {
- //let rezoned_date = rezone_if_needed(&res, &options);
- // let rezoned_date = UTC.timestamp(res.timestamp(), 0);
- // let rezoned_date = tzid.from_utc_datetime(&res.naive_utc());
- // let rezoned_date = res.with_timezone(&options.tzid);
-
- if !iter_result.accept(res) {
- return iter_result.get_value();
- }
- if count > 0 {
- count -= 1;
- if count == 0 {
- return iter_result.get_value();
- }
- }
- }
- }
- }
- }
-
- if options.interval == 0 {
- return iter_result.get_value();
- }
-
- // Handle frequency and interval
- counter_date = increment_counter_date(counter_date, options, filtered);
-
- if counter_date.year() > 2200 {
- return iter_result.get_value();
- }
-
- if options.freq == Frequenzy::Hourly
- || options.freq == Frequenzy::Minutely
- || options.freq == Frequenzy::Secondly
- {
- timeset = ii.gettimeset(
- &options.freq,
- counter_date.hour() as usize,
- counter_date.minute() as usize,
- counter_date.second() as usize,
- 0,
- );
- }
-
- ii.rebuild(counter_date.year() as isize, counter_date.month() as usize);
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 94f4a3e..17d9ce1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,17 +40,14 @@ extern crate regex;
mod datetime;
mod easter;
mod iter;
-mod iter_set;
-mod iterinfo;
mod masks;
-mod monthinfo;
-mod poslist;
mod parse_options;
-mod yearinfo;
mod options;
mod rrulestr;
mod rrule;
+mod rrule_iter;
mod rruleset;
+mod rruleset_iter;
pub use crate::rrule::RRule;
pub use crate::rruleset::RRuleSet;
diff --git a/src/rrule.rs b/src/rrule.rs
index 6904d6c..d7aa198 100644
--- a/src/rrule.rs
+++ b/src/rrule.rs
@@ -1,5 +1,5 @@
-use crate::iter::*;
-use crate::iter_set::iter_v2;
+use crate::iter::iter;
+use crate::rrule_iter::*;
use crate::options::*;
use chrono::prelude::*;
use chrono_tz::Tz;
@@ -25,7 +25,7 @@ impl RRule {
};
let mut iter_res = RRuleIterRes::new(QueryMethodTypes::All, iter_args);
- let res = iter_v2(&mut iter_res, &mut self.options);
+ let res = iter(&mut iter_res, &mut self.options);
res
}
@@ -38,7 +38,7 @@ impl RRule {
};
let mut iter_res = RRuleIterRes::new(QueryMethodTypes::Before, iter_args);
- iter_v2(&mut iter_res, &mut self.options)
+ iter(&mut iter_res, &mut self.options)
}
pub fn after(&mut self, dt: DateTime<Tz>, inc: bool) -> Vec<DateTime<Tz>> {
@@ -50,7 +50,7 @@ impl RRule {
};
let mut iter_res = RRuleIterRes::new(QueryMethodTypes::After, iter_args);
- iter_v2(&mut iter_res, &mut self.options)
+ iter(&mut iter_res, &mut self.options)
}
pub fn between(
@@ -67,6 +67,6 @@ impl RRule {
};
let mut iter_res = RRuleIterRes::new(QueryMethodTypes::Between, iter_args);
- iter_v2(&mut iter_res, &mut self.options)
+ iter(&mut iter_res, &mut self.options)
}
}
diff --git a/src/rrule_iter.rs b/src/rrule_iter.rs
new file mode 100644
index 0000000..7751476
--- /dev/null
+++ b/src/rrule_iter.rs
@@ -0,0 +1,93 @@
+use crate::iter::IterResult;
+use chrono::prelude::*;
+use chrono::Duration;
+use chrono_tz::Tz;
+
+pub enum QueryMethodTypes {
+ All,
+ Between,
+ Before,
+ After,
+}
+
+pub struct IterArgs {
+ pub inc: bool,
+ pub before: Option<DateTime<Tz>>,
+ pub after: Option<DateTime<Tz>>,
+ pub dt: Option<DateTime<Tz>>,
+}
+
+pub struct RRuleIterRes {
+ pub method: QueryMethodTypes,
+ pub args: IterArgs,
+ pub min_date: Option<DateTime<Tz>>,
+ pub max_date: Option<DateTime<Tz>>,
+ pub result: Vec<DateTime<Tz>>,
+ pub total: usize,
+}
+
+impl RRuleIterRes {
+ pub fn new(method: QueryMethodTypes, args: IterArgs) -> Self {
+ let (max_date, min_date) = match method {
+ QueryMethodTypes::Between if args.inc => {
+ (Some(args.before.unwrap()), Some(args.after.unwrap()))
+ }
+ QueryMethodTypes::Between => (
+ Some(args.before.unwrap() - Duration::milliseconds(1)),
+ Some(args.after.unwrap() + Duration::milliseconds(1)),
+ ),
+ QueryMethodTypes::Before if args.inc => (Some(args.dt.unwrap()), None),
+ QueryMethodTypes::Before => (Some(args.dt.unwrap() - Duration::milliseconds(1)), None),
+ QueryMethodTypes::After if args.inc => (None, Some(args.dt.unwrap())),
+ QueryMethodTypes::After => (None, Some(args.dt.unwrap() + Duration::milliseconds(1))),
+ _ => (None, None),
+ };
+
+ Self {
+ method,
+ args,
+ min_date,
+ max_date,
+ total: 0,
+ result: vec![],
+ }
+ }
+
+ pub fn add(&mut self, date: DateTime<Tz>) -> bool {
+ self.result.push(date);
+ true
+ }
+}
+
+impl IterResult for RRuleIterRes {
+ fn accept(&mut self, date: DateTime<Tz>) -> bool {
+ self.total += 1;
+ let too_early = self.min_date.is_some() && date < self.min_date.unwrap();
+ let too_late = self.max_date.is_some() && date > self.max_date.unwrap();
+
+ match self.method {
+ QueryMethodTypes::Between if too_early => true,
+ QueryMethodTypes::Between if too_late => false,
+ QueryMethodTypes::Before if too_late => false,
+ QueryMethodTypes::After if too_early => true,
+ QueryMethodTypes::After => {
+ self.add(date);
+ false
+ }
+ _ => self.add(date),
+ }
+ }
+
+ // before and after returns only one date whereas all and between an array
+ fn get_value(&self) -> Vec<DateTime<Tz>> {
+ match self.method {
+ QueryMethodTypes::Between | QueryMethodTypes::All => self.result.clone(),
+ _ => {
+ if self.result.is_empty() {
+ return vec![];
+ }
+ vec![self.result[self.result.len() - 1].clone()]
+ }
+ }
+ }
+}
diff --git a/src/rruleset.rs b/src/rruleset.rs
index f572404..dc9d589 100644
--- a/src/rruleset.rs
+++ b/src/rruleset.rs
@@ -1,174 +1,18 @@
-use crate::iter::*;
-use crate::iter_set::{iter_v2, IterResult};
-use crate::rrule::*;
+use crate::iter::{iter, IterResult};
use chrono::prelude::*;
use chrono_tz::{Tz, UTC};
-use std::collections::HashMap;
+use crate::rrule::RRule;
+use crate::rruleset_iter::RRuleSetIter;
#[derive(Debug)]
pub struct RRuleSet {
- rrule: Vec<RRule>,
- rdate: Vec<DateTime<Utc>>,
- exrule: Vec<RRule>,
- exdate: Vec<DateTime<Utc>>,
+ pub rrule: Vec<RRule>,
+ pub rdate: Vec<DateTime<Utc>>,
+ pub exrule: Vec<RRule>,
+ pub exdate: Vec<DateTime<Utc>>,
pub dtstart: Option<DateTime<Utc>>,
}
-struct RRuleSetIter<'a> {
- exdate_hash: HashMap<i64, ()>,
- iter_res: RRuleIterRes,
- rrule_set: &'a mut RRuleSet,
-}
-
-impl<'a> RRuleSetIter<'a> {
- pub fn all(rrule_set: &'a mut RRuleSet) -> Self {
- let iter_args = IterArgs {
- inc: true,
- before: None,
- after: None,
- dt: None,
- };
- let iter_res = RRuleIterRes::new(QueryMethodTypes::All, iter_args);
-
- Self {
- exdate_hash: HashMap::new(),
- iter_res,
- rrule_set,
- }
- }
-
- pub fn before(rrule_set: &'a mut RRuleSet, dt: DateTime<Tz>, inc: bool) -> Self {
- let iter_args = IterArgs {
- inc,
- before: None,
- after: None,
- dt: Some(dt),
- };
- let iter_res = RRuleIterRes::new(QueryMethodTypes::Before, iter_args);
-
- Self {
- exdate_hash: HashMap::new(),
- iter_res,
- rrule_set,
- }
- }
-
- pub fn after(rrule_set: &'a mut RRuleSet, dt: DateTime<Tz>, inc: bool) -> Self {
- let iter_args = IterArgs {
- inc,
- before: None,
- after: None,
- dt: Some(dt),
- };
- let iter_res = RRuleIterRes::new(QueryMethodTypes::After, iter_args);
-
- Self {
- exdate_hash: HashMap::new(),
- iter_res,
- rrule_set,
- }
- }
-
- pub fn between(
- rrule_set: &'a mut RRuleSet,
- after: DateTime<Tz>,
- before: DateTime<Tz>,
- inc: bool,
- ) -> Self {
- let iter_args = IterArgs {
- inc,
- before: Some(before),
- after: Some(after),
- dt: None,
- };
- let iter_res = RRuleIterRes::new(QueryMethodTypes::Between, iter_args);
-
- Self {
- exdate_hash: HashMap::new(),
- iter_res,
- rrule_set,
- }
- }
-
- pub fn eval_exdate(&mut self, after: &DateTime<Tz>, before: &DateTime<Tz>) {
- for rrule in self.rrule_set.exrule.iter_mut() {
- for date in rrule.between(after.clone(), before.clone(), true) {
- self.exdate_hash.insert(date.timestamp(), ());
- }
- }
- }
-
- fn accept_when_unknown_bounds(&mut self, date: DateTime<Tz>) -> bool {
- let dt = date.timestamp();
- if !self.exdate_hash.contains_key(&dt) {
- self.eval_exdate(&date.timezone().timestamp(dt - 1, 0), &date.timezone().timestamp(dt + 1, 0));
- if !self.exdate_hash.contains_key(&dt) {
- self.exdate_hash.insert(dt, ());
- return self.iter_res.accept(date.clone());
- }
- }
-
- true
- }
-
- fn accept_when_known_bounds(&mut self, date: DateTime<Tz>) -> bool {
- let dt = date.timestamp();
- if !self.exdate_hash.contains_key(&dt) {
- self.exdate_hash.insert(dt, ());
- return self.iter_res.accept(date.clone());
- }
-
- true
- }
-
- pub fn iter(&mut self, tzid: Option<String>) -> Vec<DateTime<Tz>> {
- let tzid: Tz = tzid.unwrap_or(String::from("UTC")).parse().unwrap_or(UTC);
-
- for date in &self.rrule_set.exdate {
- let zoned_date = date.with_timezone(&tzid);
- self.exdate_hash.insert(zoned_date.timestamp(), ());
- }
-
- match &self.iter_res.method {
- QueryMethodTypes::Between => {
- self.eval_exdate(
- &self.iter_res.args.after.unwrap().clone(),
- &self.iter_res.args.before.unwrap().clone(),
- );
- }
- _ => (),
- };
-
- for date in &self.rrule_set.rdate.clone() {
- let zoned_date = date.with_timezone(&tzid);
- if !self.accept(zoned_date) {
- break;
- }
- }
-
- for rule in self.rrule_set.rrule.clone().iter_mut() {
- iter_v2(self, &mut rule.options);
- }
-
- let mut res = self.iter_res.get_value();
- res.sort();
- res
- }
-}
-
-impl<'a> IterResult for RRuleSetIter<'a> {
- fn accept(&mut self, date: DateTime<Tz>) -> bool {
- match &self.iter_res.method {
- QueryMethodTypes::Between => self.accept_when_known_bounds(date),
- _ => self.accept_when_unknown_bounds(date),
- }
- }
-
- fn get_value(&self) -> Vec<DateTime<Tz>> {
- self.iter_res.get_value()
- }
-}
-
impl RRuleSet {
pub fn new() -> Self {
Self {
diff --git a/src/rruleset_iter.rs b/src/rruleset_iter.rs
new file mode 100644
index 0000000..ba8e305
--- /dev/null
+++ b/src/rruleset_iter.rs
@@ -0,0 +1,161 @@
+use crate::iter::{iter, IterResult};
+use chrono::prelude::*;
+use crate::rruleset::RRuleSet;
+use crate::rrule_iter::*;
+use std::collections::HashMap;
+use chrono_tz::{Tz, UTC};
+
+pub struct RRuleSetIter<'a> {
+ exdate_hash: HashMap<i64, ()>,
+ iter_res: RRuleIterRes,
+ rrule_set: &'a mut RRuleSet,
+}
+
+impl<'a> RRuleSetIter<'a> {
+ pub fn all(rrule_set: &'a mut RRuleSet) -> Self {
+ let iter_args = IterArgs {
+ inc: true,
+ before: None,
+ after: None,
+ dt: None,
+ };
+ let iter_res = RRuleIterRes::new(QueryMethodTypes::All, iter_args);
+
+ Self {
+ exdate_hash: HashMap::new(),
+ iter_res,
+ rrule_set,
+ }
+ }
+
+ pub fn before(rrule_set: &'a mut RRuleSet, dt: DateTime<Tz>, inc: bool) -> Self {
+ let iter_args = IterArgs {
+ inc,
+ before: None,
+ after: None,
+ dt: Some(dt),
+ };
+ let iter_res = RRuleIterRes::new(QueryMethodTypes::Before, iter_args);
+
+ Self {
+ exdate_hash: HashMap::new(),
+ iter_res,
+ rrule_set,
+ }
+ }
+
+ pub fn after(rrule_set: &'a mut RRuleSet, dt: DateTime<Tz>, inc: bool) -> Self {
+ let iter_args = IterArgs {
+ inc,
+ before: None,
+ after: None,
+ dt: Some(dt),
+ };
+ let iter_res = RRuleIterRes::new(QueryMethodTypes::After, iter_args);
+
+ Self {
+ exdate_hash: HashMap::new(),
+ iter_res,
+ rrule_set,
+ }
+ }
+
+ pub fn between(
+ rrule_set: &'a mut RRuleSet,
+ after: DateTime<Tz>,
+ before: DateTime<Tz>,
+ inc: bool,
+ ) -> Self {
+ let iter_args = IterArgs {
+ inc,
+ before: Some(before),
+ after: Some(after),
+ dt: None,
+ };
+ let iter_res = RRuleIterRes::new(QueryMethodTypes::Between, iter_args);
+
+ Self {
+ exdate_hash: HashMap::new(),
+ iter_res,
+ rrule_set,
+ }
+ }
+
+ pub fn eval_exdate(&mut self, after: &DateTime<Tz>, before: &DateTime<Tz>) {
+ for rrule in self.rrule_set.exrule.iter_mut() {
+ for date in rrule.between(after.clone(), before.clone(), true) {
+ self.exdate_hash.insert(date.timestamp(), ());
+ }
+ }
+ }
+
+ fn accept_when_unknown_bounds(&mut self, date: DateTime<Tz>) -> bool {
+ let dt = date.timestamp();
+ if !self.exdate_hash.contains_key(&dt) {
+ self.eval_exdate(&date.timezone().timestamp(dt - 1, 0), &date.timezone().timestamp(dt + 1, 0));
+ if !self.exdate_hash.contains_key(&dt) {
+ self.exdate_hash.insert(dt, ());
+ return self.iter_res.accept(date.clone());
+ }
+ }
+
+ true
+ }
+
+ fn accept_when_known_bounds(&mut self, date: DateTime<Tz>) -> bool {
+ let dt = date.timestamp();
+ if !self.exdate_hash.contains_key(&dt) {
+ self.exdate_hash.insert(dt, ());
+ return self.iter_res.accept(date.clone());
+ }
+
+ true
+ }
+
+ pub fn iter(&mut self, tzid: Option<String>) -> Vec<DateTime<Tz>> {
+ let tzid: Tz = tzid.unwrap_or(String::from("UTC")).parse().unwrap_or(UTC);
+
+ for date in &self.rrule_set.exdate {
+ let zoned_date = date.with_timezone(&tzid);
+ self.exdate_hash.insert(zoned_date.timestamp(), ());
+ }
+
+ match &self.iter_res.method {
+ QueryMethodTypes::Between => {
+ self.eval_exdate(
+ &self.iter_res.args.after.unwrap().clone(),
+ &self.iter_res.args.before.unwrap().clone(),
+ );
+ }
+ _ => (),
+ };
+
+ for date in &self.rrule_set.rdate.clone() {
+ let zoned_date = date.with_timezone(&tzid);
+ if !self.accept(zoned_date) {
+ break;
+ }
+ }
+
+ for rule in self.rrule_set.rrule.clone().iter_mut() {
+ iter(self, &mut rule.options);
+ }
+
+ let mut res = self.iter_res.get_value();
+ res.sort();
+ res
+ }
+}
+
+impl<'a> IterResult for RRuleSetIter<'a> {
+ fn accept(&mut self, date: DateTime<Tz>) -> bool {
+ match &self.iter_res.method {
+ QueryMethodTypes::Between => self.accept_when_known_bounds(date),
+ _ => self.accept_when_unknown_bounds(date),
+ }
+ }
+
+ fn get_value(&self) -> Vec<DateTime<Tz>> {
+ self.iter_res.get_value()
+ }
+}