📌 Overview
Kenat (Amharic: ቀናት) is a comprehensive JavaScript library for the Ethiopian calendar. It provides a complete toolset for developers, handling date conversions, advanced formatting, full date arithmetic, and a powerful, authentic holiday calculation system based on the traditional Bahire Hasab (ባሕረ ሃሳብ).
- 🔄 Bidirectional Conversion: Seamlessly convert between Ethiopian and Gregorian calendars with high precision.
- 🗂️ Complete Holiday System: Pre-loaded with all public, religious (Christian & Muslim), and cultural holidays.
- 🔎 Advanced Holiday Filtering: Easily filter holidays by tags (e.g., public, christian, muslim).
- 📖 Authentic Liturgical Calculations: Implements Bahire Hasab (ባሕረ ሃሳብ) for movable feasts and fasts.
- 🔠 Localized Formatting: Display dates in both Amharic and English with multiple format options.
- 🔢 Geez Numerals: Convert numbers and dates to traditional Geez numeral equivalents.
- ➕ Full Date Arithmetic: Add or subtract days, months, and years with support for the 13-month calendar.
↔️ Date Difference & Distance API: Calculate precise differences and human-friendly distances between dates.- 🕒 Ethiopian Time: Convert between 24-hour Gregorian and 12-hour Ethiopian time systems.
- 🗓️ Calendar Generation: Create monthly or yearly calendar grids with customizable options.
- 🕌 Fasting Periods: Calculate Orthodox Christian fasting periods and Islamic Ramadan dates.
- 📅 Date Range Generation: Generate arrays of dates between two Ethiopian dates.
- 🏷️ Holiday Distance Helpers: Find distances to next/previous holiday occurrences.
- 📊 Multiple Output Formats: Support for ISO strings, custom formatting, and structured data.
npm install kenat
Kenat includes full TypeScript definitions. No additional type packages needed!
import Kenat from 'kenat';
import type { EthiopianDate, Holiday } from 'kenat';
const today: Kenat = new Kenat();
const date: EthiopianDate = today.getEthiopian();
// Default import (Kenat class)
import Kenat from 'kenat';
// Named imports for utilities
import {
getHolidaysForYear,
HolidayTags,
toGeez,
toEC,
toGC,
diffBreakdown,
getFastingPeriod,
MonthGrid,
Time
} from 'kenat';
Get today's Ethiopian date:
import Kenat from 'kenat';
const today = new Kenat();
console.log(today.getEthiopian());
// → { year: 2018, month: 1, day: 8 }
console.log(today.format({ lang: 'english', showWeekday: true }));
// → "Thursday, Meskerem 8 2018"
// Get Gregorian equivalent
console.log(today.getGregorian());
// → { year: 2025, month: 9, day: 19 }
// Format with time
const withTime = today.setTime(8, 30, 'day');
console.log(withTime.format({ includeTime: true }));
// → "2018/1/8 8:30 day"
import { getHolidaysForYear } from 'kenat';
const holidaysIn2017 = getHolidaysForYear(2017);
console.log(holidaysIn2017.find(h => h.key === 'fasika'));
// Output for Fasika (Easter) in 2017
{
key: 'fasika',
tags: ['public', 'religious', 'christian'],
movable: true,
name: 'ፋሲካ',
description: 'የኢየሱስ ክርስቶስን ከሙታን መነሣት ያከብራል።...',
ethiopian: { year: 2017, month: 8, day: 12 },
gregorian: { year: 2025, month: 4, day: 20 }
}
import { getHolidaysForYear, HolidayTags } from 'kenat';
const publicHolidays = getHolidaysForYear(2017, {
filter: HolidayTags.PUBLIC
});
const religiousHolidays = getHolidaysForYear(2017, {
filter: [HolidayTags.CHRISTIAN, HolidayTags.MUSLIM]
});
const meskel = new Kenat('2017/1/17');
console.log(meskel.isHoliday()); // → Returns the Meskel holiday object
const notHoliday = new Kenat('2017/1/18');
console.log(notHoliday.isHoliday()); // → []
const bahireHasab = new Kenat('2017/1/1').getBahireHasab();
console.log(bahireHasab.evangelist);
// → { name: 'ማቴዎስ', remainder: 1 }
console.log(bahireHasab.movableFeasts.fasika.ethiopian);
// → { year: 2017, month: 8, day: 21 }
// Full output of .getBahireHasab() for 2017
{
ameteAlem: 7517,
meteneRabiet: 1879,
evangelist: { name: 'ማቴዎስ', remainder: 1 },
newYear: { dayName: 'ረቡዕ', tinteQemer: 2 },
medeb: 12,
wenber: 11,
abektie: 1,
metqi: 29,
bealeMetqi: { date: { year: 2017, month: 1, day: 29 }, weekday: 'Wednesday' },
mebajaHamer: 3,
nineveh: { year: 2017, month: 6, day: 3 },
movableFeasts: {
nineveh: { /* ... */ },
abiyTsome: { /* ... */ },
fasika: {
key: 'fasika',
tags: ['public', 'religious', 'christian'],
movable: true,
name: 'ፋሲካ',
description: 'የኢየሱስ ክርስቶስን ከሙታን መነሣት ያከብራል።...',
ethiopian: { year: 2017, month: 8, day: 12 },
gregorian: { year: 2025, month: 4, day: 20 }
},
// ... other movable holidays
}
}
const today = new Kenat();
const nextWeek = today.addDays(7);
const lastMonth = today.addMonths(-1);
// Fluent API
const future = today.add(2, 'years').add(3, 'months').add(15, 'days');
const a = new Kenat('2015/5/15');
const b = new Kenat('2012/5/15');
// Precise differences
console.log(a.diffInDays(b)); // → 1095
console.log(a.diffInYears(b)); // → 3
// Human-friendly distance
console.log(a.distanceTo(b, { units: ['years', 'months', 'days'], output: 'string' }));
// → "2 years 9 months 3 days"
// Monthly calendar
const calendar = Kenat.getMonthCalendar(2017, 1, {
useGeez: false,
weekdayLang: 'amharic'
});
// Yearly calendar
const yearCalendar = Kenat.getYearCalendar(2017);
// Date range generation
const start = new Kenat('2017/1/1');
const end = new Kenat('2017/1/10');
const range = Kenat.generateDateRange(start, end);
import { getFastingPeriod, getFastingInfo } from 'kenat';
// Get Lent fasting period
const lent = getFastingPeriod('ABIY_TSOME', 2017);
console.log(lent);
// → { start: { year: 2017, month: 7, day: 16 }, end: { year: 2017, month: 8, day: 12 } }
// Get fasting information
const fastingInfo = getFastingInfo('NINEVEH', 2017);
import { HolidayNames } from 'kenat';
// Distance to next holiday
console.log(Kenat.distanceToHoliday(HolidayNames.fasika, {
direction: 'future',
units: ['days'],
output: 'string'
}));
// → "358 days"
import { toGeez } from 'kenat';
console.log(toGeez(2017)); // → "፳፻፲፯"
// Format in Geez
const date = new Kenat('2017/1/1');
console.log(date.formatInGeezAmharic()); // → "መስከረም ፩ ፳፻፲፯"
// Set Ethiopian time (12-hour system)
const withTime = new Kenat('2017/1/1').setTime(8, 30, 'day');
console.log(withTime.format({ includeTime: true }));
// → "2017/1/1 8:30 day"
// Convert to ISO format
console.log(withTime.toISOString());
// → "2017-01-01T08:30"
Main class for Ethiopian date operations.
Constructor:
new Kenat() // Current date
new Kenat('2017/1/1') // Ethiopian date string
new Kenat({year: 2017, month: 1, day: 1}) // Date object
new Kenat(new Date()) // Gregorian Date object
Key Methods:
getEthiopian()
- Returns{year, month, day}
getGregorian()
- Returns Gregorian equivalentformat(options)
- Format with various optionsadd(amount, unit)
/subtract(amount, unit)
- Date arithmeticdistanceTo(other, options)
- Human-friendly distance calculationisHoliday(options)
- Check if date is a holidaygetBahireHasab()
- Get liturgical calculationssetTime(hour, minute, period)
- Set Ethiopian time
toEC(year, month, day)
- Gregorian to EthiopiantoGC(year, month, day)
- Ethiopian to GregoriantoGeez(number)
- Convert to Geez numeralstoArabic(geezString)
- Convert from Geez numerals
getHolidaysForYear(year, options)
- Get all holidays for a yeargetHolidaysInMonth(year, month, lang)
- Get holidays for a monthgetHoliday(key, year)
- Get specific holidayHolidayTags
- Constants for filtering holidaysHolidayNames
- Constants for holiday keys
getFastingPeriod(fastKey, year)
- Get fasting period datesgetFastingInfo(fastKey, year)
- Get fasting informationgetBahireHasab(year)
- Get Bahire Hasab calculations
Kenat.getMonthCalendar(year, month, options)
- Generate month calendarKenat.getYearCalendar(year, options)
- Generate year calendarKenat.generateDateRange(start, end)
- Generate date rangeMonthGrid.create(options)
- Create calendar grid
diffBreakdown(dateA, dateB, options)
- Precise date differenceKenat.distanceToHoliday(holidayKey, options)
- Distance to holiday
HolidayTags
- Holiday category tagsHolidayNames
- Holiday name constantsmonthNames
- Month name arrays in multiple languagesFastingKeys
- Fasting period keys
For detailed method signatures and advanced usage, refer to the full documentation.
-
Fork the repo & clone it.
-
Create a new branch:
git checkout -b feature/your-feature
-
Write your changes and add tests in the
/tests
directory. -
Run
npm test
to ensure everything passes. -
Open a Pull Request with your improvements or bug fix.
Melaku Demeke
Special thanks to the Ethiopian Orthodox Tewahedo Church for preserving the traditional Bahire Hasab calculations and to the open-source community for their contributions and feedback.
Thanks to all the amazing people who have contributed to this project!
MIT — see LICENSE for details.