src / ical.ts
import * as ical from "node-ical";
export interface CalEvent {
uid: string;
summary: string;
start: Date;
end: Date;
location?: string;
description?: string;
allDay: boolean;
}
export async function parseIcsFile(filePath: string): Promise<CalEvent[]> {
const raw = await ical.async.parseFile(filePath);
const events: CalEvent[] = [];
for (const key of Object.keys(raw)) {
const item = raw[key];
if (item.type !== "VEVENT") continue;
const start = item.start instanceof Date ? item.start : new Date(item.start as string);
const end = item.end instanceof Date ? item.end : new Date(item.end as string);
events.push({
uid: item.uid ?? key,
summary: item.summary ?? "(no title)",
start,
end,
location: item.location,
description: item.description,
allDay: (item as unknown as Record<string, unknown>).datetype === "date",
});
}
return events.sort((a, b) => a.start.getTime() - b.start.getTime());
}
export function filterByRange(events: CalEvent[], from: Date, to: Date): CalEvent[] {
return events.filter(e => e.end >= from && e.start <= to);
}
export function formatEvent(e: CalEvent): string {
const time = e.allDay
? "all-day"
: `${e.start.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}ā${e.end.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}`;
const loc = e.location ? ` @ ${e.location}` : "";
return `${time}: ${e.summary}${loc}`;
}