Skip to content

Commit

Permalink
recur_expansion.js: fix iterator with RDATE-only recurrence
Browse files Browse the repository at this point in the history
kewisch#534

When iterating with
  e is an event-component
  if (e.isRecurring() {
     let i = e.iterator();
     while (n = i.next()) {
       o = g.getOccurrenceDetails(obj)
       …
     }
  }

on the first iteration the DTSTART instance shall be returned.  It is returned,
when there is RRULE.  In the lack of this change, on the first iteration, when
RDATE is present without RRULE, the first RDATE instance is returned.
  • Loading branch information
dilyanpalauzov committed Apr 13, 2024
1 parent 027cd6b commit 800344c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 5 deletions.
17 changes: 12 additions & 5 deletions lib/ical/recur_expansion.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class RecurExpansion {
* @type {Number}
* @private
*/
ruleDateInc = 0;
ruleDateInc = -1;

/**
* Current position in exDates array
Expand Down Expand Up @@ -240,6 +240,14 @@ class RecurExpansion {
// _after_ we choose a value this should be
// the only spot where we need to worry about the
// end of events.
if (this.ruleDateInc == -1) {
this._nextRuleDay();
if (!iter) {
// on the first iteration return DTSTART
return this.last;
}
}

if (!next && !iter) {
// there are no more iterators or rdates
this.complete = true;
Expand Down Expand Up @@ -278,7 +286,7 @@ class RecurExpansion {
}

//XXX: The spec states that after we resolve the final
// list of dates we execute exdate this seems somewhat counter
// list of dates we execute exdate. This seems somewhat counter
// intuitive to what I have seen most servers do so for now
// I exclude based on the original date not the one that may
// have been modified by the exception.
Expand Down Expand Up @@ -379,15 +387,14 @@ class RecurExpansion {

this.ruleDateInc = 0;
this.last = this.ruleDates[0].clone();
this.ruleDate = this.ruleDates[0];
} else {
this.ruleDateInc = binsearchInsert(
this.ruleDates,
this.last,
(a, b) => a.compare(b)
);
) - 1;
}

this.ruleDate = this.ruleDates[this.ruleDateInc];
}

if (component.hasProperty('rrule')) {
Expand Down
23 changes: 23 additions & 0 deletions test/recur_expansion_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ suite('recur_expansion', function() {
}, ".ruleIterators or .component must be given");
});

test('only rdate without rrule', function() {
let component = primary.component.toJSON();
component = new ICAL.Component(component);
component.removeAllProperties('rrule');

const subj = new ICAL.RecurExpansion({
component,
dtstart: primary.startDate
});
let expected = [
new Date(2012, 9, 2, 10),
new Date(2012, 10, 5, 10),
new Date(2012, 10, 10, 10),
new Date(2012, 10, 30, 10)
], dates = [], next;

while ((next = subj.next())) {
dates.push(next.toJSDate());
}

assert.deepEqual(dates, expected);
});

test('default', function() {
let dtstart = ICAL.Time.fromData({
year: 2012,
Expand Down

0 comments on commit 800344c

Please sign in to comment.