diff --git a/icalendar.ts b/icalendar.ts index bf5c638..302651a 100644 --- a/icalendar.ts +++ b/icalendar.ts @@ -29,6 +29,20 @@ const RRULE_KEY_MAP: Record = { "freq": "FREQ", // Just in case }; +/** + * Formats an RRULE value for the string representation. + * Specifically handles Date objects and nested date objects from ts-ics. + */ +function formatRRuleValue(v: any): string { + if (v instanceof Date) { + return v.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z"; + } + if (typeof v === "object" && v !== null && v.date instanceof Date) { + return v.date.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z"; + } + return String(v); +} + // ============================================================================ // Utility Functions // ============================================================================ @@ -186,7 +200,7 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] { cleanRule = Object.entries(rruleStr) .map(([k, v]) => { const standardKey = RRULE_KEY_MAP[k.toLowerCase()] || k.toUpperCase(); - return `${standardKey}=${v}`; + return `${standardKey}=${formatRRuleValue(v)}`; }) .join(";"); } else { diff --git a/icalendar_test.ts b/icalendar_test.ts index 1d5618f..3927868 100644 --- a/icalendar_test.ts +++ b/icalendar_test.ts @@ -207,7 +207,7 @@ Deno.test("expandRecurrences - object rrule (Reproduction of missing events)", ( }); -Deno.test("expandRecurrences - object rrule with until (Reproduction)", () => { +Deno.test("expandRecurrences - object rrule with until", () => { const now = new Date(); const start = new Date(now.getTime() - 10 * 86400000); const startStr = localDateString(start); @@ -216,25 +216,12 @@ Deno.test("expandRecurrences - object rrule with until (Reproduction)", () => { const icsEvent = { summary: "Object RRULE UNTIL Event", start: startStr, - rrule: { frequency: "DAILY", until: { date: untilDate } } // Common ts-ics structure + rrule: { frequency: "DAILY", until: { date: untilDate } } }; - // Spy on console.error - let errorLogged = false; - const originalConsoleError = console.error; - console.error = (...args) => { - if (args[0].includes("Error expanding recurrence for Object RRULE UNTIL Event") && - args[1].message.includes("Invalid UNTIL value")) { - errorLogged = true; - } - }; - - try { - expandRecurrences(icsEvent, 30); - } finally { - console.error = originalConsoleError; - } - - assert(errorLogged, "Should have logged an error for invalid UNTIL object value"); + const results = expandRecurrences(icsEvent, 30); + // Should now return multiple occurrences + assert(results.length > 1, `Expected > 1 occurrences, got ${results.length}`); + assertEquals(results[0].recurrent, true); });