Last active
October 14, 2025 14:14
-
-
Save sicet7/0490d68fbeafce7e8b4ea681d6b08770 to your computer and use it in GitHub Desktop.
Check if a given JavaScript Date is a Danish public holiday, (converted via. ChatGPT from PHP)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Check if a given JavaScript Date is a Danish public holiday, | |
| * using the same rules and Easter algorithm as in the provided PHP. | |
| * - No external libraries | |
| * - Works in the browser | |
| * - Uses Europe/Copenhagen civil date for comparisons | |
| * | |
| * @param {Date} date A JavaScript Date (any timezone) | |
| * @returns {boolean} true if the Copenhagen date is a holiday | |
| */ | |
| function getDanishHoliday(date) { | |
| const TZ = "Europe/Copenhagen"; | |
| // ----- helpers: tz-aware Y/M/D for any Date ----- | |
| function ymdInTZ(d, tz) { | |
| const parts = new Intl.DateTimeFormat("en-CA", { | |
| timeZone: tz, | |
| year: "numeric", | |
| month: "numeric", | |
| day: "numeric", | |
| }).formatToParts(d); | |
| const get = (type) => parseInt(parts.find(p => p.type === type).value, 10); | |
| return { y: get("year"), m: get("month"), d: get("day") }; | |
| } | |
| const inputYMD = ymdInTZ(date, TZ); | |
| const year = inputYMD.y; | |
| // ----- helpers: work with civil dates via UTC to avoid DST issues ----- | |
| function toUTCDate({ y, m, d }) { | |
| return new Date(Date.UTC(y, m - 1, d)); | |
| } | |
| function fromUTCDate(utcDate) { | |
| return { y: utcDate.getUTCFullYear(), m: utcDate.getUTCMonth() + 1, d: utcDate.getUTCDate() }; | |
| } | |
| function addDaysYMD(ymd, deltaDays) { | |
| const ms = toUTCDate(ymd).getTime() + deltaDays * 86400000; | |
| return fromUTCDate(new Date(ms)); | |
| } | |
| const fmt = (ymd) => `${ymd.y}-${ymd.m}-${ymd.d}`; // PHP-like Y-n-j (no leading zeros) | |
| // ----- Easter Sunday ----- | |
| function easterSundayYMD(T) { | |
| const a = T % 19; | |
| const b = T % 4; | |
| const c = T % 7; | |
| const k = Math.floor(T / 100); | |
| const p = Math.floor((13 + 8 * k) / 25); | |
| const q = Math.floor(k / 4); | |
| const M = (15 - p + k - q) % 30; | |
| const N = (4 + k - q) % 7; | |
| const d = (19 * a + M) % 30; | |
| const e = (2 * b + 4 * c + 6 * d + N) % 7; | |
| let day, month; | |
| if (d === 29 && e === 6) { | |
| // April 19 | |
| day = 19; month = 4; | |
| } else if (d === 28 && e === 6 && a > 10) { | |
| // April 18 | |
| day = 18; month = 4; | |
| } else { | |
| // Standard calc | |
| day = 22 + d + e; | |
| month = 3; // March | |
| if (day > 31) { | |
| day = d + e - 9; | |
| month = 4; // April | |
| } | |
| } | |
| return { y: T, m: month, d: day }; | |
| } | |
| // ----- Holidays for the computed year ----- | |
| const easter = easterSundayYMD(year); | |
| const holidays = {}; | |
| const newYearsDay = fmt({ y: year, m: 1, d: 1 }); // New Year's Day | |
| const palmSunday = fmt(addDaysYMD(easter, -7)); // Palm Sunday | |
| const maundyThursday = fmt(addDaysYMD(easter, -3)); // Maundy Thursday | |
| const goodFriday = fmt(addDaysYMD(easter, -2)); // Good Friday | |
| const easterSunday = fmt(easter); // Easter Sunday | |
| const secondEasterDay = fmt(addDaysYMD(easter, 1)); // Second Easter Day (Easter Monday) | |
| const christsAscensionDay = fmt(addDaysYMD(easter, 39)); //Christ's Ascension Day | |
| const pentecost = fmt(addDaysYMD(easter, 49)); // Pentecost (Whit Sunday) | |
| const secondPentecostDay = fmt(addDaysYMD(easter, 50)); // Second Pentecost Day (Whit Monday) | |
| const christmasDay = fmt({ y: year, m: 12, d: 25 }); // Christmas Day | |
| const secondChristmasDay = fmt({ y: year, m: 12, d: 26 }); // Second Christmas Day | |
| holidays[newYearsDay] = "Nytårsdag"; | |
| holidays[palmSunday] = "Palmesøndag"; | |
| holidays[maundyThursday] = "Skærtorsdag"; | |
| holidays[goodFriday] = "Langfredag"; | |
| holidays[easterSunday] = "Påskedag"; | |
| holidays[easterSunday] = "Påskedag"; | |
| holidays[secondEasterDay] = "Anden Påskedag"; | |
| holidays[christsAscensionDay] = "Kristi himmelfartsdag"; | |
| holidays[pentecost] = "Pinsedag"; | |
| holidays[secondPentecostDay] = "Anden Pinsedag"; | |
| holidays[christmasDay] = "Juledag"; | |
| holidays[secondChristmasDay] = "Anden Juledag"; | |
| return holidays[fmt(inputYMD)] ?? null; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment