Rrule: Recurring Events using byweekday shift by one day

Created on 22 Mar 2020  ·  3Comments  ·  Source: jakubroztocil/rrule

  • [x] Verify that you've looked through existing issues for duplicates before
    creating a new one
  • [x] Code sample reproducing the issue. Be sure to include all input values you
    are using such as the exact RRule string and dates.
  • [x] Expected output
  • [x] Actual output
  • [x] The version of rrule you are using

    • 2.6.4

  • [x] Your operating system

    • Linux

  • [x] Your local timezone (run $ date from the command line of the machine showing the bug)

    • Europe/Paris but timezones are shifted. See below


I'm trying to get the next Tuesdays after a given date (1st Feb 2020 in Europe/Paris).
Nonetheless the events start at Wednesday if still being in that timezone.
Calculating the events for timezone America/New_York the events are as expected.

Please check the below snippet. My findings are:

// problem: events should be on Tuesday but are shifted by one day:
// Tue Feb 04 2020 00:00:00 GMT+0100 (Central European Standard Time) ...
$ TZ=Europe/Paris node zone.js Europe/Paris
rule:
DTSTART;TZID=Europe/Paris:20200131T230000
RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=2
events:
Wed Feb 05 2020 00:00:00 GMT+0100 (Central European Standard Time)
Wed Feb 12 2020 00:00:00 GMT+0100 (Central European Standard Time)
luxon:
Sat Feb 01 2020 00:00:00 GMT+0100 (Central European Standard Time)

// timezone America/New_York shows correct result
$ TZ=America/New_York node zone.js America/New_York
rule:
DTSTART;TZID=America/New_York:20200201T050000
RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=2
events:
Tue Feb 04 2020 00:00:00 GMT-0500 (Eastern Standard Time)
Tue Feb 11 2020 00:00:00 GMT-0500 (Eastern Standard Time)
luxon:
Sat Feb 01 2020 00:00:00 GMT-0500 (Eastern Standard Time)

// crossing timezones show correct result
$ TZ=America/New_York node zone.js Europe/Paris
rule:
DTSTART;TZID=Europe/Paris:20200201T050000
RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=2
events:
Mon Feb 03 2020 18:00:00 GMT-0500 (Eastern Standard Time)
Mon Feb 10 2020 18:00:00 GMT-0500 (Eastern Standard Time)
luxon:
Sat Feb 01 2020 00:00:00 GMT-0500 (Eastern Standard Time)

// UTC shows correct result
$ TZ=UTC node zone.js UTC
rule:
DTSTART:20200201T000000Z
RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=2
events:
Tue Feb 04 2020 00:00:00 GMT+0000 (Coordinated Universal Time)
Tue Feb 11 2020 00:00:00 GMT+0000 (Coordinated Universal Time)
luxon:
Sat Feb 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)
const { DateTime } = require('luxon')
const { RRule } = require('rrule/dist/es5/rrule-tz.js')

const dtstart = new Date(2020, 1, 1, 0)
const tzid = process.argv[2] || 'Europe/Paris'

const rule = new RRule({
  freq: RRule.WEEKLY,
  dtstart,
  tzid,
  byweekday: [RRule.TU],
  count: 2
})

console.log('rule:\n' + rule.toString())
console.log('events:\n' + rule.all().map(d => d.toString()).join('\n'))

const datetime = DateTime.fromJSDate(dtstart).setZone(tzid)
console.log('luxon:\n' + datetime.toJSDate().toString())

Most helpful comment

Hello, the same issue here
For recurrence: "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=20200430T040000Z"

rule.all() shows TU,WE,TH,FR,SA

All 3 comments

Hello, the same issue here
For recurrence: "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=20200430T040000Z"

rule.all() shows TU,WE,TH,FR,SA

Update: I think this was purely my confusion around rrule.js's default behavior regarding UTC inputs as well as JS Date objects.

As gleaned from other comments, this confusion seems quite common:
(1) Working with TZID
(2) Inputting DTSTART in the correct format (local to the timezone, rather than UTC or local to the computer)
(3) Inputting the right dates into rrule.between(). If declaring a TZID, much like you have to massage the dates when they come out - using DateTime.fromJSDate(date).toUTC().setZone('local', { keepLocalTime: true }), you have to massage the dates going in to between() (likely after/before as well) using DateTime.fromMillis(posixTime).setZone('utc', { keepLocalTime: true }).

Despite my troubles with the documentation, and frustrations around undocumented behavior, I'm very grateful this library exists. Thank you to the creator and all the maintainers and contributors. Much like luxon grew out of lessons learned from moment, I think the next iteration of an rrule library will build on the shoulders of rrule.js.

Original posted "issue", disregard what I've said below.
Also experiencing what appears to be this issue as well.

import { rrulestr } from 'rrule';

const twoWeeks = 1209600000;
const myrrule = ["DTSTART:20200104T000000Z", "RRULE:FREQ=WEEKLY;BYDAY=FR"]
rrulestr(myrrule.join('\n'))
    .between(new Date(Date.now() - twoWeeks), new Date(Date.now() + twoWeeks))

This returns a list of dates that occur on Thursday.
I've made sure that the DTSTART is UTC.

The event in question occurs on Friday at 18:00-0600 (mountain time), which is the same as Saturday 00:00-UTC, but rrule.between() oddly returns times @ Thursday 18:00-0600.

I'll gladly attempt to dissect the code to see where/how the issue is occurring. If anyone more familiar with the codebase has some tips to point me in the right direction, let me know, thanks!

@davidgoli Hey David! I've been working with rrule, for the past 5 days and cannot figure out how to work with timezones. If I put the time in at 9pm my time, it gets converted to 4am UTC time. This causes an issue when I want to set recurring events on certain days, lets say Fridays. So then it repeats Friday 4am, and when it gets translated back to my timezone, then it is Thursday 9pm when I wanted it on Friday. Do you have any suggestions for this? I tried with tzid but I cannot get that to work either. Not sure how I'm supposed to incorporate Luxon? I have downloaded the package.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

espen picture espen  ·  11Comments

espen picture espen  ·  10Comments

zeluspudding picture zeluspudding  ·  11Comments

grigio picture grigio  ·  7Comments

maconfr picture maconfr  ·  6Comments