mangstadt / biweekly

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

DAYLIGHT in VTIMEZONE not applied when DTSTART very old (Outlook generated iCalendar) #85

Closed sven-geisenhainer closed 4 years ago

sven-geisenhainer commented 6 years ago

Outlook 16.0 generated iCalendars might use very old DTSTART property values for VTIMEZONE observance rrules, e.g.:

BEGIN:VTIMEZONE BEGIN:DAYLIGHT DTSTART:16010325T020000 ... END:DAYLIGHT ... END:VTIMEZONE

biweekly seems to stick to the STANDARD observance rrule if the DAYLIGHT rrule starts before 1919-01-01.

Complete example (test.ics generated by Outlook 16.0, irrelevant properties removed):

BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:W. Europe Standard Time
BEGIN:STANDARD
DTSTART:16011028T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010325T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
CLASS:PUBLIC
CREATED:20180314T152639Z
DESCRIPTION: Test
DTEND;TZID="W. Europe Standard Time":20180722T130000
DTSTAMP:20180314T152639Z
DTSTART;TZID="W. Europe Standard Time":20180722T120000
SUMMARY;LANGUAGE=de:Meeting in Berlin
UID:0a1f4b32-279a-11e8-adab-e67eecc63901
END:VEVENT
END:VCALENDAR

Test programm:

public static void main(String[] args) throws Exception {
        File file = new File("test.ics");
        ICalendar ical = Biweekly.parse(file).first();
        VEvent event = ical.getEvents().get(0);
        System.out.println("Start: " + event.getDateStart().getValue());
        System.out.println("End: " + event.getDateEnd().getValue());
}

Output:

Start: Sun Jul 22 13:00:00 CEST 2018 End: Sun Jul 22 14:00:00 CEST 2018

Changing the DAYLIGHT rrules DTSTART property value to a more recent date e.g. 19800101T000000 fixes the issue.

mangstadt commented 4 years ago

It's been a while, but...

I am not able to reproduce this. Your JVM's default timezone isn't different from the timezone defined in the iCal file, is it?

Because the event starts in July, that means its UTC offset should be +2:00, correct? Which means the start time of the event should be 10:00 UTC and the end time should be 11:00 UTC.

The following unit test passes for me. "issue85.ical" contains your iCalendar data verbatim and "issue85-1980.ical" is the same, but with DAYLIGHT's DTSTART set to "19800101T000000"

@Test
public void test() throws Exception {
  DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
  df.setTimeZone(TimeZone.getTimeZone("UTC"));

  String files[] = { "issue85.ical", "issue85-1980.ical" };
  for (String file : files) {
    ICalendar ical = Biweekly.parse(new File(file)).first();
    VEvent event = ical.getEvents().get(0);

    assertEquals("2018-07-22T10:00:00", df.format(event.getDateStart().getValue()));
    assertEquals("2018-07-22T11:00:00", df.format(event.getDateEnd().getValue()));
  }
}
sven-geisenhainer commented 4 years ago

I also cannot reproduce this anymore (v0.6.3) - obviously the issue has already been fixed. Thank you for investigating and keep the good work going!

mangstadt commented 4 years ago

Thanks!