kenat
Version:
A JavaScript library for the Ethiopian calendar with date and time support.
2 lines • 102 kB
JavaScript
var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:true});var _KenatError=class _KenatError extends Error{constructor(message){super(message);this.name=this.constructor.name}toJSON(){return{type:this.name,message:this.message}}};__name(_KenatError,"KenatError");var KenatError=_KenatError;var _InvalidEthiopianDateError=class _InvalidEthiopianDateError extends KenatError{constructor(year,month,day){super(`Invalid Ethiopian date: ${year}/${month}/${day}`);this.date={year,month,day}}toJSON(){return{...super.toJSON(),date:this.date,validRange:{month:"1\u201313",day:"1\u201330 (or 5/6 for the 13th month)"}}}};__name(_InvalidEthiopianDateError,"InvalidEthiopianDateError");var InvalidEthiopianDateError=_InvalidEthiopianDateError;var _InvalidGregorianDateError=class _InvalidGregorianDateError extends KenatError{constructor(year,month,day){super(`Invalid Gregorian date: ${year}/${month}/${day}`);this.date={year,month,day}}toJSON(){return{...super.toJSON(),date:this.date,validRange:{month:"1\u201312",day:"1\u201331 (depending on month)"}}}};__name(_InvalidGregorianDateError,"InvalidGregorianDateError");var InvalidGregorianDateError=_InvalidGregorianDateError;var _InvalidDateFormatError=class _InvalidDateFormatError extends KenatError{constructor(inputString){super(`Invalid date string format: "${inputString}". Expected 'yyyy/mm/dd' or 'yyyy-mm-dd'.`);this.inputString=inputString}toJSON(){return{...super.toJSON(),inputString:this.inputString}}};__name(_InvalidDateFormatError,"InvalidDateFormatError");var InvalidDateFormatError=_InvalidDateFormatError;var _UnrecognizedInputError=class _UnrecognizedInputError extends KenatError{constructor(input){const inputType=typeof input;super(`Unrecognized input type for Kenat constructor: ${inputType}`);this.input=input}toJSON(){return{...super.toJSON(),inputType:typeof this.input}}};__name(_UnrecognizedInputError,"UnrecognizedInputError");var UnrecognizedInputError=_UnrecognizedInputError;var _GeezConverterError=class _GeezConverterError extends KenatError{constructor(message){super(message)}};__name(_GeezConverterError,"GeezConverterError");var GeezConverterError=_GeezConverterError;var _InvalidInputTypeError=class _InvalidInputTypeError extends KenatError{constructor(functionName,parameterName,expectedType,receivedValue){const receivedType=typeof receivedValue;super(`Invalid type for parameter '${parameterName}' in function '${functionName}'. Expected '${expectedType}' but got '${receivedType}'.`);this.functionName=functionName;this.parameterName=parameterName;this.expectedType=expectedType;this.receivedValue=receivedValue}toJSON(){return{...super.toJSON(),functionName:this.functionName,parameterName:this.parameterName,expectedType:this.expectedType,receivedType:typeof this.receivedValue}}};__name(_InvalidInputTypeError,"InvalidInputTypeError");var InvalidInputTypeError=_InvalidInputTypeError;var _InvalidTimeError=class _InvalidTimeError extends KenatError{constructor(message){super(message)}};__name(_InvalidTimeError,"InvalidTimeError");var InvalidTimeError=_InvalidTimeError;var _InvalidGridConfigError=class _InvalidGridConfigError extends KenatError{constructor(message){super(message)}};__name(_InvalidGridConfigError,"InvalidGridConfigError");var InvalidGridConfigError=_InvalidGridConfigError;var _UnknownHolidayError=class _UnknownHolidayError extends KenatError{constructor(holidayKey){super(`Unknown movable holiday key: "${holidayKey}"`);this.holidayKey=holidayKey}toJSON(){return{...super.toJSON(),holidayKey:this.holidayKey}}};__name(_UnknownHolidayError,"UnknownHolidayError");var UnknownHolidayError=_UnknownHolidayError;function validateNumericInputs(funcName,dateParts){for(const[name,value]of Object.entries(dateParts)){if(typeof value!=="number"||isNaN(value)){throw new InvalidInputTypeError(funcName,name,"number",value)}}}__name(validateNumericInputs,"validateNumericInputs");function validateEthiopianDateObject(dateObj,funcName,paramName){if(typeof dateObj!=="object"||dateObj===null){throw new InvalidInputTypeError(funcName,paramName,"object",dateObj)}const d=dateObj;validateNumericInputs(funcName,{[`${paramName}.year`]:d.year,[`${paramName}.month`]:d.month,[`${paramName}.day`]:d.day})}__name(validateEthiopianDateObject,"validateEthiopianDateObject");function dayOfYear(year,month,day){const monthLengths=[31,isGregorianLeapYear(year)?29:28,31,30,31,30,31,31,30,31,30,31];let doy=0;for(let i=0;i<month-1;i++){doy+=monthLengths[i]}doy+=day;return doy}__name(dayOfYear,"dayOfYear");function monthDayFromDayOfYear(year,dayOfYear2){const monthLengths=[31,isGregorianLeapYear(year)?29:28,31,30,31,30,31,31,30,31,30,31];let month=1;while(dayOfYear2>monthLengths[month-1]){dayOfYear2-=monthLengths[month-1];month++}return{month,day:dayOfYear2}}__name(monthDayFromDayOfYear,"monthDayFromDayOfYear");function isGregorianLeapYear(year){return year%4===0&&year%100!==0||year%400===0}__name(isGregorianLeapYear,"isGregorianLeapYear");function isEthiopianLeapYear(year){return year%4===3}__name(isEthiopianLeapYear,"isEthiopianLeapYear");function getEthiopianDaysInMonth(year,month){if(month===13){return isEthiopianLeapYear(year)?6:5}return 30}__name(getEthiopianDaysInMonth,"getEthiopianDaysInMonth");function getWeekday({year,month,day}){const g=toGC(year,month,day);return new Date(g.year,g.month-1,g.day).getDay()}__name(getWeekday,"getWeekday");function isValidEthiopianDate(year,month,day){if(month<1||month>13){return false}if(day<1||day>getEthiopianDaysInMonth(year,month)){return false}return true}__name(isValidEthiopianDate,"isValidEthiopianDate");function getGregorianDateOfEthiopianNewYear(ethiopianYear){validateNumericInputs("getGregorianDateOfEthiopianNewYear",{ethiopianYear});const gregorianYear=ethiopianYear+7;const newYearDay=isGregorianLeapYear(gregorianYear+1)?12:11;return{gregorianYear,month:9,day:newYearDay}}__name(getGregorianDateOfEthiopianNewYear,"getGregorianDateOfEthiopianNewYear");function toGC(ethYear,ethMonth,ethDay){validateNumericInputs("toGC",{ethYear,ethMonth,ethDay});if(ethMonth<1||ethMonth>13){throw new InvalidEthiopianDateError(ethYear,ethMonth,ethDay)}const maxDay=ethMonth===13?isEthiopianLeapYear(ethYear)?6:5:30;if(ethDay<1||ethDay>maxDay){throw new InvalidEthiopianDateError(ethYear,ethMonth,ethDay)}const newYear=getGregorianDateOfEthiopianNewYear(ethYear);const daysSinceNewYear=(ethMonth-1)*30+ethDay-1;const newYearDOY=dayOfYear(newYear.gregorianYear,newYear.month,newYear.day);let gregorianDOY=newYearDOY+daysSinceNewYear;let gregorianYear=newYear.gregorianYear;const yearLength=isGregorianLeapYear(gregorianYear)?366:365;if(gregorianDOY>yearLength){gregorianDOY-=yearLength;gregorianYear+=1}const{month,day}=monthDayFromDayOfYear(gregorianYear,gregorianDOY);return{year:gregorianYear,month,day}}__name(toGC,"toGC");function toEC(gYear,gMonth,gDay){validateNumericInputs("toEC",{gYear,gMonth,gDay});const isValidDate=__name((y,m,d)=>{const date=new Date(Date.UTC(y,m-1,d));return date.getUTCFullYear()===y&&date.getUTCMonth()===m-1&&date.getUTCDate()===d},"isValidDate");const inputDate=new Date(Date.UTC(gYear,gMonth-1,gDay));const minDate=new Date(Date.UTC(1900,0,1));const maxDate=new Date(Date.UTC(2100,11,31));if(!isValidDate(gYear,gMonth,gDay)||inputDate<minDate||inputDate>maxDate){throw new InvalidGregorianDateError(gYear,gMonth,gDay)}const oneDay=864e5;const oneYear=365*oneDay;const fourYears=1461*oneDay;const baseDate=new Date(Date.UTC(1971,8,12));const diff=inputDate.getTime()-baseDate.getTime();const fourYearCycles=Math.floor(diff/fourYears);let remainingYears=Math.floor((diff-fourYearCycles*fourYears)/oneYear);if(remainingYears===4)remainingYears=3;const remainingMonths=Math.floor((diff-fourYearCycles*fourYears-remainingYears*oneYear)/(30*oneDay));const remainingDays=Math.floor((diff-fourYearCycles*fourYears-remainingYears*oneYear-remainingMonths*30*oneDay)/oneDay);const ethYear=1964+fourYearCycles*4+remainingYears;const month=remainingMonths+1;const day=remainingDays+1;return{year:ethYear,month,day}}__name(toEC,"toEC");var islamicFormatter=new Intl.DateTimeFormat("en-TN-u-ca-islamic",{day:"numeric",month:"numeric",year:"numeric"});function getHijriYear(date){const parts=islamicFormatter.formatToParts(date);let hYear=null;parts.forEach(({type,value})=>{if(type==="year")hYear=parseInt(value,10)});return hYear}__name(getHijriYear,"getHijriYear");var hijriToGregorianCache=new Map;function hijriToGregorian(hYear,hMonth,hDay,gregorianYear){const cacheKey=`${hYear}-${hMonth}-${hDay}-${gregorianYear}`;if(hijriToGregorianCache.has(cacheKey)){return hijriToGregorianCache.get(cacheKey)??null}const baseDate=new Date(gregorianYear-1,0,1);for(let offset=0;offset<=730;offset++){const testDate=new Date(baseDate);testDate.setDate(testDate.getDate()+offset);const parts=islamicFormatter.formatToParts(testDate);const hijriParts={};parts.forEach(({type,value})=>{if(type!=="literal")hijriParts[type]=parseInt(value,10)});if(hijriParts.year===hYear&&hijriParts.month===hMonth&&hijriParts.day===hDay&&testDate.getFullYear()===gregorianYear){hijriToGregorianCache.set(cacheKey,testDate);return testDate}}hijriToGregorianCache.set(cacheKey,null);return null}__name(hijriToGregorian,"hijriToGregorian");var monthNames={english:["Meskerem","Tikimt","Hidar","Tahsas","Tir","Yekatit","Megabit","Miazia","Ginbot","Sene","Hamle","Nehase","Pagume"],amharic:["\u1218\u1235\u12A8\u1228\u121D","\u1325\u1245\u121D\u1275","\u1205\u12F3\u122D","\u1273\u1205\u1233\u1235","\u1325\u122D","\u12E8\u12AB\u1272\u1275","\u1218\u130B\u1262\u1275","\u121A\u12EB\u12DD\u12EB","\u130D\u1295\u1266\u1275","\u1230\u1294","\u1200\u121D\u120C","\u1290\u1210\u1234","\u1333\u1309\u121C"],gregorian:["January","February","March","April","May","June","July","August","September","October","November","December"]};var daysOfWeek={english:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],amharic:["\u12A5\u1211\u12F5","\u1230\u129E","\u121B\u12AD\u1230\u129E","\u1228\u1261\u12D5","\u1210\u1219\u1235","\u12D3\u122D\u1265","\u1245\u12F3\u121C"]};var HolidayTags={PUBLIC:"public",RELIGIOUS:"religious",CHRISTIAN:"christian",MUSLIM:"muslim",STATE:"state",CULTURAL:"cultural",OTHER:"other"};var keyToTewsakMap={nineveh:"NINEVEH",abiyTsome:"ABIY_TSOME",debreZeit:"DEBRE_ZEIT",hosanna:"HOSANNA",siklet:"SIKLET",fasika:"TINSAYE",rikbeKahnat:"RIKBE_KAHNAT",erget:"ERGET",paraclete:"PARACLETE",tsomeHawaryat:"TSOME_HAWARYAT",tsomeDihnet:"TSOME_DIHENET"};var holidayInfo={enkutatash:{name:{amharic:"\u12A5\u1295\u1241\u1323\u1323\u123D",english:"Ethiopian New Year (Enkutatash)"},description:{amharic:"\u12E8\u12A2\u1275\u12EE\u1335\u12EB \u12A0\u12F2\u1235 \u12D3\u1218\u1275 \u1218\u1300\u1218\u122A\u12EB\u1364 \u12E8\u12DD\u1293\u1265 \u12C8\u1245\u1275 \u121B\u1265\u1243\u1271\u1295 \u12A5\u1293 \u12F3\u130D\u121D \u1218\u1273\u12F0\u1235\u1295 \u12EB\u1218\u1208\u12AD\u1273\u120D\u1362",english:"Marks the start of the Ethiopian year; symbolizes renewal and the end of the rainy season."}},meskel:{name:{amharic:"\u1218\u1235\u1240\u120D",english:"Finding of the True Cross (Meskel)"},description:{amharic:"\u12604\u129B\u12CD \u1218\u1276 \u12AD\u134D\u1208 \u12D8\u1218\u1295 \u1260\u1295\u130D\u1225\u1275 \u12A5\u120C\u1292 \u12A0\u121B\u12AB\u129D\u1290\u1275 \u12E8\u130C\u1273\u127D\u1295 \u1218\u1235\u1240\u120D \u1218\u1308\u1298\u1271\u1295 \u12EB\u12A8\u1265\u122B\u120D\u1362",english:"Commemorates the discovery of the True Cross by Empress Helena in the 4th century."}},beherbehereseb:{name:{amharic:"\u12E8\u1265\u1214\u122D \u1265\u1214\u1228\u1230\u1266\u127D \u1240\u1295",english:"Nations, Nationalities, and Peoples' Day"},description:{amharic:"\u12E8\u12A2\u1275\u12EE\u1335\u12EB \u1265\u1214\u122D \u1265\u1214\u1228\u1230\u1266\u127D\u1295 \u120D\u12E9\u1290\u1275 \u12E8\u121A\u12EB\u12A8\u1265\u122D\u1363 \u12A5\u12A9\u120D \u1218\u1265\u1273\u1278\u12CD\u1295 \u12E8\u121A\u12EB\u1228\u130B\u130D\u1325 \u12A5\u1293 \u1260\u1263\u1205\u120D\u1293 \u124B\u1295\u124B \u12A0\u1295\u12F5\u1290\u1275\u1295 \u12E8\u121A\u12EB\u1320\u1293\u12AD\u122D \u1260\u12D3\u120D \u1290\u12CD\u1362",english:"Acknowledges and celebrates the diversity of Ethiopia's ethnic groups, affirming their equal rights and fostering unity."}},gena:{name:{amharic:"\u1308\u1293",english:"Ethiopian Christmas (Genna)"},description:{amharic:"\u12E8\u12A2\u12E8\u1231\u1235 \u12AD\u122D\u1235\u1276\u1235\u1295 \u120D\u12F0\u1275 \u12E8\u121A\u12EB\u12A8\u1265\u122D \u12E8\u12A2\u1275\u12EE\u1335\u12EB \u12A6\u122D\u1276\u12F6\u12AD\u1235 \u1270\u12CB\u1215\u12F6 \u1264\u1270 \u12AD\u122D\u1235\u1272\u12EB\u1295 \u1260\u12D3\u120D\u1362",english:"Ethiopian Orthodox Christmas celebrating the birth of Jesus Christ."}},timket:{name:{amharic:"\u1325\u121D\u1240\u1275",english:"Ethiopian Epiphany (Timket)"},description:{amharic:"\u12E8\u12A2\u12E8\u1231\u1235 \u12AD\u122D\u1235\u1276\u1235\u1295 \u1260\u12EE\u122D\u12F3\u1296\u1235 \u12C8\u1295\u12DD \u1218\u1320\u1218\u1241\u1295 \u12EB\u12A8\u1265\u122B\u120D\u1362",english:"Commemorates the baptism of Jesus in the Jordan River."}},martyrsDay:{name:{amharic:"\u12E8\u1230\u121B\u12D5\u1273\u1275 \u1240\u1295",english:"Martyrs' Day"},description:{amharic:"\u1208\u12A2\u1275\u12EE\u1335\u12EB \u1290\u1343\u1290\u1275\u1293 \u12AD\u1265\u122D \u1215\u12ED\u12C8\u1273\u1278\u12CD\u1295 \u12E8\u1220\u12C9 \u1230\u121B\u12D5\u1273\u1275\u1295 \u12EB\u1235\u1263\u120D\u1362",english:"Honors those who sacrificed their lives for Ethiopia\u2019s freedom and independence."}},adwa:{name:{amharic:"\u12E8\u12A0\u12F5\u12CB \u12F5\u120D \u1260\u12D3\u120D",english:"Victory of Adwa"},description:{amharic:"\u12601896 \u12D3.\u121D. \u12A2\u1275\u12EE\u1335\u12EB \u1260\u1323\u120A\u12EB\u1295 \u1245\u129D \u1308\u12E5\u12CE\u127D \u120B\u12ED \u12E8\u1270\u1240\u12F3\u1300\u127D\u12CD\u1295 \u12F5\u120D \u12EB\u12A8\u1265\u122B\u120D\u1362",english:"Celebrates Ethiopia\u2019s victory over Italian colonizers in 1896."}},labour:{name:{amharic:"\u12E8\u1230\u122B\u1270\u129E\u127D \u1240\u1295",english:"International Labour Day"},description:{amharic:"\u12D3\u1208\u121D \u12A0\u1240\u134D \u12E8\u1220\u122B\u1270\u129E\u127D\u1293 \u12E8\u1225\u122B \u1218\u1265\u1276\u127D \u1240\u1295 \u1290\u12CD\u1362",english:"A global celebration of workers and labor rights."}},patriots:{name:{amharic:"\u12E8\u12A0\u122D\u1260\u129E\u127D \u1240\u1295",english:"Patriots' Victory Day"},description:{amharic:"\u12E8\u1323\u120A\u12EB\u1295 \u12C8\u1228\u122B\u1295 \u12E8\u1270\u124B\u124B\u1219 \u12A2\u1275\u12EE\u1335\u12EB\u12CD\u12EB\u1295 \u12A0\u122D\u1260\u129E\u127D\u1295 \u12F5\u120D \u12EB\u1235\u1263\u120D\u1362",english:"Honors Ethiopian resistance fighters who defeated Italian occupation."}},nineveh:{name:{amharic:"\u133E\u1218 \u1290\u1290\u12CC",english:"Fast of Nineveh"},description:{amharic:"\u12E8\u1290\u1290\u12CC \u1230\u12CE\u127D \u1295\u1235\u1210 \u1218\u130D\u1263\u1273\u1278\u12CD\u1295 \u12E8\u121A\u12EB\u1235\u1273\u12CD\u1235 \u12E8\u1226\u1235\u1275 \u1240\u1295 \u133E\u121D \u1290\u12CD\u1362",english:"A three-day fast commemorating the repentance of the people of Nineveh."}},abiyTsome:{name:{amharic:"\u12D0\u1262\u12ED \u133E\u121D",english:"Great Lent"},description:{amharic:"\u12A8\u134B\u1232\u12AB \u1260\u134A\u1275 \u12E8\u121A\u133E\u121D \u12E855 \u1240\u1293\u1275 \u12E8\u133E\u121D \u12C8\u1245\u1275 \u1290\u12CD\u1362",english:"The Great Lent, a 55-day fasting period before Easter."}},debreZeit:{name:{amharic:"\u12F0\u1265\u1228 \u12D8\u12ED\u1275",english:"Mid-Lent Sunday"},description:{amharic:"\u12A2\u12E8\u1231\u1235 \u1260\u12F0\u1265\u1228 \u12D8\u12ED\u1275 \u1270\u122B\u122B \u12EB\u1235\u1270\u121B\u1228\u12CD\u1295 \u1275\u121D\u1205\u122D\u1275 \u12E8\u121A\u12EB\u1235\u1273\u12CD\u1235 \u12E8\u12D0\u1262\u12ED \u133E\u121D \u12A0\u130B\u121B\u123D \u12A5\u1211\u12F5\u1362",english:"Mid-Lent Sunday, commemorating Jesus's sermon on the Mount of Olives."}},hosanna:{name:{amharic:"\u1206\u1233\u12D5\u1293",english:"Palm Sunday"},description:{amharic:"\u12A2\u12E8\u1231\u1235 \u1260\u12AD\u1265\u122D \u12C8\u12F0 \u12A2\u12E8\u1229\u1233\u120C\u121D \u1218\u130D\u1263\u1271\u1295 \u12E8\u121A\u12EB\u1235\u1273\u12CD\u1235 \u1260\u12D3\u120D\u1362",english:"Palm Sunday, commemorating Jesus's triumphal entry into Jerusalem."}},siklet:{name:{amharic:"\u1235\u1245\u1208\u1275",english:"Good Friday"},description:{amharic:"\u12E8\u12A2\u12E8\u1231\u1235 \u12AD\u122D\u1235\u1276\u1235\u1295 \u1235\u1245\u1208\u1275 \u12E8\u121A\u12EB\u1235\u1273\u12CD\u1235 \u1290\u12CD\u1362",english:"Marks the crucifixion of Jesus Christ."}},fasika:{name:{amharic:"\u134B\u1232\u12AB",english:"Ethiopian Easter"},description:{amharic:"\u12E8\u12A2\u12E8\u1231\u1235 \u12AD\u122D\u1235\u1276\u1235\u1295 \u12A8\u1219\u1273\u1295 \u1218\u1290\u1223\u1275 \u12EB\u12A8\u1265\u122B\u120D\u1362 \u1260\u12A2\u1275\u12EE\u1335\u12EB \u12CD\u1235\u1325 \u12AB\u1209 \u12AD\u122D\u1235\u1272\u12EB\u1293\u12CA \u1260\u12D3\u120B\u1275 \u12A0\u1295\u12F1\u1293 \u12CB\u1290\u129B\u12CD \u1290\u12CD\u1362",english:"Celebrates the resurrection of Jesus Christ. One of the most important Christian holidays in Ethiopia."}},rikbeKahnat:{name:{amharic:"\u122D\u12AD\u1260 \u12AB\u1205\u1293\u1275",english:"Meeting of the Priests"},description:{amharic:"\u12A8\u134B\u1232\u12AB 24 \u1240\u1293\u1275 \u1260\u128B\u120B \u12E8\u121A\u12A8\u1260\u122D \u12E8\u12AB\u1205\u1293\u1275 \u1218\u1230\u1263\u1230\u1265 \u1260\u12D3\u120D \u1290\u12CD\u1362",english:"The Meeting of the Priests, 24 days after Easter."}},erget:{name:{amharic:"\u12D5\u122D\u1308\u1275",english:"Ascension"},description:{amharic:"\u12A8\u134B\u1232\u12AB 40 \u1240\u1293\u1275 \u1260\u128B\u120B \u12A2\u12E8\u1231\u1235 \u12C8\u12F0 \u1230\u121B\u12ED \u121B\u1228\u1309\u1295 \u12EB\u12A8\u1265\u122B\u120D\u1362",english:"The Ascension of Jesus into heaven, 40 days after Easter."}},paraclete:{name:{amharic:"\u1330\u122B\u1245\u120A\u1326\u1235",english:"Pentecost"},description:{amharic:"\u1218\u1295\u1348\u1235 \u1245\u12F1\u1235 \u1260\u1210\u12CB\u122D\u12EB\u1275 \u120B\u12ED \u1218\u12CD\u1228\u12F1\u1295 \u12E8\u121A\u12EB\u12A8\u1265\u122D \u1260\u12D3\u120D\u1363 \u12A8\u134B\u1232\u12AB 50 \u1240\u1293\u1275 \u1260\u128B\u120B\u1362",english:"Pentecost, celebrating the descent of the Holy Spirit upon the Apostles, 50 days after Easter."}},tsomeHawaryat:{name:{amharic:"\u133E\u1218 \u1210\u12CB\u122D\u12EB\u1275",english:"Apostles' Fast"},description:{amharic:"\u12A8\u1330\u122B\u1245\u120A\u1326\u1235 \u121B\u130D\u1235\u1275 \u12E8\u121A\u1300\u121D\u122D \u12E8\u1210\u12CB\u122D\u12EB\u1275 \u133E\u121D \u1290\u12CD\u1362",english:"The Fast of the Apostles, which begins the day after Pentecost."}},tsomeDihnet:{name:{amharic:"\u133E\u1218 \u12F5\u1285\u1290\u1275",english:"Fast of Salvation"},description:{amharic:"\u1260\u12E8\u1233\u121D\u1295\u1271 \u1228\u1261\u12D5 \u12A5\u1293 \u12D3\u122D\u1265 \u12E8\u121A\u133E\u121D \u12E8\u12F5\u1285\u1290\u1275 \u133E\u121D \u1290\u12CD\u1362",english:"The Fast of Salvation, observed on Wednesdays and Fridays."}},eidFitr:{name:{amharic:"\u12D2\u12F5 \u12A0\u120D \u1348\u1325\u122D",english:"Eid al-Fitr"},description:{amharic:"\u12E8\u1228\u1218\u12F3\u1295 \u133E\u121D \u12C8\u122D \u1218\u1308\u1263\u12F0\u12F5\u1295 \u12E8\u121A\u12EB\u1218\u1208\u12AD\u1275 \u1260\u12D3\u120D\u1362",english:"Marks the end of Ramadan, the month of fasting for Muslims."}},eidAdha:{name:{amharic:"\u12D2\u12F5 \u12A0\u120D \u12A0\u12F5\u1210",english:"Eid al-Adha"},description:{amharic:"\u12A0\u1265\u122D\u1203\u121D \u1208\u12A5\u130D\u12DA\u12A0\u1265\u1214\u122D \u1260\u1218\u1273\u12D8\u12DD \u120D\u1301\u1295 \u1208\u1218\u1220\u12CB\u1275 \u1348\u1243\u12F0\u129D\u1290\u1271\u1295 \u12E8\u121A\u12EB\u1235\u1273\u12CD\u1235 \u1260\u12D3\u120D\u1362",english:"Commemorates Abraham\u2019s willingness to sacrifice his son as an act of obedience to God."}},moulid:{name:{amharic:"\u1218\u12CD\u120A\u12F5",english:"Birth of the Prophet"},description:{amharic:"\u12E8\u1290\u1262\u12E9 \u1219\u1210\u1218\u12F5\u1295 \u12E8\u120D\u12F0\u1275 \u1260\u12D3\u120D \u12EB\u12A8\u1265\u122B\u120D\u1362",english:"Celebrates the birthday of the Prophet Mohammed."}},jummah:{name:{amharic:"\u1301\u121D\u12D3",english:"Jummah"},description:{amharic:"\u1233\u121D\u1295\u1273\u12CA \u12E8\u1219\u1235\u120A\u121E\u127D \u12E8\u130B\u122B \u1235\u130D\u12F0\u1275\u1362",english:"The weekly Muslim congregational prayer."}}};var HolidayNames=Object.freeze(Object.keys(holidayInfo).reduce((acc,key)=>{acc[key]=key;return acc},{}));var evangelistNames={english:{1:"Matthew",2:"Mark",3:"Luke",0:"John"},amharic:{1:"\u121B\u1274\u12CE\u1235",2:"\u121B\u122D\u1246\u1235",3:"\u1209\u1243\u1235",0:"\u12EE\u1210\u1295\u1235"}};var tewsakMap={Sunday:7,Monday:6,Tuesday:5,Wednesday:4,Thursday:3,Friday:2,Saturday:8};var movableHolidayTewsak={NINEVEH:0,ABIY_TSOME:14,DEBRE_ZEIT:41,HOSANNA:62,SIKLET:67,TINSAYE:69,RIKBE_KAHNAT:93,ERGET:108,PARACLETE:118,TSOME_HAWARYAT:119,TSOME_DIHENET:121};var movableHolidays={nineveh:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},abiyTsome:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},debreZeit:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},hosanna:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},siklet:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN,HolidayTags.PUBLIC]},fasika:{tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},rikbeKahnat:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},erget:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},paraclete:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},tsomeHawaryat:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},tsomeDihnet:{tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},eidFitr:{tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.MUSLIM]},eidAdha:{tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.MUSLIM]},moulid:{tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.MUSLIM]}};var FastingKeys={ABIY_TSOME:"ABIY_TSOME",TSOME_HAWARYAT:"TSOME_HAWARYAT",TSOME_NEBIYAT:"TSOME_NEBIYAT",NINEVEH:"NINEVEH",FILSETA:"FILSETA",RAMADAN:"RAMADAN",TSOME_DIHENET:"TSOME_DIHENET"};var fastingInfo={ABIY_TSOME:{name:{amharic:"\u12D0\u1262\u12ED \u133E\u121D (\u1201\u12F3\u12F4)",english:"Great Lent (Abiy Tsome)"},description:{amharic:"\u12A8\u134B\u1232\u12AB \u1260\u134A\u1275 \u12E8\u121A\u133E\u121D 55 \u1240\u1293\u1275 \u12E8\u133E\u121D \u12C8\u1245\u1275 \u1290\u12CD\u1362",english:"A 55-day fasting season observed before Easter in the Ethiopian Orthodox Church."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},NINEVEH:{name:{amharic:"\u133E\u1218 \u1290\u1290\u12CC",english:"Fast of Nineveh"},description:{amharic:"\u12E8\u1290\u1290\u12CC \u1230\u12CE\u127D \u1208\u1230\u1229\u1275 \u1210\u1322\u12EB\u1275 \u12E8\u12A5\u130D\u12DA\u12A0\u1265\u1214\u122D\u1295 \u121D\u1205\u1228\u1275\u1293 \u12ED\u1245\u122D\u1273 \u1208\u1218\u1320\u12E8\u1245 \u12E8\u1346\u1219\u1275\u1295 \u1208\u121B\u1235\u1273\u12C8\u1235 \u1290\u12CD\u1362",english:"A three-day fast commemorating the repentance of the people of Nineveh."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},TSOME_HAWARYAT:{name:{amharic:"\u133E\u1218 \u1210\u12CB\u122D\u12EB\u1275",english:"Apostles' Fast (Tsome Hawaryat)"},description:{amharic:"\u12AD\u122D\u1235\u1276\u1235 \u12A8\u1219\u1273\u1295 \u1270\u1208\u12ED\u1276 \u12A8\u1270\u1290\u1233 \u1260\u1203\u120B \u1245\u12F1\u1233\u1295 \u1200\u12CB\u122D\u12EB\u1275 \u1230\u121B\u12EB\u12CA \u1270\u120D\u12A5\u12AE \u1235\u1208\u1270\u1230\u121B\u1278\u12CD \u12A850\u1240\u1295 \u1260\u1203\u120B \u1260\u1260\u12A0\u1208 \u1330\u122B\u1245\u120A\u1326\u1235 \u121B\u130D\u1235\u1275 \u1218\u1346\u121D \u1300\u1218\u1229\u1362",english:"Begins after Pentecost and lasts until Hamle 4 in the Ethiopian calendar."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},TSOME_NEBIYAT:{name:{amharic:"\u12E8\u1308\u1293-\u1346\u121D (\u133E\u1218 \u1290\u1262\u12EB\u1275)",english:"Fast of the Prophets (Tsome Nebiyat)"},description:{amharic:"\u12A8\u1205\u12F3\u122D 15 \u12A5\u1235\u12A8 \u1273\u1215\u1233\u1235 28 \u12F5\u1228\u1235 \u12E8\u121A\u1320\u1265\u1245 \u12E8\u124B\u121A \u133E\u121D \u1290\u12CD\u1362",english:"A fixed fast observed from Hidar 15 to Tahsas 28."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},FILSETA:{name:{amharic:"\u134D\u120D\u1230\u1273",english:"Filseta"},description:{amharic:"\u1346\u1218 \u134D\u120D\u1230\u1273 /\u12A8\u1290\u1210\u1234 1 \u12A5\u1235\u12A8 \u1290\u1210\u1234 14 \u1240\u1295/ \u12E8\u12A5\u1218\u1264\u1273\u127D\u1295 \u12D5\u1228\u134D\u1275\u1363 \u1275\u1295\u1223\u12A4\u1293 \u12D5\u122D\u1308\u1277 \u12E8\u121A\u1273\u1230\u1265\u1260\u1275 \u12C8\u1245\u1275 \u1290\u12CD\u1361\u1361",english:"A fixed 14-day fast (Nehase 1\u201314) commemorating the Dormition, Resurrection, and Assumption of the Virgin Mary; a season of prayer and intercession."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},RAMADAN:{name:{amharic:"\u1228\u1218\u12F3\u1295",english:"Ramadan"},description:{amharic:"\u1228\u1218\u12F3\u1295 \u1260\u1202\u1305\u122B \u12A0\u1246\u1323\u1320\u122D \u12D8\u1320\u1290\u129B\u12CD \u12C8\u122D \u12A5\u1293 \u1260\u1219\u1235\u120A\u121E\u127D \u12D8\u1295\u12F5 \u12E8\u133E\u121D\u1363 \u1338\u120E\u1275 \u12C8\u122D \u1290\u12CD",english:"The Islamic month of fasting from dawn to sunset; a time of prayer, reflection, and charity."},tags:[HolidayTags.RELIGIOUS,HolidayTags.MUSLIM]},TSOME_DIHENET:{name:{amharic:"\u133E\u1218 \u12F5\u1285\u1290\u1275 (\u1228\u1261\u12A5\xB7\u12D3\u122D\u1265)",english:"Fast of Salvation (Wed & Fri)"},description:{amharic:"\u12A8\u1260\u12A0\u1208 \u1200\u121D\u1233 \u12CD\u132D \u1260\u1233\u121D\u1295\u1275 \u1228\u1261\u12A5 \u12A5\u1293 \u12A0\u122D\u1265 \u12E8\u121D\u1295\u1346\u1218\u12CD \u1290\u12CD\u1362",english:"A fast observed on Wednesdays and Fridays outside of the 50 days after Easter."},tags:[HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]}};var symbols={ones:["","\u1369","\u136A","\u136B","\u136C","\u136D","\u136E","\u136F","\u1370","\u1371"],tens:["","\u1372","\u1373","\u1374","\u1375","\u1376","\u1377","\u1378","\u1379","\u137A"],hundred:"\u137B",tenThousand:"\u137C"};function toGeez(input){if(typeof input!=="number"&&typeof input!=="string"){throw new GeezConverterError("Input must be a number or a string.")}const num=Number(input);if(isNaN(num)||!Number.isInteger(num)||num<0){throw new GeezConverterError("Input must be a non-negative integer.")}if(num===0)return"0";function convertBelow100(n){if(n<=0)return"";const tensDigit=Math.floor(n/10);const onesDigit=n%10;return symbols.tens[tensDigit]+symbols.ones[onesDigit]}__name(convertBelow100,"convertBelow100");if(num<100){return convertBelow100(num)}if(num===100)return symbols.hundred;if(num<1e4){const hundreds=Math.floor(num/100);const remainder2=num%100;const hundredPart=(hundreds>1?convertBelow100(hundreds):"")+symbols.hundred;return hundredPart+convertBelow100(remainder2)}const tenThousandPart=Math.floor(num/1e4);const remainder=num%1e4;const tenThousandGeez=(tenThousandPart>1?toGeez(tenThousandPart):"")+symbols.tenThousand;return tenThousandGeez+(remainder>0?toGeez(remainder):"")}__name(toGeez,"toGeez");function toArabic(geezStr){if(typeof geezStr!=="string"){throw new GeezConverterError("Input must be a non-empty string.")}if(geezStr.trim()===""){return 0}const reverseMap={};symbols.ones.forEach((char,i)=>{if(char)reverseMap[char]=i});symbols.tens.forEach((char,i)=>{if(char)reverseMap[char]=i*10});reverseMap[symbols.hundred]=100;reverseMap[symbols.tenThousand]=1e4;let total=0;let currentNumber=0;for(const char of geezStr){const value=reverseMap[char];if(value===void 0){throw new GeezConverterError(`Unknown Ge'ez numeral: ${char}`)}if(value===100||value===1e4){currentNumber=(currentNumber||1)*value;if(value===1e4){total+=currentNumber;currentNumber=0}}else{currentNumber+=value}}total+=currentNumber;return total}__name(toArabic,"toArabic");function printMonthCalendarGrid(ethiopianYear,ethiopianMonth,calendarData,useGeez=false){validateNumericInputs("printMonthCalendarGrid",{ethiopianYear,ethiopianMonth});if(ethiopianMonth<1||ethiopianMonth>13){throw new InvalidInputTypeError("printMonthCalendarGrid","ethiopianMonth","number between 1 and 13",ethiopianMonth)}if(!Array.isArray(calendarData)||calendarData.length===0){console.error("Calendar data is empty or invalid. Cannot print grid.");return}const daysOfWeek2=["Mo","Tu","We","Th","Fr","Sa","Su"];console.log(`
${monthNames.amharic[ethiopianMonth-1]} ${useGeez?toGeez(ethiopianYear):ethiopianYear}`);console.log(daysOfWeek2.join(" "));const firstDayGregorian=calendarData[0].gregorian;const jsDate=new Date(firstDayGregorian.year,firstDayGregorian.month-1,firstDayGregorian.day);const weekDay=(jsDate.getDay()+6)%7;let row=Array(weekDay).fill(" ");for(const day of calendarData){const ethDay=useGeez?toGeez(day.ethiopian.day).padStart(2,"\u1369"):String(day.ethiopian.day).padStart(2," ");const gregDay=String(day.gregorian.day).padStart(2," ");row.push(`${ethDay}/${gregDay}`);if(row.length===7){console.log(row.join(" "));row=[]}}if(row.length>0){console.log(row.join(" ").padEnd(27," "))}}__name(printMonthCalendarGrid,"printMonthCalendarGrid");var _Time=class _Time{constructor(hour,minute=0,period="day"){validateNumericInputs("Time.constructor",{hour,minute});if(hour<1||hour>12){throw new InvalidTimeError(`Invalid Ethiopian hour: ${hour}. Must be between 1 and 12.`)}if(minute<0||minute>59){throw new InvalidTimeError(`Invalid minute: ${minute}. Must be between 0 and 59.`)}if(period!=="day"&&period!=="night"){throw new InvalidTimeError(`Invalid period: "${period}". Must be 'day' or 'night'.`)}this.hour=hour;this.minute=minute;this.period=period}static fromGregorian(hour,minute=0){validateNumericInputs("Time.fromGregorian",{hour,minute});if(hour<0||hour>23){throw new InvalidTimeError(`Invalid Gregorian hour: ${hour}. Must be between 0 and 23.`)}if(minute<0||minute>59){throw new InvalidTimeError(`Invalid minute: ${minute}. Must be between 0 and 59.`)}let tempHour=hour-6;if(tempHour<0){tempHour+=24}const period=tempHour<12?"day":"night";let ethHour=tempHour%12;ethHour=ethHour===0?12:ethHour;return new _Time(ethHour,minute,period)}toGregorian(){let gregHour=this.hour%12;if(this.period==="day"){gregHour+=6}else{gregHour+=18}gregHour=gregHour%24;return{hour:gregHour,minute:this.minute}}static fromString(timeString){if(typeof timeString!=="string"||timeString.trim()===""){throw new InvalidTimeError(`Input must be a non-empty string, but received "${timeString}".`)}if(!timeString.includes(":")){throw new InvalidTimeError(`Invalid time string format: "${timeString}". Time must include a colon ':' separator.`)}const parseNumber=__name(str=>{const arabicNum=parseInt(str,10);if(!isNaN(arabicNum)){return arabicNum}try{return toArabic(str)}catch(e){return NaN}},"parseNumber");const parts=timeString.split(/[:\s]+/).filter(p=>p);if(parts.length<2){throw new InvalidTimeError(`Invalid time string format: "${timeString}".`)}const hour=parseNumber(parts[0]);const minute=parseNumber(parts[1]);if(isNaN(hour)||isNaN(minute)){throw new InvalidTimeError(`Invalid number in time string: "${timeString}"`)}let period="day";if(parts.length>2){const periodStr=parts[2].toLowerCase();if(periodStr==="night"||periodStr==="\u121B\u1273"){period="night"}}return new _Time(hour,minute,period)}add(duration){if(typeof duration!=="object"||duration===null){throw new InvalidTimeError("Duration must be an object.")}const{hours=0,minutes=0}=duration;validateNumericInputs("Time.add",{hours,minutes});const greg=this.toGregorian();let totalMinutes=greg.hour*60+greg.minute+hours*60+minutes;totalMinutes=(totalMinutes%1440+1440)%1440;const newHour=Math.floor(totalMinutes/60);const newMinute=totalMinutes%60;return _Time.fromGregorian(newHour,newMinute)}subtract(duration){if(typeof duration!=="object"||duration===null){throw new InvalidTimeError("Duration must be an object.")}const{hours=0,minutes=0}=duration;return this.add({hours:-hours,minutes:-minutes})}diff(otherTime){if(!(otherTime instanceof _Time)){throw new InvalidTimeError("Can only compare with another Time instance.")}const t1=this.toGregorian();const t2=otherTime.toGregorian();const totalMinutes1=t1.hour*60+t1.minute;const totalMinutes2=t2.hour*60+t2.minute;let diff=Math.abs(totalMinutes1-totalMinutes2);if(diff>720)diff=1440-diff;return{hours:Math.floor(diff/60),minutes:diff%60}}format(options={}){const defaultLang=options.useGeez===false?"english":"amharic";const{lang=defaultLang,useGeez=true,showPeriodLabel=true,zeroAsDash=true}=options;const formatNum=__name(num=>{if(useGeez)return toGeez(num);return num.toString().padStart(2,"0")},"formatNum");const hourStr=formatNum(this.hour);let minuteStr;if(zeroAsDash&&this.minute===0){minuteStr="_"}else{minuteStr=useGeez?toGeez(this.minute):this.minute.toString().padStart(2,"0")}let periodLabel="";if(showPeriodLabel){if(lang==="english"){periodLabel=this.period}else{const amharicLabels={day:"\u1320\u12CB\u1275",night:"\u121B\u1273"};periodLabel=amharicLabels[this.period]}}const label=periodLabel?` ${periodLabel}`:"";return`${hourStr}:${minuteStr}${label}`}};__name(_Time,"Time");var Time=_Time;function addDays(ethiopian,days){validateEthiopianDateObject(ethiopian,"addDays","ethiopian");validateNumericInputs("addDays",{days});let{year,month,day}=ethiopian;day+=days;while(day>getEthiopianDaysInMonth(year,month)){day-=getEthiopianDaysInMonth(year,month);month+=1;if(month>13){month=1;year+=1}}while(day<=0){month-=1;if(month<1){month=13;year-=1}day+=getEthiopianDaysInMonth(year,month)}return{year,month,day}}__name(addDays,"addDays");function addMonths(ethiopian,months){validateEthiopianDateObject(ethiopian,"addMonths","ethiopian");validateNumericInputs("addMonths",{months});let{year,month,day}=ethiopian;let totalMonths=month+months;year+=Math.floor((totalMonths-1)/13);month=((totalMonths-1)%13+13)%13+1;const daysInTargetMonth=getEthiopianDaysInMonth(year,month);if(day>daysInTargetMonth){day=daysInTargetMonth}return{year,month,day}}__name(addMonths,"addMonths");function addYears(ethiopian,years){validateEthiopianDateObject(ethiopian,"addYears","ethiopian");validateNumericInputs("addYears",{years});let{year,month,day}=ethiopian;year+=years;if(month===13&&day===6&&!isEthiopianLeapYear(year)){day=5}return{year,month,day}}__name(addYears,"addYears");function diffInDays(a,b){validateEthiopianDateObject(a,"diffInDays","a");validateEthiopianDateObject(b,"diffInDays","b");const totalDays=__name(eth=>{let days=0;for(let y=1;y<eth.year;y++){days+=isEthiopianLeapYear(y)?366:365}for(let m=1;m<eth.month;m++){days+=getEthiopianDaysInMonth(eth.year,m)}days+=eth.day;return days},"totalDays");return totalDays(a)-totalDays(b)}__name(diffInDays,"diffInDays");function diffInMonths(a,b){validateEthiopianDateObject(a,"diffInMonths","a");validateEthiopianDateObject(b,"diffInMonths","b");const totalMonthsA=a.year*13+(a.month-1);const totalMonthsB=b.year*13+(b.month-1);let diff=totalMonthsA-totalMonthsB;if(a.day<b.day){diff-=1}return diff}__name(diffInMonths,"diffInMonths");function diffInYears(a,b){validateEthiopianDateObject(a,"diffInYears","a");validateEthiopianDateObject(b,"diffInYears","b");const isAfter=a.year>b.year||a.year===b.year&&a.month>b.month||a.year===b.year&&a.month===b.month&&a.day>=b.day;const[later,earlier]=isAfter?[a,b]:[b,a];let diff=later.year-earlier.year;if(later.month<earlier.month||later.month===earlier.month&&later.day<earlier.day){diff--}const finalDiff=isAfter?diff:-diff;if(finalDiff===0){return 0}return finalDiff}__name(diffInYears,"diffInYears");function diffBreakdown(a,b,options={}){validateEthiopianDateObject(a,"diffBreakdown","a");validateEthiopianDateObject(b,"diffBreakdown","b");const{units=["years","months","days"]}=options;const totalDaysDiff=diffInDays(a,b);const sign=totalDaysDiff===0?1:totalDaysDiff>0?1:-1;const later=sign>=0?a:b;const earlier=sign>=0?b:a;let cursor={...earlier};const result={sign,totalDays:Math.abs(totalDaysDiff)};if(units.includes("years")){let years=0;while(true){const next=addYears(cursor,1);if(diffInDays(later,next)>=0){years+=1;cursor=next}else{break}}result.years=years}if(units.includes("months")){let months=0;while(true){const next=addMonths(cursor,1);if(diffInDays(later,next)>=0){months+=1;cursor=next}else{break}}result.months=months}if(units.includes("days")){result.days=Math.abs(diffInDays(later,cursor))}return result}__name(diffBreakdown,"diffBreakdown");function getBahireHasab(ethiopianYear,options={}){validateNumericInputs("getBahireHasab",{ethiopianYear});const{lang="amharic"}=options;const base=_calculateBahireHasabBase(ethiopianYear);const evangelistRemainder=base.ameteAlem%4;const evangelistNamesMap=evangelistNames;const evangelistName=evangelistNamesMap[lang]?.[evangelistRemainder]||evangelistNames.english[evangelistRemainder];const tinteQemer=(base.ameteAlem+base.meteneRabiet)%7;const weekdayIndex=(tinteQemer+1)%7;const daysOfWeekMap=daysOfWeek;const newYearWeekday=daysOfWeekMap[lang]?.[weekdayIndex]||daysOfWeek.english[weekdayIndex];const movableFeasts={};const tewsakToKeyMap=Object.entries(keyToTewsakMap).reduce((acc,[key,val])=>{acc[val]=key;return acc},{});Object.keys(movableHolidayTewsak).forEach(tewsakKey=>{const holidayKey=tewsakToKeyMap[tewsakKey];if(holidayKey){const date=addDays(base.ninevehDate,movableHolidayTewsak[tewsakKey]);const info=holidayInfo[holidayKey];const rules=movableHolidays[holidayKey];movableFeasts[holidayKey]={key:holidayKey,tags:rules.tags,movable:true,name:info?.name?.[lang]||info?.name?.english,description:info?.description?.[lang]||info?.description?.english,ethiopian:date,gregorian:toGC(date.year,date.month,date.day)}}});return{ameteAlem:base.ameteAlem,meteneRabiet:base.meteneRabiet,evangelist:{name:evangelistName,remainder:evangelistRemainder},newYear:{dayName:newYearWeekday,tinteQemer},medeb:base.medeb,wenber:base.wenber,abektie:base.abektie,metqi:base.metqi,bealeMetqi:{date:base.bealeMetqiDate,weekday:base.bealeMetqiWeekday},mebajaHamer:base.mebajaHamer,nineveh:base.ninevehDate,movableFeasts}}__name(getBahireHasab,"getBahireHasab");function getMovableHoliday(holidayKey,ethiopianYear){validateNumericInputs("getMovableHoliday",{ethiopianYear});const tewsak=movableHolidayTewsak[holidayKey];if(tewsak===void 0){throw new UnknownHolidayError(holidayKey)}const{ninevehDate}=_calculateBahireHasabBase(ethiopianYear);return addDays(ninevehDate,tewsak)}__name(getMovableHoliday,"getMovableHoliday");function _calculateBahireHasabBase(ethiopianYear){const ameteAlem=5500+ethiopianYear;const meteneRabiet=Math.floor(ameteAlem/4);const medeb=ameteAlem%19;const wenber=medeb===0?18:medeb-1;const abektie=wenber*11%30;const rawMetqi=wenber*19%30;const metqi=rawMetqi===0?30:rawMetqi;const bealeMetqiMonth=metqi>14?1:2;const bealeMetqiDay=metqi;const bealeMetqiDate={year:ethiopianYear,month:bealeMetqiMonth,day:bealeMetqiDay};const bealeMetqiWeekday=daysOfWeek.english[getWeekday(bealeMetqiDate)];const tewsak=tewsakMap[bealeMetqiWeekday];const mebajaHamerSum=bealeMetqiDay+tewsak;const mebajaHamer=mebajaHamerSum>30?mebajaHamerSum%30:mebajaHamerSum;let ninevehMonth=metqi>14?5:6;if(mebajaHamerSum>30)ninevehMonth++;const ninevehDate={year:ethiopianYear,month:ninevehMonth,day:mebajaHamer};return{ameteAlem,meteneRabiet,medeb,wenber,abektie,metqi,bealeMetqiDate,bealeMetqiWeekday,mebajaHamer,ninevehDate}}__name(_calculateBahireHasabBase,"_calculateBahireHasabBase");var fixedHolidays={enkutatash:{month:1,day:1,tags:[HolidayTags.PUBLIC,HolidayTags.CULTURAL]},meskel:{month:1,day:17,tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},beherbehereseb:{month:3,day:29,tags:[HolidayTags.PUBLIC,HolidayTags.STATE]},gena:{month:4,day:29,tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},timket:{month:5,day:11,tags:[HolidayTags.PUBLIC,HolidayTags.RELIGIOUS,HolidayTags.CHRISTIAN]},martyrsDay:{month:6,day:12,tags:[HolidayTags.PUBLIC,HolidayTags.STATE]},adwa:{month:6,day:23,tags:[HolidayTags.PUBLIC,HolidayTags.STATE]},labour:{month:8,day:23,tags:[HolidayTags.PUBLIC,HolidayTags.STATE]},patriots:{month:8,day:27,tags:[HolidayTags.PUBLIC,HolidayTags.STATE]}};function findAllIslamicOccurrences(ethiopianYear,hijriMonth,hijriDay){const startGregorianYear=toGC(ethiopianYear,1,1).year;const endGregorianYear=toGC(ethiopianYear,13,5).year;const occurrences=[];const checkGregorianYear=__name(gYear=>{const hijriYearAtStart=getHijriYear(new Date(gYear,0,1));const hijriYearsToCheck=[hijriYearAtStart,hijriYearAtStart+1];hijriYearsToCheck.forEach(hYear=>{const gregorianDate=hijriToGregorian(hYear,hijriMonth,hijriDay,gYear);if(gregorianDate&&gregorianDate.getFullYear()===gYear){const ecDate=toEC(gregorianDate.getFullYear(),gregorianDate.getMonth()+1,gregorianDate.getDate());if(ecDate.year===ethiopianYear){occurrences.push({gregorian:{year:gregorianDate.getFullYear(),month:gregorianDate.getMonth()+1,day:gregorianDate.getDate()},ethiopian:ecDate})}}})},"checkGregorianYear");checkGregorianYear(startGregorianYear);if(startGregorianYear!==endGregorianYear){checkGregorianYear(endGregorianYear)}return Array.from(new Map(occurrences.map(item=>[JSON.stringify(item.ethiopian),item])).values())}__name(findAllIslamicOccurrences,"findAllIslamicOccurrences");function findHijriMonthRanges(ethiopianYear,hijriMonth){const startGregorianYear=toGC(ethiopianYear,1,1).year;const endGregorianYear=toGC(ethiopianYear,13,5).year;const ranges=[];const findRangeInGregorianYear=__name(gYear=>{const hijriYearAtStart=getHijriYear(new Date(gYear,0,1));const hijriYearsToCheck=[hijriYearAtStart-1,hijriYearAtStart,hijriYearAtStart+1];for(const hYear of hijriYearsToCheck){const startDateGregorian=hijriToGregorian(hYear,hijriMonth,1,gYear);if(!startDateGregorian)continue;const nextMonth=hijriMonth===12?1:hijriMonth+1;const nextYear=hijriMonth===12?hYear+1:hYear;let endDateGregorian;const endDateCandidate=hijriToGregorian(nextYear,nextMonth,1,gYear)||hijriToGregorian(nextYear,nextMonth,1,gYear+1);if(endDateCandidate){endDateGregorian=new Date(endDateCandidate.getTime()-864e5)}else{continue}const startEC=toEC(startDateGregorian.getFullYear(),startDateGregorian.getMonth()+1,startDateGregorian.getDate());const endEC=toEC(endDateGregorian.getFullYear(),endDateGregorian.getMonth()+1,endDateGregorian.getDate());if(startEC.year===ethiopianYear||endEC.year===ethiopianYear){ranges.push({start:startEC,end:endEC})}}},"findRangeInGregorianYear");findRangeInGregorianYear(startGregorianYear);if(startGregorianYear!==endGregorianYear){findRangeInGregorianYear(endGregorianYear)}const uniqueRanges=Array.from(new Map(ranges.map(item=>[`${item.start.year}/${item.start.month}/${item.start.day}`,item])).values());return uniqueRanges}__name(findHijriMonthRanges,"findHijriMonthRanges");var getAllMoulidDates=__name(year=>findAllIslamicOccurrences(year,3,12),"getAllMoulidDates");var getAllEidFitrDates=__name(year=>findAllIslamicOccurrences(year,10,1),"getAllEidFitrDates");var getAllEidAdhaDates=__name(year=>findAllIslamicOccurrences(year,12,10),"getAllEidAdhaDates");function getHoliday(holidayKey,ethYear,options={}){validateNumericInputs("getHoliday",{ethYear});const{lang="amharic"}=options;const info=holidayInfo[holidayKey];if(!info)return null;const name=info?.name?.[lang]||info?.name?.english;const description=info?.description?.[lang]||info?.description?.english;if(fixedHolidays[holidayKey]){const rules=fixedHolidays[holidayKey];return{key:holidayKey,tags:rules.tags,movable:false,name,description,ethiopian:{year:ethYear,month:rules.month,day:rules.day}}}const tewsakKey=keyToTewsakMap[holidayKey];if(tewsakKey){const date=getMovableHoliday(tewsakKey,ethYear);return{key:holidayKey,tags:movableHolidays[holidayKey].tags,movable:true,name,description,ethiopian:date,gregorian:toGC(date.year,date.month,date.day)}}let muslimDateData;if(holidayKey==="eidFitr")muslimDateData=getAllEidFitrDates(ethYear)[0];else if(holidayKey==="eidAdha")muslimDateData=getAllEidAdhaDates(ethYear)[0];else if(holidayKey==="moulid")muslimDateData=getAllMoulidDates(ethYear)[0];if(muslimDateData){return{key:holidayKey,tags:movableHolidays[holidayKey].tags,movable:true,name,description,ethiopian:muslimDateData.ethiopian,gregorian:muslimDateData.gregorian}}return null}__name(getHoliday,"getHoliday");function getHolidaysInMonth(ethYear,ethMonth,options={}){validateNumericInputs("getHolidaysInMonth",{ethYear,ethMonth});if(ethMonth<1||ethMonth>13){throw new InvalidInputTypeError("getHolidaysInMonth","ethMonth","number between 1 and 13",ethMonth)}const{lang="amharic",filter=null}=options;const allHolidaysForMonth=[];const allHolidayKeys=Object.keys(holidayInfo);allHolidayKeys.forEach(key=>{const holiday=getHoliday(key,ethYear,{lang});if(holiday&&holiday.ethiopian.month===ethMonth){allHolidaysForMonth.push(holiday)}});const muslimHolidays=[...getAllMoulidDates(ethYear).map(d=>({...d,key:"moulid"})),...getAllEidFitrDates(ethYear).map(d=>({...d,key:"eidFitr"})),...getAllEidAdhaDates(ethYear).map(d=>({...d,key:"eidAdha"}))];muslimHolidays.forEach(data=>{if(data.ethiopian.month===ethMonth){const info=holidayInfo[data.key];const holidayObj={key:data.key,tags:movableHolidays[data.key].tags,movable:true,name:info?.name?.[lang]||info?.name?.english,description:info?.description?.[lang]||info?.description?.english,ethiopian:data.ethiopian,gregorian:data.gregorian};if(!allHolidaysForMonth.some(h=>JSON.stringify(h.ethiopian)===JSON.stringify(holidayObj.ethiopian))){allHolidaysForMonth.push(holidayObj)}}});const filterTags=filter?Array.isArray(filter)?filter:[filter]:null;const finalHolidays=filterTags?allHolidaysForMonth.filter(holiday=>holiday.tags.some(tag=>filterTags.includes(tag))):allHolidaysForMonth;finalHolidays.sort((a,b)=>a.ethiopian.day-b.ethiopian.day);return finalHolidays}__name(getHolidaysInMonth,"getHolidaysInMonth");function getHolidaysForYear(ethYear,options={}){validateNumericInputs("getHolidaysForYear",{ethYear});const{lang="amharic",filter=null}=options;const allHolidaysForYear=[];const singleOccurrenceKeys=Object.keys(fixedHolidays).concat(Object.keys(keyToTewsakMap));singleOccurrenceKeys.forEach(key=>{const holiday=getHoliday(key,ethYear,{lang});if(holiday){allHolidaysForYear.push(holiday)}});const addMuslimHolidays=__name((key,dateArray)=>{dateArray.forEach(data=>{const info=holidayInfo[key];allHolidaysForYear.push({key,tags:movableHolidays[key].tags,movable:true,name:info?.name?.[lang]||info?.name?.english,description:info?.description?.[lang]||info?.description?.english,ethiopian:data.ethiopian,gregorian:data.gregorian})})},"addMuslimHolidays");addMuslimHolidays("moulid",getAllMoulidDates(ethYear));addMuslimHolidays("eidFitr",getAllEidFitrDates(ethYear));addMuslimHolidays("eidAdha",getAllEidAdhaDates(ethYear));const filterTags=filter?Array.isArray(filter)?filter:[filter]:null;const finalHolidays=filterTags?allHolidaysForYear.filter(holiday=>holiday.tags.some(tag=>filterTags.includes(tag))):allHolidaysForYear;finalHolidays.sort((a,b)=>{if(a.ethiopian.month!==b.ethiopian.month){return a.ethiopian.month-b.ethiopian.month}return a.ethiopian.day-b.ethiopian.day});return finalHolidays}__name(getHolidaysForYear,"getHolidaysForYear");var nigs_default={"1":[{id:"ledeta_mariam",name:{english:"Ldata Mariam, The nativity of Our Holy Mother Virgin Mariam",amharic:"\u120D\u12F0\u1273 \u121B\u122D\u12EB\u121D"},description:{english:"Commemoration of the birth of St. Mary.",amharic:"\u12E8\u1245\u12F5\u1235\u1275 \u12F5\u1295\u130D\u120D \u121B\u122D\u12EB\u121D \u120D\u12F0\u1275 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[9]},{id:"archangel_raguel",name:{english:"Archangel Raguel",amharic:"\u122B\u1309\u12A4\u120D"},description:{english:"Commemoration of Archangel Raguel.",amharic:"\u12E8\u1218\u120B\u12A9 \u122B\u1309\u12A4\u120D \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[]},{id:"bartholomew_the_apostle",name:{english:"Bartholomew the Apostle",amharic:"\u1210\u12CB\u122D\u12EB\u12CD \u1260\u122D\u1270\u120E\u121C\u12CE\u1235"},description:{english:"Commemoration of Bartholomew the Apostle.",amharic:"\u12E8\u1210\u12CB\u122D\u12EB\u12CD \u1260\u122D\u1270\u120E\u121C\u12CE\u1235 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[]},{id:"prophet_elijah_ginbot",name:{english:"Prophet Elijah",amharic:"\u1290\u1265\u12E9 \u12A4\u120D\u12EB\u1235"},description:{english:"Commemoration of Prophet Elijah.",amharic:"\u12E8\u1290\u1265\u12E9 \u12A4\u120D\u12EB\u1235 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[4]},{id:"kidus_yohannes",name:{english:"Kidus Yohannes",amharic:"\u1245\u12F1\u1235 \u12EE\u1210\u1295\u1235"},description:{english:"Commemoration of Kidus Yohannes.",amharic:"\u12E8\u1245\u12F1\u1235 \u12EE\u1210\u1295\u1235 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:false,negs:[1]}],"2":[{id:"abba_guba",name:{english:"Abba Guba, one of the Nine Saints",amharic:"\u12A0\u1263 \u1309\u1263"},description:{english:"Commemoration of Abba Guba, one of the Nine Saints.",amharic:"\u12A8\u12D8\u1320\u1299 \u1245\u12F1\u1233\u1295 \u12A0\u1295\u12F1 \u12E8\u12A0\u1263 \u1309\u1263 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[]},{id:"thaddeus_the_apostle_major",name:{english:"Thaddeus the Apostle",amharic:"\u1210\u12CB\u122D\u12EB\u12CD \u1273\u12F5\u12EE\u1235"},description:{english:"Commemoration of Thaddeus the Apostle.",amharic:"\u12E8\u1210\u12CB\u122D\u12EB\u12CD \u1273\u12F5\u12EE\u1235 \u1218\u1273\u1230\u1262\u12EB\u1362"},major:true,negs:[11]},{id:"thaddeus_apostle_minor",name:{english:"Thaddeus the Apostle",amharic:"\u1210\u12CB\u122D\u12EB\u12CD \u1273\u12F5\u12EE\u1235"},description:{english:"Commemoration of Thaddeus the Apostle.",amharic:"\u12E8\u1210\u12CB\u122D\u12EB\u12CD \u1273\u12F5\u12EE\u1235 \u1218\u1273\u1230\u1262\u1