rrule icon indicating copy to clipboard operation
rrule copied to clipboard

toText() returns the wrong "until" date (one day early)

Open schemar opened this issue 3 years ago • 5 comments

When converting an RRule toText(), the end of the recurrence is one day early. See screenshot from the demo page below:

image
  • 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!

schemar avatar Oct 26 '21 11:10 schemar

I am also facing same issue whenever using new RRule({values}).toText().

Zeshan-Sh avatar Dec 22 '21 12:12 Zeshan-Sh

@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.

Zeshan-Sh avatar Dec 22 '21 13:12 Zeshan-Sh

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()

CovetingEpiphany2152 avatar Dec 15 '22 10:12 CovetingEpiphany2152

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.

CovetingEpiphany2152 avatar Dec 15 '22 12:12 CovetingEpiphany2152

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.

TobTobXX avatar Mar 31 '23 18:03 TobTobXX