Search code examples
javaicalendarbiweekly

BiWeekly Iterating over daylight savings change


I am trying to iterate an event across a daylight savings change with the Java BiWeekly library.

Say the event starts at 8am, I want it to stay at 8am regardless of whether daylight savings is in effect or not.

The following code is from the BiWeekly website: https://github.com/mangstadt/biweekly/wiki/Examples#calculating-the-dates-in-a-recurring-event

ICalendar ical = ...
TimezoneInfo tzinfo = ical.getTimezoneInfo();

VEvent event = ical.getEvents().get(0);
DateStart dtstart = event.getDateStart();

TimeZone timezone;
if (tzinfo.isFloating(dtstart)){
  timezone = TimeZone.getDefault();
} else {
  TimezoneAssignment dtstartTimezone = tzinfo.getTimezone(dtstart);
  timezone = (dtstartTimezone == null) ? TimeZone.getTimeZone("UTC") : dtstartTimezone.getTimeZone();
}
DateIterator it = event.getDateIterator(timezone);

If I have a celendar created as:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Michael Angstadt//biweekly 0.6.3//EN
BEGIN:VEVENT
UID:deb01413-942a-4ea9-a53c-541493fa668a
DTSTAMP:20200213T051827Z
SUMMARY;LANGUAGE=en-us:Team Meeting
DTSTART;TZID=/Pacific/Auckland:20200213T181827
DURATION:PT1H
RRULE:FREQ=WEEKLY;INTERVAL=2
END:VEVENT
END:VCALENDAR

Iterating over this, the time changes by an hour as it crosses the daylight savings boundary.

How should it be done to keep the occurrences occurring at the given time? (It is correct that it occurs at the same time in UTC, but I want it to occur at the same time locally.)


Solution

  • For some reason the dtstartTimezone in the code above is returning null even though there was a timezone in the DTSTART of the event. (That might be another issue to track down.)

    Because this was null the iterator was getting a UTC timezone and hence the dates iterated were UTC based and changed when crossing the daylight saving boundary in the target timezone.

    Removing the timezone assignment code that pulled the timezone out of the calendar and replacing it with val timezone = TimeZone.getTimeZone("Pacific/Auckland") (or the proper timezone) and using that in the iterator fixes this issue.