| | import { |
| | daysInHebrewMonth, |
| | monthsInHebrewYear, |
| | roshHashanah, |
| | } from "./calendarMath.js"; |
| | import { GREGORIAN_EPOCH, type HebrewDate, MS_PER_DAY } from "./constants.js"; |
| |
|
| | |
| | function dateToAbsolute(date: Date): number { |
| | |
| | |
| | |
| | const useUTC = date.getFullYear() < 100; |
| | const year = useUTC ? date.getUTCFullYear() : date.getFullYear(); |
| | const month = useUTC ? date.getUTCMonth() : date.getMonth(); |
| | const day = useUTC ? date.getUTCDate() : date.getDate(); |
| | const normalized = new Date(0); |
| | normalized.setUTCFullYear(year, month, day); |
| | normalized.setUTCHours(0, 0, 0, 0); |
| | return Math.floor((normalized.getTime() - GREGORIAN_EPOCH) / MS_PER_DAY) + 1; |
| | } |
| |
|
| | |
| | function absoluteToDate(absolute: number): Date { |
| | const utc = new Date(GREGORIAN_EPOCH + (absolute - 1) * MS_PER_DAY); |
| | const result = new Date(0); |
| | result.setFullYear(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()); |
| | result.setHours(0, 0, 0, 0); |
| | return result; |
| | } |
| |
|
| | |
| | function absoluteFromHebrew({ year, monthIndex, day }: HebrewDate): number { |
| | let days = day - 1; |
| | for (let index = 0; index < monthIndex; index += 1) { |
| | days += daysInHebrewMonth(year, index); |
| | } |
| | return roshHashanah(year) + days; |
| | } |
| |
|
| | |
| | function hebrewFromAbsolute(absolute: number): HebrewDate { |
| | const date = new Date(GREGORIAN_EPOCH + (absolute - 1) * MS_PER_DAY); |
| | let year = date.getUTCFullYear() + 3760; |
| | if (date.getUTCMonth() >= 8) { |
| | year += 1; |
| | } |
| |
|
| | while (absolute >= roshHashanah(year + 1)) { |
| | year += 1; |
| | } |
| | while (absolute < roshHashanah(year)) { |
| | year -= 1; |
| | } |
| |
|
| | let dayOfYear = absolute - roshHashanah(year); |
| | const monthCount = monthsInHebrewYear(year); |
| | let monthIndex = 0; |
| | while (monthIndex < monthCount) { |
| | const monthDays = daysInHebrewMonth(year, monthIndex); |
| | if (dayOfYear < monthDays) { |
| | break; |
| | } |
| | dayOfYear -= monthDays; |
| | monthIndex += 1; |
| | } |
| |
|
| | return { |
| | year, |
| | monthIndex, |
| | day: dayOfYear + 1, |
| | }; |
| | } |
| |
|
| | |
| | export function toHebrewDate(date: Date): HebrewDate { |
| | return hebrewFromAbsolute(dateToAbsolute(date)); |
| | } |
| |
|
| | |
| | export function toGregorianDate(hebrew: HebrewDate): Date { |
| | return absoluteToDate(absoluteFromHebrew(hebrew)); |
| | } |
| |
|