Skip to content

Timezone DTSTART is interpreted as UTC #847

Description

@Tugzrida

When converting times from UTC to local time, the DTSTART times from the timezone definition seem to be interpreted as (almost) UTC instead of in their TZOFFSETFROM as set out in RFC5545 and as used by every ICS I've been able to find in the wild.

From a brief look, it seems that utcOffset in timezone.js compares the provided time with the timezone's change points assuming they're both normalised to the same UTC offset, but this is not necessarily true.

Below is a minimal reproduction and table setting out the provided input, actual output and expected output for this example.

const zoneDef = `BEGIN:VCALENDAR
PRODID:-//tzurl.org//NONSGML Olson 2025a//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Australia/Sydney
LAST-MODIFIED:20250121T082933Z
TZURL:https://www.tzurl.org/zoneinfo/Australia/Sydney
X-LIC-LOCATION:Australia/Sydney
X-PROLEPTIC-TZNAME:LMT
BEGIN:STANDARD
TZNAME:AEST
TZOFFSETFROM:+1100
TZOFFSETTO:+1000
DTSTART:20080406T030000
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:AEDT
TZOFFSETFROM:+1000
TZOFFSETTO:+1100
DTSTART:20081005T020000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
END:DAYLIGHT
END:VTIMEZONE
END:VCALENDAR
`

const sydTZ = new ICAL.Timezone({
    component: new ICAL.Component(ICAL.parse(zoneDef)).getFirstSubcomponent("vtimezone"),
    tzid: "Australia/Sydney"
})

console.log(ICAL.Time.fromDateTimeString('2025-04-05T16:00:00Z').convertToZone(sydTZ).toString())
Input Output Expected
2025-04-05T14:00:00Z 2025-04-06T01:00:00 2025-04-06T01:00:00
2025-04-05T15:00:00Z 2025-04-06T02:00:00 2025-04-06T02:00:00
2025-04-05T16:00:00Z 2025-04-06T03:00:00 2025-04-06T02:00:00
2025-04-05T17:00:00Z 2025-04-06T04:00:00 2025-04-06T03:00:00
... ... ...
2025-04-06T01:00:00Z 2025-04-06T12:00:00 2025-04-06T11:00:00
2025-04-06T02:00:00Z 2025-04-06T12:00:00 2025-04-06T12:00:00
2025-04-06T03:00:00Z 2025-04-06T13:00:00 2025-04-06T13:00:00
2025-04-06T04:00:00Z 2025-04-06T14:00:00 2025-04-06T14:00:00

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions