UNPKG

ethio-calendar-converter-angular

Version:
145 lines (123 loc) 4.45 kB
import { Injectable } from '@angular/core'; import { EthiopianDate, GregorianDate } from './models/calendar.model'; @Injectable({ providedIn: 'root' }) 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)' }`; } }