u01jmg3 / ics-parser

Parser for iCalendar Events • PHP 8+, 7 (≥ 7.4), 5 (≥ 5.6)
MIT License
448 stars 144 forks source link

With X-WR-TIMEZONE set wrong time is returned #245

Closed arwinvdv closed 2 years ago

arwinvdv commented 4 years ago

Description of the Issue:

Google Calendar provides X-WR-TIMEZONE attributed and a VTIMEZONE. When the X-WR-TIMEZONE isset it ignores the VTIMEZONE. But with the iCal I get from Google the events are one hour to early.

The ics file:

BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Test
X-WR-TIMEZONE:UTC
BEGIN:VTIMEZONE
TZID:Europe/Amsterdam
X-LIC-LOCATION:Europe/Amsterdam
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART:20191104T153000Z
DTEND:20191104T160000Z
DTSTAMP:20191105T084237Z
UID:abcd@google.com
CREATED:20191101T164838Z
DESCRIPTION:
LAST-MODIFIED:20191101T164838Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:test event
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

Actual result:

dtstart: "20191104T153000Z"
dtend: "20191104T160000Z"
"dtstart_tz": "20191104T153000"
"dtend_tz": "20191104T160000"

Expected result:

dtstart: "20191104T153000Z"
dtend: "20191104T160000Z"
"dtstart_tz": "20191104T163000"
"dtend_tz": "20191104T170000"

Possible solution

In calendarTimeZone($ignoreUtc = false) first check for VTIMEZONE?

u01jmg3 commented 2 years ago

@s0600204: again I understand if you're busy but your input would be welcome on this issue too

s0600204 commented 2 years ago

dtstart_tz and dtend_tz represent the start and end points of an event local to the "timezone of the calendar". This, of course, requires some determination of what the "timezone of the calendar" is.

To do this, the ics-parser reads from the (non-standard) X-WR-TIMEZONE stanza, which in the ics sample given has a value of UTC. Remove this line and the ics-parser uses the last-specified VTIMEZONE instead (Europe/Amsterdam).

Personally, I advise not using dtstart_tz or dtend_tz - if you aren't in the same timezone as the one specified by X-WR-TIMEZONE, then neither are of any use.

If you wish to know the start of an event as a date-time local to a timezone of your choosing:

// Get the UTC timestamp of the date:
$start_utc = $event->dtstart_array[2];

// Create a php DateTime object:
$start_datetime = new DateTime('@' . $start_utc);

// Cast into the timezone you wish the output to be:
// (php-recognised timezones only: https://www.php.net/manual/en/timezones.php)
$start_datetime->setTimezone(new DateTimeZone('Europe/Oslo'));

// Output into a format of your choosing:
echo $start_datetime->format('Y-m-d H:i:s');

As an aside:

RFC5545 doesn't specify a way to declare a "calendar timezone" or a "default" timezone - it doesn't need one: date-times specified without timezones are considered to be local to whatever timezone is "observing" (e.g. whichever timezone the reader is in). This does however mean that DTSTART=20210202T090000 when read by someone in Berlin refers to a different absolute point in time than when read by someone in New York (08:00 UTC and 14:00 UTC respectively).

To get round this, Google (and Apple and others) use the non-standard X-WR-TIMEZONE stanza to say: "All those floating date-times without an explicit timezone? They're all local to this one." (In case this is unclear: this runs contrary to the RFC5545 specification, and thus is - by definition - incorrect behaviour.)

(The standards-compliant way would be to not use floating date-times, but to explicitly specify a timezone for each and every one.)

The popularity of the non-standard stanza does present some interoperability problems: if we completely ignored it, we would get complaints about incorrect event times from users of Google Calendar/Apple iCal living outside the timezone specified by the stanza in question.

In reference to this particular issue however: we are presented with a date-time with an explicit timezone (UTC), so the "calendar's timezone" (such as it may or may not be) is irrelevant.

See also: https://blog.jonudell.net/2011/10/17/x-wr-timezone-considered-harmful/

u01jmg3 commented 2 years ago

@s0600204: thank you for the detailed explanation

@arwinvdv: I'm closing this issue in light of the above. I would also recommend reading the attached article - even 11 years on it is still relevant.