Skip to content

Instantly share code, notes, and snippets.

@sicet7
Last active October 14, 2025 14:14
Show Gist options
  • Select an option

  • Save sicet7/0490d68fbeafce7e8b4ea681d6b08770 to your computer and use it in GitHub Desktop.

Select an option

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)
/**
* 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