UNPKG

kenya-holidays

Version:

A simple package to retrieve all Kenyan public holidays for a given year

238 lines (212 loc) 8.78 kB
// File: index.js /** * Kenya Public Holidays * A simple package to get all Kenyan public holidays for a given year */ /** * Calculate Easter Sunday date for a given year * Based on Butcher's algorithm * @param {number} year - The year to calculate Easter for * @return {Date} - Easter Sunday Date object */ function calculateEaster(year) { // Use Meeus/Jones/Butcher algorithm 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) - 1; // 0-based month const day = ((h + l - 7 * m + 114) % 31) + 1; return new Date(year, month, day); } /** * Get Good Friday date (two days before Easter Sunday) * @param {number} year - The year to calculate for * @return {Date} - Good Friday Date object */ function getGoodFriday(year) { const easter = calculateEaster(year); const goodFriday = new Date(easter); goodFriday.setDate(easter.getDate() - 2); return goodFriday; } /** * Format a date in YYYY-MM-DD format * @param {Date} date - The date to format * @return {string} - Formatted date string */ function formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } /** * Get all Kenyan public holidays for a given year * @param {number} [year=null] - The year to get holidays for (defaults to current year) * @param {boolean} [formatted=false] - Whether to return formatted dates (YYYY-MM-DD) * @return {Object} - Object containing holiday names and their dates */ function getKenyanHolidays(year = null, formatted = false) { // Use current year if not specified const targetYear = year || new Date().getFullYear(); // Calculate Easter-dependent dates const easterSunday = calculateEaster(targetYear); const goodFriday = getGoodFriday(targetYear); const easterMonday = new Date(easterSunday); easterMonday.setDate(easterSunday.getDate() + 1); // Define fixed holidays const holidays = { "New Year's Day": new Date(targetYear, 0, 1), // January 1 "Good Friday": goodFriday, "Easter Monday": easterMonday, "Labour Day": new Date(targetYear, 4, 1), // May 1 "Madaraka Day": new Date(targetYear, 5, 1), // June 1 "Huduma Day": new Date(targetYear, 9, 10), // October 10 "Mashujaa Day": new Date(targetYear, 9, 20), // October 20 "Jamhuri Day": new Date(targetYear, 11, 12), // December 12 "Christmas Day": new Date(targetYear, 11, 25), // December 25 "Boxing Day": new Date(targetYear, 11, 26), // December 26 "Utamaduni Day": new Date(targetYear, 11, 27), // December 27 }; // Note: Eid holidays are not included as they require Islamic lunar calendar calculations // Consider adding a note or placeholder for these holidays["Eid al-Fitr*"] = "Variable date based on Islamic calendar"; holidays["Eid al-Adha*"] = "Variable date based on Islamic calendar"; holidays["Diwali*"] = "Variable date (sometimes declared a public holiday)"; // Format dates if requested if (formatted) { const formattedHolidays = {}; for (const [name, date] of Object.entries(holidays)) { if (date instanceof Date) { formattedHolidays[name] = formatDate(date); } else { formattedHolidays[name] = date; // Keep as is for variable dates } } return formattedHolidays; } return holidays; } /** * Get Kenyan holidays in a more detailed format with additional information * @param {number} [year=null] - The year to get holidays for (defaults to current year) * @return {Array} - Array of holiday objects with date, name, and type */ function getDetailedKenyanHolidays(year = null) { const targetYear = year || new Date().getFullYear(); const basicHolidays = getKenyanHolidays(targetYear); const detailedHolidays = []; // Define holiday types const holidayTypes = { "New Year's Day": "National", "Good Friday": "Religious", "Easter Monday": "Religious", "Labour Day": "National", "Madaraka Day": "National", "Huduma Day": "National", "Mashujaa Day": "National", "Jamhuri Day": "National", "Christmas Day": "Religious", "Boxing Day": "National", "Utamaduni Day": "National", "Eid al-Fitr*": "Religious", "Eid al-Adha*": "Religious", "Diwali*": "Religious" }; // Add descriptions const descriptions = { "New Year's Day": "Celebrates the start of the new year", "Good Friday": "Commemorates the crucifixion of Jesus Christ", "Easter Monday": "Celebrates the resurrection of Jesus Christ", "Labour Day": "Honors the contributions of workers", "Madaraka Day": "Commemorates Kenya gaining internal self-rule in 1963", "Huduma Day": "Celebrates public service and national unity", "Mashujaa Day": "Honors all Kenyans who contributed to the independence struggle", "Jamhuri Day": "Celebrates Kenya's independence from Britain in 1963", "Christmas Day": "Celebrates the birth of Jesus Christ", "Boxing Day": "Traditional day of giving to the less fortunate", "Utamaduni Day": "Celebrates Kenya's cultural heritage", "Eid al-Fitr*": "Marks the end of Ramadan, the Islamic holy month of fasting", "Eid al-Adha*": "Commemorates Ibrahim's willingness to sacrifice his son", "Diwali*": "Hindu festival of lights" }; for (const [name, date] of Object.entries(basicHolidays)) { detailedHolidays.push({ name: name, date: date instanceof Date ? formatDate(date) : date, type: holidayTypes[name] || "Other", description: descriptions[name] || "", isVariable: !(date instanceof Date) }); } // Sort by date (putting variable dates at the end) return detailedHolidays.sort((a, b) => { if (a.isVariable && !b.isVariable) return 1; if (!a.isVariable && b.isVariable) return -1; if (a.isVariable && b.isVariable) return 0; return new Date(a.date) - new Date(b.date); }); } /** * Check if a specific date is a Kenyan public holiday * @param {Date|string} date - The date to check (Date object or YYYY-MM-DD string) * @param {number} [year=null] - Optional year to use for holiday calculation (defaults to year of provided date) * @return {Object|null} - Holiday information if it's a holiday, null otherwise */ function isKenyanHoliday(date, year = null) { // Convert string date to Date object if needed let dateObj; if (typeof date === 'string') { dateObj = new Date(date); } else if (date instanceof Date) { dateObj = new Date(date); } else { throw new Error('Date must be a Date object or a YYYY-MM-DD string'); } // Use year from date if not specified const targetYear = year || dateObj.getFullYear(); // Get all holidays for the target year const holidays = getKenyanHolidays(targetYear); // Format the input date for comparison (strip time component) const formattedDate = new Date( dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate() ); // Check if the date matches any holiday for (const [name, holidayDate] of Object.entries(holidays)) { if (holidayDate instanceof Date) { const formattedHolidayDate = new Date( holidayDate.getFullYear(), holidayDate.getMonth(), holidayDate.getDate() ); if (formattedDate.getTime() === formattedHolidayDate.getTime()) { // Get the detailed info for this holiday const detailedHolidays = getDetailedKenyanHolidays(targetYear); const holidayInfo = detailedHolidays.find(h => h.name === name); return { name, date: formatDate(holidayDate), type: holidayInfo ? holidayInfo.type : null, description: holidayInfo ? holidayInfo.description : null }; } } } return null; } module.exports = { getKenyanHolidays, getDetailedKenyanHolidays, isKenyanHoliday };