/** * ISO Week Calculation Utilities * * Helper functions for ISO 8601 week calculations * Week starts on Monday and ends on Sunday */ /** * Get the Monday of the ISO week for a given date */ export function getWeekStart(date: Date): Date { const d = new Date(date); const day = d.getDay(); const diff = d.getDate() - day + (day === 0 ? -6 : 1); d.setDate(diff); d.setHours(0, 0, 0, 0); return d; } /** * Get the Sunday of the ISO week for a given date */ export function getWeekEnd(date: Date): Date { const monday = getWeekStart(date); const sunday = new Date(monday); sunday.setDate(sunday.getDate() + 6); sunday.setHours(23, 59, 59, 999); return sunday; } /** * Get ISO week number (1-53) */ export function getISOWeek(date: Date): number { const d = new Date( Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()), ); const dayNum = d.getUTCDay() || 7; d.setUTCDate(d.getUTCDate() + 4 - dayNum); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7); } /** * Format date as YYYY-MM-DD */ export function formatDate(date: Date): string { return date.toISOString().split("T")[0]; } /** * Get all weeks in a date range */ export function getWeeksInRange( startDate: string, endDate: string, ): Array<{ weekStart: string; weekEnd: string; weekNumber: number; }> { const weeks: Array<{ weekStart: string; weekEnd: string; weekNumber: number; }> = []; const start = new Date(startDate); const end = new Date(endDate); const current = getWeekStart(start); while (current <= end) { const weekStart = getWeekStart(current); const weekEnd = getWeekEnd(current); weeks.push({ weekStart: formatDate(weekStart), weekEnd: formatDate(weekEnd), weekNumber: getISOWeek(current), }); current.setDate(current.getDate() + 7); } return weeks; } /** * Test ISO week calculations */ export function testISOWeekCalculations(): void { console.log("ISO Week Calculation Tests\n"); const testDates = [ { date: "2024-01-01", expected: { monday: "2024-01-01", sunday: "2024-01-07", week: 1 }, }, { date: "2024-01-02", expected: { monday: "2024-01-01", sunday: "2024-01-07", week: 1 }, }, { date: "2024-01-07", expected: { monday: "2024-01-01", sunday: "2024-01-07", week: 1 }, }, { date: "2024-01-08", expected: { monday: "2024-01-08", sunday: "2024-01-14", week: 2 }, }, { date: "2024-12-31", expected: { monday: "2024-12-30", sunday: "2025-01-05", week: 1 }, }, // Week 1 of 2025 ]; testDates.forEach(({ date, expected }) => { const d = new Date(date); const monday = formatDate(getWeekStart(d)); const sunday = formatDate(getWeekEnd(d)); const week = getISOWeek(d); const mondayMatch = monday === expected.monday; const sundayMatch = sunday === expected.sunday; const weekMatch = week === expected.week; console.log(`Date: ${date}`); console.log( ` Monday: ${monday} ${mondayMatch ? "✓" : "✗ (expected: " + expected.monday + ")"}`, ); console.log( ` Sunday: ${sunday} ${sundayMatch ? "✓" : "✗ (expected: " + expected.sunday + ")"}`, ); console.log( ` Week: ${week} ${weekMatch ? "✓" : "✗ (expected: " + expected.week + ")"}`, ); console.log(); }); } // Run tests if executed directly if (typeof require !== "undefined" && require.main === module) { testISOWeekCalculations(); } export default { getWeekStart, getWeekEnd, getISOWeek, formatDate, getWeeksInRange, testISOWeekCalculations, };