mangstadt / biweekly

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

Consider parsing support for X-WR-TIMEZONE #90

Closed waded closed 5 years ago

waded commented 5 years ago

I've noticed that relatively common calendar exports (e.g. export URLs provided by Google Calendar as of 9/18/2019) use X-WR-TIMEZONE to state timezone of events contained within, rather than VTIMEZONE with, or global IDs on, the DTSTART/DTEND values.

Here's the result of export of a simple calendar from Google Calendar, where the calendar itself is set to America/Denver, then an event's added that's intended to be in that zone, set explicitly to start at 6PM in Denver, and then exported using the iCal URL Google Calendar provides in Calendar Settings:

BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:TEST CALENDAR
X-WR-TIMEZONE:America/Denver
X-WR-CALDESC:A calendar with time zone set to America/Denver.
BEGIN:VEVENT
DTSTART:20190919T000000Z
DTEND:20190919T010000Z
DTSTAMP:20190918T215921Z
UID:63dhaee7e9pgtht3l4s8uvh2be@google.com
CREATED:20190918T215716Z
DESCRIPTION:
LAST-MODIFIED:20190918T215716Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Event set to Sept 18 2019 6PM in Denver
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

When parsed by biweekly 0.6.3 the value of calendar.getTimezoneInfo().getTimezone(event.getDateStart()) and calendar.getTimezoneInfo().getDefaultTimezone() are both null. Per the documentation it's understood then that both this event and the default are UTC. And DTSTART is 20190919T000000Z which is UTC equivalent to 6PM in Denver on that day. But this may be surprising to the user of biweekly in this situation, since during creation of the calendar the timezone was set to America/Denver on both calendar and event in the user interface.

Has any kind of mode for parsing X-WR-TIMEZONE to default been considered, beyond built-it-yourself using calendar.getExperimentalProperty("X-WR-TIMEZONE")? I didn't see any history of support for this specificially in this repository so I thought I'd bring it up. It appears based on googling that it's X-WR-TIMEZONe has been used by Google as far back as 10 years ago, and other libraries have grappled with it.

waded commented 5 years ago

My feedback is it may be best to simply enhance examples in documentation about dealing with timezones to include code examples of using the biweekly library to determine zoned times normatively (VTIMEZONE, time with global IDs, time with Z, or floating) from an iCal feed... and then a mention that X-WR-TIMEZONE exists and can be used as informatively to determine a zone if a preference for zone isn't known and a particular event resolves to UTC (often not the best choice for display) without it.

mangstadt commented 5 years ago

The methods you referenced are intended to be used primarily for (1) calculating the times of recurring events and (2) determining how dates should be serialized when written to an ical file. They are not necessarily meant to be used for determining how a particular date should be displayed to the end-user (if that is what you were suggesting).

Timezones are very important for calculating the dates of recurring events because these events can span daylight savings boundaries, which vary depending on the timezone. I tried exporting my own Google Calendar, which contains recurring events, and the ICS file contained both VTIMEZONE components and a X-WR-TIMEZONE property. Maybe Google Calendar is including the VTIMEZONE for backwards compatibility? Or maybe X-WR-TIMEZONE isn't meant to be a complete replacement for vanilla timezone definitions? A specification document for X-WR-TIMEZONE would be helpful.

I'm not sure I want to include this in the core API, since it is not part of the main iCal specification. But I have added a section to the wiki that mentions this. Please have a read and let me know your thoughts. https://github.com/mangstadt/biweekly/wiki/Timezones#x-wr-timezone

waded commented 5 years ago

The new section in the wiki about X-WR-TIMEZONE makes sense. I think it resolves this issue. (Please close it if you agree.) I agree with not adding anything to the core API beyond the existing experimental property access methods. An enum of common experimental properties may make some sense at some point, providing a place to attach documentation to the code itself, but the wiki provides an important overview of how RFC5545 and the library intersect. Thanks!

I did search for any kind of specification of X-WR-TIMEZONE and found nothing.

For Google Calendar I believe (based on inspection of behavior, no particular insider knowledge here) it's merely a mirror of the timeZone property at the Calendar level in their API. That property is separate from timeZone properties at the Event level in the API, which are required for recurring events for the same reason as in RFC5545. Once exporting to iCal, the timeZones set on events get converted into VTIMEZONE as necessary to clarify the recurrence, but the time zone at the calendar level is communicated with X-WR-TIMEZONE. Then once imported, the user doing the import sees the same zone and formatted times on non-recurring events as the user who exported. (And the user can change that zone in settings of the calendar.)

mangstadt commented 5 years ago

Sounds good. I will close the issue. Thanks for your time!