From 31a040cb115bfe31a4ab2485e1af06624d652861 Mon Sep 17 00:00:00 2001 From: cos Date: Thu, 1 Jul 2021 23:32:47 +0200 Subject: Bugfix for RRule{after, before} edge cases Corrects implementation to work according to documenated (and reasonable) behaviour. Also adds some test cases to cover these functions. --- src/rrule.rs | 4 +-- tests/rrule.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/rrule.rs b/src/rrule.rs index 1d95fe9..71f7e47 100644 --- a/src/rrule.rs +++ b/src/rrule.rs @@ -33,7 +33,7 @@ impl RRule { /// With inc == true, if dt itself is an recurrence, it will be returned. pub fn after(&self, dt: DateTime, inc: bool) -> Option> { self.into_iter() - .skip_while(|d| if inc { *d <= dt } else { *d < dt }) + .skip_while(|d| if inc { *d < dt } else { *d <= dt }) .next() } @@ -48,7 +48,7 @@ impl RRule { inc: bool, ) -> Vec> { self.into_iter() - .skip_while(|d| if inc { *d <= after } else { *d < after }) + .skip_while(|d| if inc { *d < after } else { *d <= after }) .take_while(|d| if inc { *d <= before } else { *d < before }) .collect() } diff --git a/tests/rrule.rs b/tests/rrule.rs index 64cac9c..3c96108 100644 --- a/tests/rrule.rs +++ b/tests/rrule.rs @@ -6937,4 +6937,94 @@ mod test { assert_eq!(o.weekday(), Sat); } } + + #[test] + fn test_before_inclusive_hit() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 2).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(Some(before), rrule.before(before, inc)); + } + + #[test] + fn test_before_inclusive_miss() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 3).and_hms(9, 0, 0); + let oracle = UTC.ymd(2012, 2, 2).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(Some(oracle), rrule.before(before, inc)); + } + + #[test] + fn test_after_inclusive_hit() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3".parse().unwrap(); + + let after = UTC.ymd(2012, 2, 2).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(Some(after), rrule.after(after, inc)); + } + + #[test] + fn test_after_inclusive_miss() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3".parse().unwrap(); + + let after = UTC.ymd(2012, 2, 2).and_hms(10, 0, 0); + let oracle = UTC.ymd(2012, 2, 3).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(Some(oracle), rrule.after(after, inc)); + } + + #[test] + fn test_between_inclusive_both_miss() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=5".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 2).and_hms(10, 0, 0); + let middle = UTC.ymd(2012, 2, 3).and_hms(9, 30, 0); + let after = UTC.ymd(2012, 2, 4).and_hms(9, 0, 0); + let inc = true; + + assert_eq!(vec![middle], rrule.between(before, after, inc)); + } + + #[test] + fn test_between_inclusive_lower_miss() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=5".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 2).and_hms(10, 0, 0); + let middle = UTC.ymd(2012, 2, 3).and_hms(9, 30, 0); + let after = UTC.ymd(2012, 2, 4).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(vec![middle, after], rrule.between(before, after, inc)); + } + + #[test] + fn test_between_inclusive_upper_miss() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=5".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 2).and_hms(9, 30, 0); + let middle = UTC.ymd(2012, 2, 3).and_hms(9, 30, 0); + let after = UTC.ymd(2012, 2, 4).and_hms(9, 0, 0); + let inc = true; + + assert_eq!(vec![before, middle], rrule.between(before, after, inc)); + } + + #[test] + fn test_between_inclusive_both_hit() { + let rrule: RRule = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=5".parse().unwrap(); + + let before = UTC.ymd(2012, 2, 2).and_hms(9, 30, 0); + let middle = UTC.ymd(2012, 2, 3).and_hms(9, 30, 0); + let after = UTC.ymd(2012, 2, 4).and_hms(9, 30, 0); + let inc = true; + + assert_eq!(vec![before, middle, after], rrule.between(before, after, inc)); + } } -- cgit v1.2.3