fix(tasks): refuse a cycle start that is not a real date
A corrupt import is stored as it came, and "2026-13-01" passed the pattern, then threw in periodOf on every render. "2026-02-30" rolled into March instead and moved the cycle. The schema now round-trips the date, so either is kept on disk and left off screen like any unreadable task. Found by the schema-guardian review. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2477b0a8a7
commit
8d0b45f83a
+12
-1
@@ -17,7 +17,18 @@ import { DAY } from "./time.ts";
|
||||
/** ISO weekday: Monday is 1, Sunday is 7. */
|
||||
export const WeekdaySchema = z.number().int().min(1).max(7);
|
||||
|
||||
const DayKey = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
||||
/**
|
||||
* A real calendar date. The round trip refuses "2026-13-01", which would throw
|
||||
* in `periodOf`, and "2026-02-30", which would roll into March and move the
|
||||
* cycle — a corrupt import is stored verbatim, so the schema is the guard.
|
||||
*/
|
||||
const DayKey = z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
||||
.refine((s) => {
|
||||
const ms = Date.parse(`${s}T00:00:00Z`);
|
||||
return Number.isFinite(ms) && new Date(ms).toISOString().slice(0, 10) === s;
|
||||
});
|
||||
|
||||
export const PeriodSchema = z.union([
|
||||
z.object({ unit: z.literal("week"), startsOn: WeekdaySchema }),
|
||||
|
||||
Reference in New Issue
Block a user