src/chronology/domain/DateConverterBase.ts
import data from 'chronology/domain/dateConverterData.json'
import DateConverterCompute from './DateConverterCompute'
export const monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
]
export const weekDayNames = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
]
const babylonianMonths = [
{ name: 'Nisannu', number: 'I', value: 1 },
{ name: 'Ayyāru', number: 'II', value: 2 },
{ name: 'Simānu', number: 'III', value: 3 },
{ name: 'Duʾūzu', number: 'IV', value: 4 },
{ name: 'Abu', number: 'V', value: 5 },
{ name: 'Ulūlu', number: 'VI', value: 6 },
{ name: 'Tašrītu', number: 'VII', value: 7 },
{ name: 'Araḫsamna', number: 'VIII', value: 8 },
{ name: 'Kislīmu', number: 'IX', value: 9 },
{ name: 'Ṭebētu', number: 'X', value: 10 },
{ name: 'Šabāṭu', number: 'XI', value: 11 },
{ name: 'Addaru', number: 'XII', value: 12 },
{ name: 'Ulūlu II', number: 'VIb', value: 13 },
{ name: 'Addāru II', number: 'XIIb', value: 14 },
]
export interface GregorianProps {
gregorianYear: number
gregorianMonth: number
gregorianDay: number
}
export interface JulianProps {
julianYear: number
julianMonth: number
julianDay: number
}
export interface SeBabylonianProps {
seBabylonianYear: number
mesopotamianMonth: number
mesopotamianDay?: number
}
export interface CalendarProps
extends GregorianProps,
JulianProps,
SeBabylonianProps {
bcGregorianYear?: number
bcJulianYear?: number
weekDay: number
cjdn: number
lunationNabonassar: number
seMacedonianYear?: number
seArsacidYear?: number
mesopotamianMonthLength?: number
ruler?: string
regnalYear?: number
regnalYears?: number
}
interface CalendarUpdateProps {
julianYear: number
julianMonth: number
julianDay: number
weekDay: number
cjdn: number
seBabylonianYear: number
lunationNabonassar: number
mesopotamianMonth: number
ruler?: string
regnalYear?: number
regnalYears?: number
i: number
}
export default class DateConverterBase extends DateConverterCompute {
getBcYear(year: number): number | undefined {
return year < 1 ? 1 - year : undefined
}
private getDaysInMonth(year: number, isJulian: boolean): number[] {
return [
31,
this.isLeapYear(year, isJulian) ? 29 : 28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31,
]
}
getMonthLength(isJulian = false): number {
const { year, month } = this.getYearAndMonth(isJulian)
return this.getDaysInMonth(year, isJulian)[month - 1]
}
getMesopotamianMonthsOfSeYear(
seBabylonianYear: number
): { name: string; number: string; value: number }[] {
return data.seBabylonianYearMonthPeriod
.filter(
(seBabylonianYearMonth) => seBabylonianYearMonth[0] === seBabylonianYear
)
.map(
(seBabylonianYearMonth) =>
babylonianMonths.find(
(_month) => _month.value === seBabylonianYearMonth[1]
) ?? babylonianMonths[0]
)
}
applyDate(
{ year, month, day }: { year: number; month: number; day: number },
dateType: 'gregorian' | 'julian'
): void {
const keyPrefix = dateType === 'gregorian' ? 'gregorian' : 'julian'
const bcYearKey =
dateType === 'gregorian' ? 'bcGregorianYear' : 'bcJulianYear'
this.calendar = {
...this.calendar,
[`${keyPrefix}Year`]: year,
[`${keyPrefix}Month`]: month,
[`${keyPrefix}Day`]: day,
[bcYearKey]: this.getBcYear(year),
}
}
applyGregorianDateWhenJulian(): void {
const cjdn = this.computeCjdnFromJulianDate({ ...this.calendar })
this.applyDate(this.computeGregorianDateFromCjdn(cjdn), 'gregorian')
}
updateBabylonianDate(
cjdn: number = this.computeCjdnFromJulianDate({ ...this.calendar })
): void {
const weekDay = this.computeWeekDay(cjdn)
const babylonianValues = this.computeBabylonianValues(cjdn)
this.updateCalendarProperties({
julianYear: this.calendar.julianYear,
julianMonth: this.calendar.julianMonth,
julianDay: this.calendar.julianDay,
cjdn,
weekDay,
...this.computeRegnalValues(babylonianValues.seBabylonianYear),
...babylonianValues,
})
}
private updateCalendarProperties(props: CalendarUpdateProps): void {
const { cjdn, weekDay, julianYear, julianMonth, julianDay } = props
this.calendar.cjdn = cjdn
this.calendar.weekDay = weekDay
this.applyDate(
{ year: julianYear, month: julianMonth, day: julianDay },
'julian'
)
this.applyBabylonianDate(props)
this.applySeleucidDate(props)
}
private applyBabylonianDate(props: CalendarUpdateProps): void {
const { cjdn, mesopotamianMonth, i, ruler, regnalYear, regnalYears } = props
const mesopotamianDay = cjdn - data.babylonianCjdnPeriod[i - 1] + 1
const mesopotamianMonthLength =
data.babylonianCjdnPeriod[i] - data.babylonianCjdnPeriod[i - 1]
const lunationNabonassar = 1498 + i
this.calendar = {
...this.calendar,
mesopotamianDay,
mesopotamianMonthLength,
mesopotamianMonth,
ruler,
regnalYear,
regnalYears,
lunationNabonassar,
}
}
private applySeleucidDate(props: CalendarUpdateProps): void {
const { seBabylonianYear, mesopotamianMonth } = props
const seMacedonianYear = this.calculateSeMacedonianYear(
seBabylonianYear,
mesopotamianMonth
)
const seArsacidYear = this.calculateSeArsacidYear(seBabylonianYear)
this.calendar = {
...this.calendar,
seBabylonianYear,
seMacedonianYear,
seArsacidYear,
}
}
private isLeapYear(year: number, isJulian = false): boolean {
return isJulian
? year % 4 === 0
: year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
}
private getYearAndMonth(isJulian = false): { year: number; month: number } {
return isJulian
? { year: this.calendar.julianYear, month: this.calendar.julianMonth }
: {
year: this.calendar.gregorianYear,
month: this.calendar.gregorianMonth,
}
}
}