fix: timezone parsing issues for calendars (#21665)
* fix timezone parsing issues for calendars * fix: maintain backward compatibility with other timezone specification methods accepting the cubic-dev-ai as implement backward compatibility with different event ICS event types Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update Cubic comment * Fix timezone handling in ICS feed calendar service - Fix VTIMEZONE selection to find matching timezone instead of using first one - Improve TZID parameter extraction from DTSTART property using jCal array - Fix precedence: DTSTART TZID > standalone TZID > UTC > fallback - Resolves issue where Europe/Brussels events showed wrong times in Europe/Paris * remove comments * remove comments --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Kartik Saini <41051387+kart1ka@users.noreply.github.com>
This commit is contained in:
2 files changed
+41
-8
No files matched your search
@@ -159,11 +159,17 @@ export default class ICSFeedCalendarService implements Calendar {
|
||||
// if (vevent?.getFirstPropertyValue("transp") === "TRANSPARENT") return;
|
||||
|
||||
const event = new ICAL.Event(vevent);
|
||||
const dtstartProperty = vevent.getFirstProperty("dtstart");
|
||||
const tzidFromDtstart = dtstartProperty ? (dtstartProperty as any).jCal[1].tzid : undefined;
|
||||
|
||||
const dtstart: { [key: string]: string } | undefined = vevent?.getFirstPropertyValue("dtstart");
|
||||
const timezone = dtstart ? dtstart["timezone"] : undefined;
|
||||
// We check if the dtstart timezone is in UTC which is actually represented by Z instead, but not recognized as that in ICAL.js as UTC
|
||||
const isUTC = timezone === "Z";
|
||||
const tzid: string | undefined = vevent?.getFirstPropertyValue("tzid") || isUTC ? "UTC" : timezone;
|
||||
|
||||
// Fix precedence: prioritize TZID from DTSTART property, then standalone TZID, then UTC, then fallback
|
||||
const tzid: string | undefined =
|
||||
tzidFromDtstart || vevent?.getFirstPropertyValue("tzid") || (isUTC ? "UTC" : timezone);
|
||||
// In case of icalendar, when only tzid is available without vtimezone, we need to add vtimezone explicitly to take care of timezone diff
|
||||
if (!vcalendar.getFirstSubcomponent("vtimezone")) {
|
||||
const timezoneToUse = tzid || userTimeZone;
|
||||
@@ -192,7 +198,16 @@ export default class ICSFeedCalendarService implements Calendar {
|
||||
console.error("No timezone found");
|
||||
}
|
||||
}
|
||||
const vtimezone = vcalendar.getFirstSubcomponent("vtimezone");
|
||||
|
||||
let vtimezone = null;
|
||||
if (tzid) {
|
||||
const allVtimezones = vcalendar.getAllSubcomponents("vtimezone");
|
||||
vtimezone = allVtimezones.find((vtz) => vtz.getFirstPropertyValue("tzid") === tzid);
|
||||
}
|
||||
|
||||
if (!vtimezone) {
|
||||
vtimezone = vcalendar.getFirstSubcomponent("vtimezone");
|
||||
}
|
||||
|
||||
// mutate event to consider travel time
|
||||
applyTravelDuration(event, getTravelDurationInSeconds(vevent));
|
||||
@@ -263,9 +278,11 @@ export default class ICSFeedCalendarService implements Calendar {
|
||||
event.endDate = event.endDate.convertToZone(zone);
|
||||
}
|
||||
|
||||
const finalStartISO = dayjs(event.startDate.toJSDate()).toISOString();
|
||||
const finalEndISO = dayjs(event.endDate.toJSDate()).toISOString();
|
||||
return events.push({
|
||||
start: dayjs(event.startDate.toJSDate()).toISOString(),
|
||||
end: dayjs(event.endDate.toJSDate()).toISOString(),
|
||||
start: finalStartISO,
|
||||
end: finalEndISO,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -393,11 +393,16 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
if (vevent?.getFirstPropertyValue("transp") === "TRANSPARENT") return;
|
||||
|
||||
const event = new ICAL.Event(vevent);
|
||||
const dtstartProperty = vevent.getFirstProperty("dtstart");
|
||||
const tzidFromDtstart = dtstartProperty ? (dtstartProperty as any).jCal[1].tzid : undefined;
|
||||
const dtstart: { [key: string]: string } | undefined = vevent?.getFirstPropertyValue("dtstart");
|
||||
const timezone = dtstart ? dtstart["timezone"] : undefined;
|
||||
// We check if the dtstart timezone is in UTC which is actually represented by Z instead, but not recognized as that in ICAL.js as UTC
|
||||
const isUTC = timezone === "Z";
|
||||
const tzid: string | undefined = vevent?.getFirstPropertyValue("tzid") || isUTC ? "UTC" : timezone;
|
||||
|
||||
// Fix precedence: prioritize TZID from DTSTART property, then standalone TZID, then UTC, then fallback
|
||||
const tzid: string | undefined =
|
||||
tzidFromDtstart || vevent?.getFirstPropertyValue("tzid") || (isUTC ? "UTC" : timezone);
|
||||
// In case of icalendar, when only tzid is available without vtimezone, we need to add vtimezone explicitly to take care of timezone diff
|
||||
if (!vcalendar.getFirstSubcomponent("vtimezone")) {
|
||||
const timezoneToUse = tzid || userTimeZone;
|
||||
@@ -426,7 +431,16 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
console.error("No timezone found");
|
||||
}
|
||||
}
|
||||
const vtimezone = vcalendar.getFirstSubcomponent("vtimezone");
|
||||
|
||||
let vtimezone = null;
|
||||
if (tzid) {
|
||||
const allVtimezones = vcalendar.getAllSubcomponents("vtimezone");
|
||||
vtimezone = allVtimezones.find((vtz) => vtz.getFirstPropertyValue("tzid") === tzid);
|
||||
}
|
||||
|
||||
if (!vtimezone) {
|
||||
vtimezone = vcalendar.getFirstSubcomponent("vtimezone");
|
||||
}
|
||||
|
||||
// mutate event to consider travel time
|
||||
applyTravelDuration(event, getTravelDurationInSeconds(vevent, this.log));
|
||||
@@ -498,9 +512,11 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
event.endDate = event.endDate.convertToZone(zone);
|
||||
}
|
||||
|
||||
const finalStartISO = dayjs(event.startDate.toJSDate()).toISOString();
|
||||
const finalEndISO = dayjs(event.endDate.toJSDate()).toISOString();
|
||||
return events.push({
|
||||
start: dayjs(event.startDate.toJSDate()).toISOString(),
|
||||
end: dayjs(event.endDate.toJSDate()).toISOString(),
|
||||
start: finalStartISO,
|
||||
end: finalEndISO,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user