diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts index a49d8c8f..bbdf5567 100644 --- a/frontend/src/utils/date.ts +++ b/frontend/src/utils/date.ts @@ -20,8 +20,15 @@ export function parseDateSafe(rawValue: string | null | undefined): Date | null : [`${isoCompatible}Z`, isoCompatible, raw] for (const candidate of candidates) { - const d = new Date(candidate) - if (!Number.isNaN(d.getTime())) return d + const d = new Date(candidate) + + // 1. Check if the date is technically valid + const isValid = !Number.isNaN(d.getTime()) + + // 2. Sanity check: Ensure the year is between 1900 and 2100 + const isRealistic = isValid && d.getFullYear() > 1900 && d.getFullYear() < 2100 + + if (isRealistic) return d } } catch (error) { console.error('Date parsing failed:', error, raw) diff --git a/frontend/testing/unit/utils/date.test.ts b/frontend/testing/unit/utils/date.test.ts index 80bfe40e..fc772c55 100644 --- a/frontend/testing/unit/utils/date.test.ts +++ b/frontend/testing/unit/utils/date.test.ts @@ -96,4 +96,22 @@ import { expect(result.time).not.toBe("UNKNOWN TIME"); }); }); + }); + + describe("Issue #107: Invalid Date Handling", () => { + test("returns N/A for completely random strings", () => { + // This should fail initially because the current function + // might return 'Invalid Date' or crash instead of 'N/A' + expect(formatLocaleDate("not-a-date")).toBe("N/A"); + }); + + test("returns N/A for impossible calendar dates", () => { + // This catches dates that JavaScript usually 'overflows' + expect(formatLocaleDate("2026-13-45")).toBe("N/A"); + }); + + test("returns N/A for numeric strings that aren't timestamps", () => { + // Prevents random 5-digit strings from being parsed as years + expect(formatLocaleDate("99999")).toBe("N/A"); + }); }); \ No newline at end of file