rrule
rrule copied to clipboard
toText() returns the wrong "until" date (one day early)
When converting an RRule toText()
, the end of the recurrence is one day early. See screenshot from the demo page below:

- Expected output:
until December 26, 2021
- Actual output:
until December 25, 2021
- Version of rrule:
2.6.8
- Operating system: Linux (Fedora 34)
- Local timezone: CEST
Thank you for rrule and your support!
I am also facing same issue whenever using new RRule({values}).toText().
@schemar I have manged to fix it by passing a new Date(), formatted like 2021-12-31 to until property inside RRule. But the bug is still showing on the mentioned rrule demo page.
The issue seems to be a problem on RRule.fromText()
.
specifying until
via new RRule(options)
works fine, and the until
date is also included in the recurring instances.
However, if you use RRule.fromText()
, the until date is excluded from the recurring instances, and doing .toText()
shows that there is an off-by-one error, the until in .toText()
is one day earlier than what is passed into .fromText()
I have found the root cause of this behavior. It should only occur for people who are living in timezones before UTC. https://github.com/jakubroztocil/rrule/blob/d352fb3c235fa91f9ee108851f49a4b76e2b8ee4/src/nlp/parsetext.ts#L426
It parses date as local time instead of UTC time. For example, you are at UTC+8, and run the following:
const d = Date.parse('dec 29 2022');
const d2 = new Date(d);
console.log(d2);
You'd get Date: "2022-12-28T16:00:00.000Z"
, which is 2022-12-29T00:00:00 for UTC +8.
However, if you pass in 'dec 29 2022 UTC' instead, you would get the expected "2022-12-29T00:00:00.000Z" for d2.
I'm starting to think that this is not an actual issue. It's because we are passing in date and time without specifying the timezone, and naturally, it is assumed to be our local timezone.
As documented, RRule will work on datetime in UTC, and return them in UTC. So it is up to the user to specify if the input timezone, or convert the output to their timezone.
There's an issue with this though: If you parse "every day until March 27, 2023 UTC" and then toText()
it, you get "every day until March 27, 2023", meaning when you parse it again, it gets interpreted in local time this time around.
I think it would be most sensible to use UTC to parse that, since when a user writes a date, I don't think they mean exactly at the moment of midnight, but rather only that date.