/** Indian financial year (April to March) helpers. Invoice dates are plain YYYY-MM-DD calendar dates, so they * are read from the string; only "now" needs a time zone, and that is always IST (UTC+05:30). */ const ISO = /^(\d{4})-(\d{2})-(\d{2})$/; const IST_OFFSET_MS = (5 * 60 + 30) * 60_000; /** Months in financial-year order, for the month filter. */ export const FY_MONTHS: { month: number; label: string }[] = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3].map((month) => ({ month, label: new Date(2000, month - 1, 1).toLocaleDateString("en-GB", { month: "long" }), })); /** Month 1-12 of an ISO date, or null when it is not one. */ export function monthOf(iso: string): number | null { const m = ISO.exec(iso); if (!m) return null; const month = Number(m[2]); return month >= 1 && month <= 12 ? month : null; } /** The calendar year in which the financial year containing `iso` starts (2026-03-31 -> 2025, 2026-04-01 -> 2026). */ export function fyStartYear(iso: string): number | null { const m = ISO.exec(iso); const month = monthOf(iso); if (!m || month === null) return null; const year = Number(m[1]); return month >= 4 ? year : year - 1; } /** 2025 -> "FY 2025-26". */ export function fyLabel(startYear: number): string { return `FY ${startYear}-${String((startYear + 1) % 100).padStart(2, "0")}`; } /** First and last day of a financial year. */ export function fyRange(startYear: number): { from: string; to: string } { return { from: `${startYear}-04-01`, to: `${startYear + 1}-03-31` }; } /** Today's date in IST as YYYY-MM-DD. */ export function todayIst(now: Date = new Date()): string { return new Date(now.getTime() + IST_OFFSET_MS).toISOString().slice(0, 10); } /** The financial year that `now` falls in, in IST. */ export function currentFyStartYear(now: Date = new Date()): number { return fyStartYear(todayIst(now)) as number; }