ethio-calendar-converter-angular
Version:
Ethiopian Calendar Converter for Angular applications
145 lines (123 loc) • 4.45 kB
text/typescript
import { Injectable } from '@angular/core';
import { EthiopianDate, GregorianDate } from './models/calendar.model';
export class EthiopianCalendarService {
// Ethiopian calendar constants
private readonly ETHIOPIAN_MONTHS = 13;
private readonly ETHIOPIAN_DAYS_IN_MONTH = 30;
private readonly ETHIOPIAN_PAGUME_DAYS = 5; // 6 in leap year
private isEthiopianLeapYear(year: number): boolean {
return (year + 1) % 4 === 0;
}
private isGregorianLeapYear(year: number): boolean {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
private validateEthiopianDate(date: EthiopianDate): boolean {
if (date.month < 1 || date.month > this.ETHIOPIAN_MONTHS) return false;
if (date.month === this.ETHIOPIAN_MONTHS) {
const maxDays = this.isEthiopianLeapYear(date.year) ?
this.ETHIOPIAN_PAGUME_DAYS + 1 :
this.ETHIOPIAN_PAGUME_DAYS;
return date.day >= 1 && date.day <= maxDays;
}
return date.day >= 1 && date.day <= this.ETHIOPIAN_DAYS_IN_MONTH;
}
toGregorian(ethiopianDate: EthiopianDate): GregorianDate {
if (!this.validateEthiopianDate(ethiopianDate)) {
throw new Error('Invalid Ethiopian date');
}
let { year, month, day } = ethiopianDate;
// Calculate the number of days from Ethiopian new year to the given date
let daysDiff = (month - 1) * this.ETHIOPIAN_DAYS_IN_MONTH + day;
// Basic conversion (Ethiopian new year is typically September 11/12)
let gregorianYear = year + 7;
let gregorianMonth = 9; // September
let gregorianDay = 10; // Start from September 10
// Adjust for Ethiopian leap year
if (this.isEthiopianLeapYear(year)) {
gregorianDay += 1;
}
// Add the difference in days
gregorianDay += daysDiff;
// Adjust the Gregorian date
const gregorianMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (this.isGregorianLeapYear(gregorianYear)) {
gregorianMonthDays[1] = 29;
}
// Adjust month and day
while (gregorianDay > gregorianMonthDays[gregorianMonth - 1]) {
gregorianDay -= gregorianMonthDays[gregorianMonth - 1];
gregorianMonth++;
if (gregorianMonth > 12) {
gregorianMonth = 1;
gregorianYear++;
if (this.isGregorianLeapYear(gregorianYear)) {
gregorianMonthDays[1] = 29;
} else {
gregorianMonthDays[1] = 28;
}
}
}
return {
year: gregorianYear,
month: gregorianMonth,
day: gregorianDay
};
}
toEthiopian(gregorianDate: GregorianDate): EthiopianDate {
let { year, month, day } = gregorianDate;
// Find the Ethiopian year
let ethiopianYear = year - 8;
// Calculate days from Ethiopian new year (September 11/12)
const gregorianMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (this.isGregorianLeapYear(year)) {
gregorianMonthDays[1] = 29;
}
// Calculate the Ethiopian date
let ethiopianMonth = 1;
let ethiopianDay = 1;
// Adjust based on the Gregorian date
if (month > 9 || (month === 9 && day > 11)) {
ethiopianYear++;
}
// Calculate days from Ethiopian new year
let daysDiff = 0;
if (month > 9) {
// Add days from September to current month
for (let m = 9; m < month; m++) {
daysDiff += gregorianMonthDays[m - 1];
}
daysDiff += day - 11;
} else if (month < 9) {
// Add remaining days from September to December
for (let m = 9; m <= 12; m++) {
daysDiff += gregorianMonthDays[m - 1];
}
// Add days from January to current month
for (let m = 1; m < month; m++) {
daysDiff += gregorianMonthDays[m - 1];
}
daysDiff += day - 11;
} else {
// September
daysDiff = day - 11;
}
// Convert days difference to Ethiopian date
ethiopianMonth = Math.floor(daysDiff / 30) + 1;
ethiopianDay = (daysDiff % 30) + 1;
return {
year: ethiopianYear,
month: ethiopianMonth,
day: ethiopianDay
};
}
// Helper method to format dates
formatDate(date: EthiopianDate | GregorianDate, isEthiopian: boolean = true): string {
const { year, month, day } = date;
return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}${
isEthiopian ? ' (Ethiopian)' : ' (Gregorian)'
}`;
}
}