mangstadt / biweekly

biweekly is an iCalendar library written in Java.
BSD 2-Clause "Simplified" License
323 stars 44 forks source link

Recurrence ends are not calculated correctly #101

Closed daMihe closed 4 years ago

daMihe commented 4 years ago

Thank you for making this great calendar library.

However there is a bug inside the recurrence calculation, reproducible using following calendar:

BEGIN:VCALENDAR
PRODID:-//K Desktop Environment//NONSGML libkcal 4.3//EN
VERSION:2.0
X-KDE-ICAL-IMPLEMENTATION-VERSION:1.0
BEGIN:VTIMEZONE
TZID:Europe/Berlin
BEGIN:STANDARD
TZNAME:CET
TZOFFSETFROM:+0000
TZOFFSETTO:+0100
DTSTART:19791231T230000
RDATE:19791231T230000
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:CEST
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
DTSTART:19810329T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:CEST
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
DTSTART:19800406T020000
RDATE:19800406T020000
END:DAYLIGHT
BEGIN:STANDARD
TZNAME:CET
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
DTSTART:19971026T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:STANDARD
TZNAME:CET
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
DTSTART:19800928T030000
RRULE:FREQ=YEARLY;UNTIL=19961027T030000;BYDAY=-1SU;BYMONTH=9
RDATE:19950924T030000
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20201003T144319Z
CREATED:20201003T144243Z
UID:37c5678e-ab6e-4616-a11b-0ce7e8dcd3c6
LAST-MODIFIED:20201003T144319Z
SUMMARY:Repeating
RRULE:FREQ=DAILY;UNTIL=20201010T145800Z
DTSTART;TZID=Europe/Berlin:20201004T170000
DTEND;TZID=Europe/Berlin:20201004T180000
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

The frequency of the event is daily and i would expect to be the last instance of the event on 2020-10-09 17:00:00 +0200 because of the UNTIL-Date in Recurrence rule ending before it would start on 2020-10-10. The DateIterator is instead returning also an instance on 2020-10-10. Other programs do not.

Example program and output:

InputStream inputFile = TestClass.class.getClassLoader().getResourceAsStream("test.ics");
try {
    ICalendar calendar = Biweekly.parse(inputFile).first();
    for (VEvent evt: calendar.getEvents()) {
        DateIterator it = evt.getDateIterator(TimeZone.getDefault());
        while (it.hasNext()) {
            Date current = it.next();
            System.out.println(current.toString());
        }
        System.out.println("end");
    }
} catch (IOException e) {
    e.printStackTrace();
}

produces:

Sun Oct 04 17:00:00 CEST 2020
Mon Oct 05 17:00:00 CEST 2020
Tue Oct 06 17:00:00 CEST 2020
Wed Oct 07 17:00:00 CEST 2020
Thu Oct 08 17:00:00 CEST 2020
Fri Oct 09 17:00:00 CEST 2020
Sat Oct 10 17:00:00 CEST 2020
end
daMihe commented 4 years ago

Ah sorry, did not find issue #99 before. Closing this as it's a duplicate. Sorry for bothering.

mangstadt commented 4 years ago

Thanks for reporting this. The bug that was fixed in https://github.com/mangstadt/biweekly/issues/99 has yet to be released.

To confirm: You are saying that the Oct 10 date should NOT be returned by the iterator?

I ran your example against the latest code and it indeed returns Oct 4-9.

daMihe commented 4 years ago

Oh cool, you are making a unit test.

Confirming that 10th of October should not be listed. Detail: 20201010T170000 in Europe/Berlin is 20201010T150000Z and therefore after “until” in rrule.

mangstadt commented 4 years ago

Thanks!