ethioholiday
Version:
A comprehensive Ethiopian holidays calculator that works with both Ethiopian and Gregorian calendar systems
164 lines (163 loc) • 6.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getEthiopianHolidays = getEthiopianHolidays;
exports.getHolidaysForGregorianYear = getHolidaysForGregorianYear;
const ethiopian_calendar_new_1 = require("ethiopian-calendar-new");
// Fixed Ethiopian holidays (month/day in Ethiopian calendar)
const FIXED_ETHIOPIAN_HOLIDAYS = [
{ name: 'Enkutatash (New Year)', month: 1, day: 1, isPublicHoliday: true },
{ name: 'Meskel (Finding of the True Cross)', month: 1, day: 17, isPublicHoliday: true },
{ name: 'Genna (Ethiopian Christmas)', month: 4, day: 29, isPublicHoliday: true },
{ name: 'Timket (Epiphany)', month: 5, day: 11, isPublicHoliday: true },
{ name: 'Victory of Adwa', month: 6, day: 23, isPublicHoliday: true },
{ name: "Patriots' Victory Day", month: 8, day: 27, isPublicHoliday: true },
{ name: 'Downfall of the Derg', month: 9, day: 20, isPublicHoliday: true },
{ name: 'National Day', month: 10, day: 20, isPublicHoliday: true },
];
// Islamic holidays (approximate - should be calculated properly in production)
const ISLAMIC_HOLIDAYS = [
{ name: 'Eid al-Fitr', isPublicHoliday: true },
{ name: 'Eid al-Adha', isPublicHoliday: true },
];
/**
* Calculate Ethiopian Orthodox Easter (Fasika) in Ethiopian calendar
* using the Gauss algorithm adapted for Ethiopian calendar.
*/
function calculateFasika(ethiopianYear) {
// Algorithm adapted from:
// https://en.wikipedia.org/wiki/Computus#Gauss's_Easter_algorithm
const a = ethiopianYear % 4;
const b = ethiopianYear % 7;
const c = ethiopianYear % 19;
const d = (19 * c + 15) % 30;
const e = (2 * a + 4 * b + 6 * d + 6) % 7;
const f = d + e + 13;
let month;
let day;
if (f <= 30) {
month = 8; // Miyazya (April-May)
day = f;
}
else {
month = 9; // Ginbot (May-June)
day = f - 30;
}
// Adjust for the Ethiopian calendar offset
return { year: ethiopianYear, month, day };
}
/**
* Calculate Islamic holidays (approximate - replace with proper Hijri calculations)
*/
function calculateIslamicHolidays(gregorianYear) {
// Note: These are approximations! In a real application, you should:
// 1. Use a proper Hijri-Gregorian conversion library
// 2. Get the dates from an authoritative Islamic calendar source
// Approximate calculations (may be off by ±1 day)
const eidAlFitr = {
year: gregorianYear,
month: 5, // May
day: Math.floor(gregorianYear * 0.03 + 10) % 28 + 1
};
const eidAlAdha = {
year: gregorianYear,
month: 7, // July
day: Math.floor(gregorianYear * 0.03 + 20) % 28 + 1
};
return [
{
name: 'Eid al-Fitr',
gregorianDate: eidAlFitr,
ethiopianDate: (0, ethiopian_calendar_new_1.toEthiopian)(eidAlFitr.year, eidAlFitr.month, eidAlFitr.day),
isPublicHoliday: true
},
{
name: 'Eid al-Adha',
gregorianDate: eidAlAdha,
ethiopianDate: (0, ethiopian_calendar_new_1.toEthiopian)(eidAlAdha.year, eidAlAdha.month, eidAlAdha.day),
isPublicHoliday: true
}
];
}
/**
* Generate all holidays for a given Ethiopian year
*/
function getEthiopianHolidays(ethiopianYear) {
const holidays = [];
// 1. Add fixed Ethiopian holidays
FIXED_ETHIOPIAN_HOLIDAYS.forEach(({ name, month, day, isPublicHoliday }) => {
const ethDate = { year: ethiopianYear, month, day };
holidays.push({
name,
ethiopianDate: ethDate,
gregorianDate: (0, ethiopian_calendar_new_1.toGregorian)(ethDate.year, ethDate.month, ethDate.day),
isPublicHoliday
});
});
// 2. Calculate movable Christian holidays (Fasika and related)
const fasikaEth = calculateFasika(ethiopianYear);
const fasikaGreg = (0, ethiopian_calendar_new_1.toGregorian)(fasikaEth.year, fasikaEth.month, fasikaEth.day);
// Add Fasika (Easter)
holidays.push({
name: 'Fasika (Easter)',
ethiopianDate: fasikaEth,
gregorianDate: fasikaGreg,
isPublicHoliday: true
});
// Add Siklet (Good Friday) - 2 days before Fasika
const sikletEth = subtractDaysFromEthiopianDate(fasikaEth, 2);
holidays.push({
name: 'Siklet (Good Friday)',
ethiopianDate: sikletEth,
gregorianDate: (0, ethiopian_calendar_new_1.toGregorian)(sikletEth.year, sikletEth.month, sikletEth.day),
isPublicHoliday: true
});
// 3. Add Islamic holidays (approximate)
holidays.push(...calculateIslamicHolidays(fasikaGreg.year));
return holidays.sort((a, b) => a.gregorianDate.year !== b.gregorianDate.year
? a.gregorianDate.year - b.gregorianDate.year
: a.gregorianDate.month !== b.gregorianDate.month
? a.gregorianDate.month - b.gregorianDate.month
: a.gregorianDate.day - b.gregorianDate.day);
}
/**
* Helper function to subtract days from an Ethiopian date
*/
function subtractDaysFromEthiopianDate(ethDate, days) {
let jdn = ethToJDN(ethDate.year, ethDate.month, ethDate.day);
jdn -= days;
return jdnToEth(jdn);
}
// JDN conversion functions (same as in your calendar implementation)
const JD_EPOCH_OFFSET_AMETE_MIHRET = 1724220;
function ethToJDN(year, month, day) {
return JD_EPOCH_OFFSET_AMETE_MIHRET +
365 * (year - 1) +
Math.floor(year / 4) +
30 * (month - 1) +
(day - 1);
}
function jdnToEth(jdn) {
const r = jdn - JD_EPOCH_OFFSET_AMETE_MIHRET;
const year = Math.floor((r + 366) / 365.25);
const newYearJDN = ethToJDN(year, 1, 1);
const daysPassed = jdn - newYearJDN;
let month;
let day;
if (daysPassed < 30 * 12) {
month = Math.floor(daysPassed / 30) + 1;
day = (daysPassed % 30) + 1;
}
else {
month = 13;
day = daysPassed - 30 * 12 + 1;
}
return { year, month, day };
}
// Utility function to get holidays for a Gregorian year
function getHolidaysForGregorianYear(gregorianYear) {
// Convert Gregorian year to approximate Ethiopian year
const ethiopianYear = gregorianYear - 8;
const holidays = getEthiopianHolidays(ethiopianYear);
// Filter holidays that fall in the Gregorian year
return holidays.filter(h => h.gregorianDate.year === gregorianYear);
}