export function isValidIso(iso: string): boolean { if (!/^\d{4}-\d{2}-\d{2}$/.test(iso)) return false const [y, m, d] = iso.split('-').map(Number) const date = new Date(y, m - 1, d) return date.getFullYear() === y && date.getMonth() === m - 1 && date.getDate() === d } export function formatIsoToDisplay(iso: string | null): string { if (!iso || !isValidIso(iso)) return '' const [y, m, d] = iso.split('-') return `${d}/${m}/${y}` } export function parseDisplayToIso(display: string): string | null { const match = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(display.trim()) if (!match) return null const [, dd, mm, yyyy] = match const iso = `${yyyy}-${mm}-${dd}` return isValidIso(iso) ? iso : null } export function isDateInRange(iso: string, min?: string, max?: string): boolean { if (min && iso < min) return false if (max && iso > max) return false return true } export function isMonthInRange(year: number, month: number, min?: string, max?: string): boolean { const ym = `${year}-${String(month + 1).padStart(2, '0')}` if (min && ym < min.slice(0, 7)) return false if (max && ym > max.slice(0, 7)) return false return true } export function isYearInRange(year: number, min?: string, max?: string): boolean { if (min && year < Number(min.slice(0, 4))) return false if (max && year > Number(max.slice(0, 4))) return false return true }