My-Weekly-ToDo-List/src/lib/holidays.ts
mARTin 798bcfe44a feat: Add Google Tasks, Apple Reminders, task import/sync, holidays, and UI enhancements
- Add Google Tasks integration and Apple Reminders support
- Add task import/export with list management APIs
- Add goal API for weekly goals
- Add German holidays library
- Add ImportListModal component
- Enhance WeeklyView with major UI improvements
- Enhance CalendarSettings with new connection options
- Add external task fields to database schema
- Add Playwright test suites for auth and tasks
- Add iCloud reminders Python scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:56:14 +01:00

91 lines
3.2 KiB
TypeScript

/**
* Holiday detection service to provide hints for upcoming celebrations.
*/
interface Holiday {
name: string;
month: number; // 0-indexed (0 = Jan, 11 = Dec)
day: number;
description: string;
}
// Fixed-date holidays
const FIXED_HOLIDAYS: Holiday[] = [
{ name: 'New Year\'s Day', month: 0, day: 1, description: 'Happy New Year!' },
{ name: 'Valentine\'s Day', month: 1, day: 14, description: 'Love is in the air!' },
{ name: 'Halloween', month: 9, day: 31, description: 'Trick or treat!' },
{ name: 'Armistice Day', month: 10, day: 11, description: 'Lest we forget.' }, // Remembrance Day
{ name: 'Christmas Eve', month: 11, day: 24, description: 'Twas the night before Christmas...' },
{ name: 'Christmas Day', month: 11, day: 25, description: 'Merry Christmas!' },
{ name: 'Boxing Day', month: 11, day: 26, description: 'Happy Boxing Day!' },
{ name: 'New Year\'s Eve', month: 11, day: 31, description: 'Ring in the New Year!' },
];
/**
* Calculates Easter Sunday for a given year using the Meeus/Jones/Butcher algorithm.
*/
function getEasterSunday(year: number): Date {
const a = year % 19;
const b = Math.floor(year / 100);
const c = year % 100;
const d = Math.floor(b / 4);
const e = b % 4;
const f = Math.floor((b + 8) / 25);
const g = Math.floor((b - f + 1) / 3);
const h = (19 * a + b - d - g + 15) % 30;
const i = Math.floor(c / 4);
const k = c % 4;
const l = (32 + 2 * e + 2 * i - h - k) % 7;
const m = Math.floor((a + 11 * h + 22 * l) / 451);
const month = Math.floor((h + l - 7 * m + 114) / 31);
const day = ((h + l - 7 * m + 114) % 31) + 1;
return new Date(year, month - 1, day);
}
/**
* Returns a hint if there is a major holiday or celebration in the week starting from weekStart.
* A "week" is defined as 7 days from weekStart.
*/
export function getHolidayHint(weekStart: Date): string | null {
const weekEnd = new Date(weekStart);
weekEnd.setDate(weekEnd.getDate() + 7);
const year = weekStart.getFullYear();
// Check fixed holidays
for (const holiday of FIXED_HOLIDAYS) {
// Handle year boundaries for fixed holidays (e.g. looking at Jan 1 from Dec 28)
const yearsToCheck = [year, year + 1];
for (const y of yearsToCheck) {
const holidayDate = new Date(y, holiday.month, holiday.day);
if (holidayDate >= weekStart && holidayDate < weekEnd) {
return `Hint: ${holiday.name} is coming up! ${holiday.description}`;
}
}
}
// Check variable holidays (Easter related)
const easter = getEasterSunday(year);
// Easter Sunday
if (easter >= weekStart && easter < weekEnd) {
return "Hint: Easter Sunday is this week! Happy Easter!";
}
// Good Friday (2 days before)
const goodFriday = new Date(easter);
goodFriday.setDate(goodFriday.getDate() - 2);
if (goodFriday >= weekStart && goodFriday < weekEnd) {
return "Hint: Good Friday is this week.";
}
// Easter Monday (1 day after)
const easterMonday = new Date(easter);
easterMonday.setDate(easterMonday.getDate() + 1);
if (easterMonday >= weekStart && easterMonday < weekEnd) {
return "Hint: Easter Monday is this week.";
}
return null;
}