tangled
alpha
login
or
join now
timtinkers.online
/
lemoncalendar
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
Get calendar-level timezone fix
timtinkers.online
1 year ago
17f1f3fc
5a2d53de
+20
-27
1 changed file
expand all
collapse all
unified
split
utils
calendarUtils.ts
+20
-27
utils/calendarUtils.ts
···
5
5
import parseISO from "https://deno.land/x/date_fns@v2.22.1/parseISO/index.js";
6
6
import startOfDay from "https://deno.land/x/date_fns@v2.22.1/startOfDay/index.ts";
7
7
import endOfDay from "https://deno.land/x/date_fns@v2.22.1/endOfDay/index.ts";
8
8
-
import { fromZonedTime } from "npm:date-fns-tz";
9
8
10
9
export interface Event {
11
10
start: Date;
···
47
46
}
48
47
49
48
const icsData = await response.text();
49
49
+
50
50
+
// Extract calendar-level timezone if present
51
51
+
let calendarTimezone: string | null = null;
52
52
+
const tzMatch = icsData.match(/X-WR-TIMEZONE:(.*?)(?:\r?\n)/);
53
53
+
if (tzMatch && tzMatch[1]) {
54
54
+
calendarTimezone = tzMatch[1].trim();
55
55
+
}
56
56
+
50
57
const events = ical.parseICS(icsData);
51
58
52
59
const parsedEvents = parseICalEvents(events).sort((a, b) =>
53
60
a.start.getTime() - b.start.getTime()
54
61
);
55
62
63
63
+
// Apply calendar-level timezone to events that don't have their own timezone
64
64
+
if (calendarTimezone) {
65
65
+
parsedEvents.forEach((event) => {
66
66
+
if (!event.timezone) event.timezone = calendarTimezone;
67
67
+
});
68
68
+
}
69
69
+
56
70
return parsedEvents;
57
71
}
58
72
59
73
// deno-lint-ignore no-explicit-any
60
74
function parseICalEvents(icalEvents: Record<string, any>): Event[] {
61
61
-
// Extract calendar-level timezone if available
62
62
-
const calendarTz =
63
63
-
Object.values(icalEvents).find((item) => item.type === "VCALENDAR")
64
64
-
?.["x-wr-timezone"] || "UTC";
65
65
-
66
75
return Object.values(icalEvents)
67
76
.filter((event) => event.type === "VEVENT")
68
77
.map((event) => {
69
69
-
// Use event-specific timezone if available, otherwise fallback to calendar timezone
70
70
-
const eventTz = event.startZone || calendarTz;
71
71
-
72
72
-
// Convert dates to UTC for internal comparisons
73
73
-
const start = normalizeDate(event.start, eventTz);
74
74
-
const end = normalizeDate(event.end, eventTz);
78
78
+
// Extract timezone information if available
79
79
+
const timezone = event.start?.tz ? event.start.tz.replace(/^\//, '') : null;
75
80
76
81
return {
77
77
-
start,
78
78
-
end,
82
82
+
start: event.start,
83
83
+
end: event.end,
79
84
location: event.location || "",
80
85
summary: event.summary || "",
81
86
description: event.description || "",
82
82
-
timezone: eventTz,
87
87
+
timezone: timezone,
83
88
};
84
89
});
85
85
-
}
86
86
-
87
87
-
function normalizeDate(date: Date, timezone: string): Date {
88
88
-
if (!date) return date;
89
89
-
90
90
-
try {
91
91
-
// Convert the date to UTC while respecting the original timezone
92
92
-
return fromZonedTime(date, timezone);
93
93
-
} catch (e) {
94
94
-
console.warn(`Failed to parse timezone ${timezone}:`, e);
95
95
-
return date;
96
96
-
}
97
90
}
98
91
99
92
export function filterEvents(