@calj.net/jdates
Version:
The Jewish Dates library from https://CalJ.net
230 lines (229 loc) • 7.65 kB
JavaScript
import { isDate, JDate } from "./JDate.js";
import { GDate } from "./GDate.js";
const uday = 25920; // 24 * 1080
const Tsyn = 765433; //29 * uday + 12 * 1080 + 793
const Ttohu = 5604; //5 * 1080 + 204;
const Tgatarad = 9924; //9 * 1080 + 204;
const Tzaken = 19440; //18 * 1080;
const Tbetutkafot = 16789; //15 * 1080 + 589;
export var HDateMonth;
(function (HDateMonth) {
HDateMonth[HDateMonth["TISHRI"] = 7] = "TISHRI";
HDateMonth[HDateMonth["CHESHVAN"] = 8] = "CHESHVAN";
HDateMonth[HDateMonth["KISLEV"] = 9] = "KISLEV";
HDateMonth[HDateMonth["TEVET"] = 10] = "TEVET";
HDateMonth[HDateMonth["SHVAT"] = 11] = "SHVAT";
HDateMonth[HDateMonth["ADAR"] = 12] = "ADAR";
HDateMonth[HDateMonth["ADAR2"] = 13] = "ADAR2";
HDateMonth[HDateMonth["NISSAN"] = 1] = "NISSAN";
HDateMonth[HDateMonth["IYAR"] = 2] = "IYAR";
HDateMonth[HDateMonth["SIVAN"] = 3] = "SIVAN";
HDateMonth[HDateMonth["TAMUZ"] = 4] = "TAMUZ";
HDateMonth[HDateMonth["AV"] = 5] = "AV";
HDateMonth[HDateMonth["ELUL"] = 6] = "ELUL";
})(HDateMonth || (HDateMonth = {}));
export var HDateYearType;
(function (HDateYearType) {
HDateYearType[HDateYearType["CHASERA"] = 1] = "CHASERA";
HDateYearType[HDateYearType["SDURA"] = 2] = "SDURA";
HDateYearType[HDateYearType["SHLEMA"] = 3] = "SHLEMA";
})(HDateYearType || (HDateYearType = {}));
const cacheRH = new Map();
export class HDate extends JDate {
static make(dayOrHdnOrJdate, month, year) {
return new HDate(dayOrHdnOrJdate, month, year);
}
constructor(dayOrHdnOrJdate, month, year) {
if (typeof dayOrHdnOrJdate === "number") {
super(HDate.hdnForYmd(year, month, dayOrHdnOrJdate));
}
else if (isDate(dayOrHdnOrJdate)) {
super(GDate.make(dayOrHdnOrJdate));
}
else {
super(dayOrHdnOrJdate);
}
const { year: y, month: m, day: d, yearType } = this.calcFromHdn();
this.year = y;
this.month = m;
this.day = d;
this.yearType = yearType;
}
static today() {
return new HDate(GDate.today());
}
getYear() {
return this.year;
}
getMonth() {
return this.month;
}
getDay() {
return this.day;
}
getMonthLength() {
return HDate.monthLengthForType(this.year, this.month, this.yearType);
}
getNumberOfMonths() {
return HDate.monthsInYear(this.year);
}
static monthsInYear(hyear) {
return HDate.embolismicYear(hyear) ? 13 : 12;
}
static monthLength(hyear, month) {
return HDate.make(1, month, hyear).getMonthLength();
}
static monthLengthForType(hyear, hmonth, yearType) {
const months = {
[HDateMonth.TISHRI]: 30,
[HDateMonth.CHESHVAN]: yearType === HDateYearType.SHLEMA ? 30 : 29,
[HDateMonth.KISLEV]: yearType === HDateYearType.CHASERA ? 29 : 30,
[HDateMonth.TEVET]: 29,
[HDateMonth.SHVAT]: 30,
[HDateMonth.ADAR]: HDate.embolismicYear(hyear) ? 30 : 29,
[HDateMonth.ADAR2]: 29,
[HDateMonth.NISSAN]: 30,
[HDateMonth.IYAR]: 29,
[HDateMonth.SIVAN]: 30,
[HDateMonth.TAMUZ]: 29,
[HDateMonth.AV]: 30,
[HDateMonth.ELUL]: 29,
};
return months[hmonth];
}
static embolismicYear(hyear) {
return (12 * hyear + 17) % 19 >= 12;
}
plus(days) {
const hdate = HDate.make(this);
hdate.calcFromHdn(days);
return hdate;
}
isEmbolismic() {
return HDate.embolismicYear(this.year);
}
getYearLength() {
const yearTypeMap = {
[HDateYearType.CHASERA]: (leap) => (leap ? 383 : 353),
[HDateYearType.SDURA]: (leap) => (leap ? 384 : 354),
[HDateYearType.SHLEMA]: (leap) => (leap ? 385 : 355),
};
return yearTypeMap[this.yearType](this.isEmbolismic());
}
getMonthName() {
return HDate.monthNames[this.month !== 12
? this.month - 1
: this.getNumberOfMonths() === 12
? 11
: 13];
}
static monthNames = [
"ניסן",
"אייר",
"סיון",
"תמוז",
"אב",
"אלול",
"תשרי",
"חשון",
"כסלו",
"טבת",
"שבט",
"אדר",
"אדר ב",
"אדר א",
];
static hdnForYmd(year, month, day) {
let _hdn = HDate.roshHashanaDay(year);
const nextRH = HDate.roshHashanaDay(year + 1);
const yearType = ((nextRH - _hdn) % 10) - 2;
let hmonth = HDateMonth.TISHRI;
const hyear = year;
const nbMonths = HDate.embolismicYear(hyear) ? 13 : 12;
if (month > nbMonths)
month = nbMonths;
while (hmonth != month) {
_hdn += HDate.monthLengthForType(hyear, hmonth, yearType);
hmonth = hmonth + 1 > nbMonths ? 1 : hmonth + 1;
}
const getMonthLength = HDate.monthLengthForType(hyear, hmonth, yearType);
if (day > getMonthLength) {
day = getMonthLength;
}
_hdn += day - 1;
return _hdn;
}
static roshHashanaDay(hyear) {
const result = cacheRH.get(hyear);
if (result) {
return result;
}
const Nmonths = Math.floor((235 * hyear - 234) / 19);
const Tmolad = Nmonths * Tsyn + Ttohu;
const days = Math.floor(Tmolad / uday);
const parts = Tmolad - days * uday;
const weekday = (1 + days) % 7;
let adu = weekday === 0 || weekday === 3 || weekday === 5;
const gatarad = !HDate.embolismicYear(hyear) && weekday === 2 && parts >= Tgatarad;
const betutkafot = hyear !== 1 &&
HDate.embolismicYear(hyear - 1) &&
weekday == 1 &&
parts >= Tbetutkafot;
let zaken = false;
if (!adu && !gatarad && !betutkafot) {
zaken = parts >= Tzaken;
if (zaken) {
adu = weekday === 2 || weekday === 4 || weekday === 6;
}
}
const lResult = 1 +
days +
(adu ? 1 : 0) +
(gatarad ? 2 : 0) +
(betutkafot ? 1 : 0) +
(zaken ? 1 : 0);
cacheRH.set(hyear, lResult);
return lResult;
}
calcFromHdn(offsetBy) {
if (offsetBy) {
this.setHdn(this.getHdn() + offsetBy);
}
const hdn = this.getHdn();
//Guess the approximate (greater) year of the specified Hebrew Day Number:
let hyear = 1 + Math.floor((234 + (19 * (hdn + 1) * uday) / Tsyn) / 235);
let rhnext = 0;
let rh = HDate.roshHashanaDay(hyear);
while (rh > hdn) {
rhnext = rh;
hyear--;
rh = HDate.roshHashanaDay(hyear);
}
if (rhnext === 0) {
rhnext = HDate.roshHashanaDay(hyear + 1);
}
this.yearType = ((rhnext - rh) % 10) - 2;
this.month = HDateMonth.TISHRI;
this.year = hyear;
this.day = 1;
let days = hdn - rh;
let ml = this.getMonthLength();
while (days >= ml) {
this.month =
this.month + 1 > this.getNumberOfMonths() ? 1 : this.month + 1;
days -= ml;
ml = this.getMonthLength();
}
this.day += days;
return {
year: this.year,
month: this.month,
day: this.day,
yearType: this.yearType,
};
}
year;
month;
day;
yearType;
}