rrule icon indicating copy to clipboard operation
rrule copied to clipboard

`RRuleSet`s don't handle `DTSTART` correctly

Open topherauyeung opened this issue 4 years ago • 6 comments

Reporting an issue

When using rrulestr to parse a set of rules, creating an RRuleSet and then enumerating its instances (or converting it to a string) is not working as expected.

The following code:

rrule.rrulestr(["RRULE:FREQ=DAILY;COUNT=2"].join("\n"), { dtstart: new Date(Date.UTC(2020, 6, 4, 0, 0)) }).toString()

produces:

'DTSTART:20200704T000000Z\nRRULE:FREQ=DAILY;COUNT=2'

while the following code:

rrule.rrulestr(["RRULE:FREQ=DAILY;COUNT=2",  "EXDATE:20600130T124000Z"].join("\n"), { dtstart: new Date(Date.UTC(2020, 6, 4, 0, 0)) 

unexpectedly produces:

'RRULE:FREQ=DAILY;COUNT=2\nEXDATE:20600130T124000Z'

and when inspecting the resultant RRuleSet, the dtstart parameter is not set correctly.

Notice that the DTSTART is missing entirely, because in the second example, rrulestr is producing an RRuleSet instead of an RRule. This bug also occurs if you pass forceset: true into the rrulestr options. This also manifests when calling .all() on the RRuleSet, which uses datetime.now() as the dtstart because it thinks that there wasn't one defined.

Version of rrule: 2.6.4 Operating system: MacOS High Sierra Local timezone: PDT

topherauyeung avatar Jul 23 '20 23:07 topherauyeung

Confirming, I have the same problem. Took a long to figure this one out. It happens even without the forceset: true though. My problem:

rrulestr(`
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=MO;BYHOUR=15;BYMINUTE=0
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=TU;BYHOUR=15;BYMINUTE=0
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=SU;BYHOUR=15;BYMINUTE=0
`, { dtstart: new Date(Date.UTC(2021, 0, 1))} ).toString();

gives:

RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=MO;BYHOUR=15;BYMINUTE=0
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=TU;BYHOUR=15;BYMINUTE=0
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=SU;BYHOUR=15;BYMINUTE=0

but what i expected was:

DTSTART:20210905T000000Z
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=MO;BYHOUR=15;BYMINUTE=0
DTSTART:20210905T000000Z
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=TU;BYHOUR=15;BYMINUTE=0
DTSTART:20210905T000000Z
RRULE:FREQ=WEEKLY;BYSECOND=0;BYDAY=SU;BYHOUR=15;BYMINUTE=0

Noitidart avatar Sep 05 '21 16:09 Noitidart

I wrote a workaround until then, it requires moment.

function getSetFromTimeRule(timeRule, options = {}) {
  let dtstartStr = '';
  if (options.dtstartMoment) {
    dtstartStr =
      'DTSTART:' + startWeekMoment.format('YYYYMMDD[T]HHmmss[Z]') + '\n';
  }

  const set = rrulestr(dtstart + timeRule);

  return set;
}

Noitidart avatar Sep 05 '21 19:09 Noitidart

Thanks! I had the same issue: setting dtstart via the rrulestr options didn't work: I got dates before the DTSTART in the result. The fix above by @Noitidart does work, but seems a workaround for broken functionality.

PanMan avatar Dec 13 '21 16:12 PanMan

Agreed, I really dont like my work around. I should remove moment from it too, its too much for others that use it and dont have moment installed.

Noitidart avatar Dec 13 '21 17:12 Noitidart

Hey folks,

I had this issue when using the rrulestr function with an RRULE that contained an EXDATE. The solution for me was to prefer using parsedRule.dtstart() and parsedRule.tzid(). I now fallback to what I was previously using (broken) which is parsedRule.options.dtstart and parsedRule.options.tzid.

It seems that the callable functions (which I hope are always present) work more reliably than accessing the options.

morgan-wowk avatar Sep 11 '22 02:09 morgan-wowk

So ? No news ?

giphy (11)

NOPR9D avatar Mar 24 '23 16:03 NOPR9D