/** * Centralized date-string utilities. * * All date values in the app use the 'YYYY-MM-DD' (wall-clock) format. * These helpers are the single source of truth for formatting and * arithmetic on that format, replacing ad-hoc inline code that was * duplicated across organize.js, recur.js, useCalendar.js, and ical-io.js. */ /** Pad a number to 2 digits with leading zero. */ export function pad2(n) { return String(n).padStart(2, '0') } /** Convert a JS Date to 'YYYY-MM-DD' (local wall-clock). */ export function toISODate(date) { return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}` } /** Parse 'YYYY-MM-DD' into { year, month, day } (month is 1-based). */ export function parseISODate(s) { const [y, m, d] = s.split('-').map(Number) return { year: y, month: m, day: d } } /** Build a local JS Date at midnight from 'YYYY-MM-DD'. */ export function toDate(isoDate) { return new Date(isoDate + 'T00:00:00') } /** Add `days` days to an ISO date string, return new ISO string. */ export function addDays(isoDate, days) { const d = toDate(isoDate) d.setDate(d.getDate() + days) return toISODate(d) } /** Whole-day difference between two ISO date strings (b - a). */ export function daysBetween(isoA, isoB) { return Math.round((toDate(isoB) - toDate(isoA)) / (24 * 3600 * 1000)) } /** Today's date as 'YYYY-MM-DD' (local). */ export function todayISO() { return toISODate(new Date()) } /** * Current UTC timestamp in compact RFC 5545 form (e.g. '20260711T085008Z'). * Used for DTSTAMP on new events. */ export function nowCompactTimestamp() { return new Date().toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z' } /** Format a JS Date's time as 'HH:MM'. */ export function toHHMM(date) { return `${pad2(date.getHours())}:${pad2(date.getMinutes())}` }