From c1ee71d98f298252a482a822616109abe8d9dc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Fri, 16 Sep 2022 17:51:09 +0300 Subject: [PATCH] recur_expansion.js: fix iterator with RDATE-only recurrence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/kewisch/ical.js/pull/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. --- lib/ical/recur_expansion.js | 17 ++++++++++++----- test/recur_expansion_test.js | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/ical/recur_expansion.js b/lib/ical/recur_expansion.js index 4f282e12..b3fc0d75 100644 --- a/lib/ical/recur_expansion.js +++ b/lib/ical/recur_expansion.js @@ -121,7 +121,7 @@ ICAL.RecurExpansion = (function() { * @type {Number} * @private */ - ruleDateInc: 0, + ruleDateInc: -1, /** * Current position in exDates array @@ -256,6 +256,14 @@ ICAL.RecurExpansion = (function() { // _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; @@ -294,7 +302,7 @@ ICAL.RecurExpansion = (function() { } //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. @@ -400,15 +408,14 @@ ICAL.RecurExpansion = (function() { this.ruleDateInc = 0; this.last = this.ruleDates[0].clone(); + this.ruleDate = this.ruleDates[0]; } else { this.ruleDateInc = ICAL.helpers.binsearchInsert( this.ruleDates, this.last, compareTime - ); + ) - 1; } - - this.ruleDate = this.ruleDates[this.ruleDateInc]; } if (component.hasProperty('rrule')) { diff --git a/test/recur_expansion_test.js b/test/recur_expansion_test.js index e3cfc356..9cb48d7a 100644 --- a/test/recur_expansion_test.js +++ b/test/recur_expansion_test.js @@ -61,6 +61,29 @@ suite('recur_expansion', function() { }, ".ruleIterators or .component must be given"); }); + test('only rdate without rrule', function() { + var component = primary.component.toJSON(); + component = new ICAL.Component(component); + component.removeAllProperties('rrule'); + + var subject = new ICAL.RecurExpansion({ + component, + dtstart: primary.startDate + }); + var expected = [ + new Date("2012-10-02T07:00:00.000Z"), + new Date("2012-11-05T08:00:00.000Z"), + new Date("2012-11-10T08:00:00.000Z"), + new Date("2012-11-30T08:00:00.000Z") + ], dates = [], next; + + while (next = subject.next() ) { + dates.push(next.toJSDate()); + } + + assert.deepEqual(dates, expected); + }); + test('default', function() { var dtstart = ICAL.Time.fromData({ year: 2012,