UNPKG

@hebcal/core

Version:

A perpetual Jewish Calendar API

1,628 lines (1,608 loc) 480 kB
/*! @hebcal/core v5.10.1, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ var hebcal = (function (exports) { 'use strict'; /** DO NOT EDIT THIS AUTO-GENERATED FILE! */ const version = '5.10.1'; /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /* eslint-disable @typescript-eslint/no-namespace, no-inner-declarations */ /** @private */ const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; /** @private */ const monthLengths = [lengths, lengths.slice()]; monthLengths[1][2] = 29; /** * @private */ function mod$1(x, y) { return x - y * Math.floor(x / y); } /** * @private */ function quotient(x, y) { return Math.floor(x / y); } /** * @private * @param abs - R.D. number of days */ function yearFromFixed(abs) { const l0 = abs - 1; const n400 = quotient(l0, 146097); const d1 = mod$1(l0, 146097); const n100 = quotient(d1, 36524); const d2 = mod$1(d1, 36524); const n4 = quotient(d2, 1461); const d3 = mod$1(d2, 1461); const n1 = quotient(d3, 365); const year = 400 * n400 + 100 * n100 + 4 * n4 + n1; return n100 !== 4 && n1 !== 4 ? year + 1 : year; } /* const ABS_14SEP1752 = 639797; const ABS_2SEP1752 = 639785; */ /* * Formerly in namespace, now top-level */ /** * Returns true if the Gregorian year is a leap year * @param year Gregorian year */ function isGregLeapYear(year) { return !(year % 4) && (!!(year % 100) || !(year % 400)); } /** * Number of days in the Gregorian month for given year * @param month Gregorian month (1=January, 12=December) * @param year Gregorian year */ function daysInGregMonth(month, year) { // 1 based months return monthLengths[+isGregLeapYear(year)][month]; } /** * Returns true if the object is a Javascript Date */ function isDate(obj) { // eslint-disable-next-line no-prototype-builtins return typeof obj === 'object' && Date.prototype.isPrototypeOf(obj); } /** * @private * @param year * @param month (1-12) * @param day (1-31) */ function toFixed(year, month, day) { const py = year - 1; return 365 * py + quotient(py, 4) - quotient(py, 100) + quotient(py, 400) + quotient(367 * month - 362, 12) + (month <= 2 ? 0 : isGregLeapYear(year) ? -1 : -2) + day; } /** * Converts Gregorian date to absolute R.D. (Rata Die) days * @param date Gregorian date */ function greg2abs(date) { if (!isDate(date)) { throw new TypeError(`not a Date: ${date}`); } else if (isNaN(date.getTime())) { throw new RangeError('Invalid Date'); } const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate()); /* if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) { throw new RangeError(`Invalid Date: ${date}`); } */ return abs; } /** * Converts from Rata Die (R.D. number) to Gregorian date. * See the footnote on page 384 of ``Calendrical Calculations, Part II: * Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M. * Clamen, Software--Practice and Experience, Volume 23, Number 4 * (April, 1993), pages 383-404 for an explanation. * * Note that this function returns the daytime portion of the date. * For example, the 15th of Cheshvan 5769 began at sundown on * 12 November 2008 and continues through 13 November 2008. This * function would return only the date 13 November 2008. * @param abs - R.D. number of days * @example * const abs = hebrew2abs(5769, months.CHESHVAN, 15); * const date = abs2greg(abs); // 13 November 2008 * const year = date.getFullYear(); // 2008 * const monthNum = date.getMonth() + 1; // 11 * const day = date.getDate(); // 13 */ function abs2greg(abs) { if (typeof abs !== 'number' || isNaN(abs)) { throw new TypeError(`not a Number: ${abs}`); } abs = Math.trunc(abs); /* if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) { throw new RangeError(`Invalid Date: ${abs}`); } */ const year = yearFromFixed(abs); const priorDays = abs - toFixed(year, 1, 1); const correction = abs < toFixed(year, 3, 1) ? 0 : isGregLeapYear(year) ? 1 : 2; const month = quotient(12 * (priorDays + correction) + 373, 367); const day = abs - toFixed(year, month, 1) + 1; const dt = new Date(year, month - 1, day); if (year < 100 && year >= 0) { dt.setFullYear(year); } return dt; } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-namespace */ /** * Gregorian date helper functions */ exports.greg = void 0; (function (greg) {})(exports.greg || (exports.greg = {})); exports.greg.abs2greg = abs2greg; exports.greg.daysInMonth = daysInGregMonth; exports.greg.greg2abs = greg2abs; exports.greg.isDate = isDate; exports.greg.isLeapYear = isGregLeapYear; /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /* * More minimal HDate */ const NISAN$4 = 1; const IYYAR$1 = 2; const SIVAN$1 = 3; const TAMUZ$1 = 4; const AV$1 = 5; const ELUL$1 = 6; const TISHREI$2 = 7; const CHESHVAN$1 = 8; const KISLEV$2 = 9; const TEVET$2 = 10; const SHVAT$1 = 11; const ADAR_I$2 = 12; const ADAR_II$2 = 13; /** * Hebrew months of the year (NISAN=1, TISHREI=7) * @readonly * @enum {number} */ const months = { /** Nissan / ניסן */ NISAN: NISAN$4, /** Iyyar / אייר */ IYYAR: IYYAR$1, /** Sivan / סיון */ SIVAN: SIVAN$1, /** Tamuz (sometimes Tammuz) / תמוז */ TAMUZ: TAMUZ$1, /** Av / אב */ AV: AV$1, /** Elul / אלול */ ELUL: ELUL$1, /** Tishrei / תִּשְׁרֵי */ TISHREI: TISHREI$2, /** Cheshvan / חשון */ CHESHVAN: CHESHVAN$1, /** Kislev / כסלו */ KISLEV: KISLEV$2, /** Tevet / טבת */ TEVET: TEVET$2, /** Sh'vat / שבט */ SHVAT: SHVAT$1, /** Adar or Adar Rishon / אדר */ ADAR_I: ADAR_I$2, /** Adar Sheini (only on leap years) / אדר ב׳ */ ADAR_II: ADAR_II$2 }; const NISAN_STR = 'Nisan'; const monthNames0 = ['', NISAN_STR, 'Iyyar', 'Sivan', 'Tamuz', 'Av', 'Elul', 'Tishrei', 'Cheshvan', 'Kislev', 'Tevet', "Sh'vat"]; /* * Transliterations of Hebrew month names. * Regular years are index 0 and leap years are index 1. * @private */ const monthNames = [[...monthNames0, 'Adar', NISAN_STR], [...monthNames0, 'Adar I', 'Adar II', NISAN_STR]]; const edCache = new Map(); const EPOCH = -1373428; // Avg year length in the cycle (19 solar years with 235 lunar months) const AVG_HEBYEAR_DAYS = 365.24682220597794; /** * @private */ function assertNumber(n, name) { if (typeof n !== 'number' || isNaN(n)) { throw new TypeError(`param '${name}' not a number: ${n}`); } } /** * Converts Hebrew date to R.D. (Rata Die) fixed days. * R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian * Calendar. * @param year Hebrew year * @param month Hebrew month * @param day Hebrew date (1-30) * @example * const abs = hebrew2abs(5769, months.CHESHVAN, 15); */ function hebrew2abs(year, month, day) { assertNumber(year, 'year'); assertNumber(month, 'month'); assertNumber(day, 'day'); if (year < 1) { throw new RangeError(`hebrew2abs: invalid year ${year}`); } let tempabs = day; if (month < TISHREI$2) { for (let m = TISHREI$2; m <= monthsInYear(year); m++) { tempabs += daysInMonth(m, year); } for (let m = NISAN$4; m < month; m++) { tempabs += daysInMonth(m, year); } } else { for (let m = TISHREI$2; m < month; m++) { tempabs += daysInMonth(m, year); } } return EPOCH + elapsedDays(year) + tempabs - 1; } /** * @private */ function newYear(year) { return EPOCH + elapsedDays(year); } /** * Converts absolute R.D. days to Hebrew date * @param abs absolute R.D. days */ function abs2hebrew(abs) { assertNumber(abs, 'abs'); abs = Math.trunc(abs); if (abs <= EPOCH) { throw new RangeError(`abs2hebrew: ${abs} is before epoch`); } // first, quickly approximate year let year = Math.floor((abs - EPOCH) / AVG_HEBYEAR_DAYS); while (newYear(year) <= abs) { ++year; } --year; let month = abs < hebrew2abs(year, 1, 1) ? 7 : 1; while (abs > hebrew2abs(year, month, daysInMonth(month, year))) { ++month; } const day = 1 + abs - hebrew2abs(year, month, 1); return { yy: year, mm: month, dd: day }; } /** * Returns true if Hebrew year is a leap year * @param year Hebrew year */ function isLeapYear(year) { return (1 + year * 7) % 19 < 7; } /** * Number of months in this Hebrew year (either 12 or 13 depending on leap year) * @param year Hebrew year */ function monthsInYear(year) { return 12 + +isLeapYear(year); // boolean is cast to 1 or 0 } /** * Number of days in Hebrew month in a given year (29 or 30) * @param month Hebrew month (e.g. months.TISHREI) * @param year Hebrew year */ function daysInMonth(month, year) { switch (month) { case IYYAR$1: case TAMUZ$1: case ELUL$1: case TEVET$2: case ADAR_II$2: return 29; } if (month === ADAR_I$2 && !isLeapYear(year) || month === CHESHVAN$1 && !longCheshvan(year) || month === KISLEV$2 && shortKislev(year)) { return 29; } else { return 30; } } /** * Returns a transliterated string name of Hebrew month in year, * for example 'Elul' or 'Cheshvan'. * @param month Hebrew month (e.g. months.TISHREI) * @param year Hebrew year */ function getMonthName(month, year) { assertNumber(month, 'month'); assertNumber(year, 'year'); if (month < 1 || month > 14) { throw new TypeError(`bad monthNum: ${month}`); } return monthNames[+isLeapYear(year)][month]; } /** * Days from sunday prior to start of Hebrew calendar to mean * conjunction of Tishrei in Hebrew YEAR * @param year Hebrew year */ function elapsedDays(year) { const n = edCache.get(year); if (typeof n === 'number') { return n; } const elapsed = elapsedDays0(year); edCache.set(year, elapsed); return elapsed; } /** * Days from sunday prior to start of Hebrew calendar to mean * conjunction of Tishrei in Hebrew YEAR * @private * @param year Hebrew year */ function elapsedDays0(year) { const prevYear = year - 1; const mElapsed = 235 * Math.floor(prevYear / 19) + // Months in complete 19 year lunar (Metonic) cycles so far 12 * (prevYear % 19) + // Regular months in this cycle Math.floor((prevYear % 19 * 7 + 1) / 19); // Leap months this cycle const pElapsed = 204 + 793 * (mElapsed % 1080); const hElapsed = 5 + 12 * mElapsed + 793 * Math.floor(mElapsed / 1080) + Math.floor(pElapsed / 1080); const parts = pElapsed % 1080 + 1080 * (hElapsed % 24); const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24); let altDay = day; if (parts >= 19440 || 2 === day % 7 && parts >= 9924 && !isLeapYear(year) || 1 === day % 7 && parts >= 16789 && isLeapYear(prevYear)) { altDay++; } if (altDay % 7 === 0 || altDay % 7 === 3 || altDay % 7 === 5) { return altDay + 1; } else { return altDay; } } /** * Number of days in the hebrew YEAR. * A common Hebrew calendar year can have a length of 353, 354 or 355 days * A leap Hebrew calendar year can have a length of 383, 384 or 385 days * @param year Hebrew year */ function daysInYear(year) { return elapsedDays(year + 1) - elapsedDays(year); } /** * true if Cheshvan is long in Hebrew year * @param year Hebrew year */ function longCheshvan(year) { return daysInYear(year) % 10 === 5; } /** * true if Kislev is short in Hebrew year * @param year Hebrew year */ function shortKislev(year) { return daysInYear(year) % 10 === 3; } /** * Converts Hebrew month string name to numeric * @param monthName monthName */ function monthFromName(monthName) { if (typeof monthName === 'number') { if (isNaN(monthName) || monthName < 1 || monthName > 14) { throw new RangeError(`bad monthName: ${monthName}`); } return monthName; } let c = monthName.trim().toLowerCase(); // If Hebrew month starts with a bet (for example `בתמוז`) then ignore it if (c[0] === 'ב') { c = c.substring(1); } /* the Hebrew months are unique to their second letter N Nisan (November?) I Iyyar E Elul C Cheshvan K Kislev 1 1Adar 2 2Adar Si Sh Sivan, Shvat Ta Ti Te Tamuz, Tishrei, Tevet Av Ad Av, Adar אב אד אי אל אב אדר אייר אלול ח חשון ט טבת כ כסלו נ ניסן ס סיון ש שבט תמ תש תמוז תשרי */ switch (c[0]) { case 'n': case 'נ': if (c[1] === 'o') { break; /* this catches "november" */ } return NISAN$4; case 'i': return IYYAR$1; case 'e': return ELUL$1; case 'c': case 'ח': return CHESHVAN$1; case 'k': case 'כ': return KISLEV$2; case 's': switch (c[1]) { case 'i': return SIVAN$1; case 'h': return SHVAT$1; } break; case 't': switch (c[1]) { case 'a': return TAMUZ$1; case 'i': return TISHREI$2; case 'e': return TEVET$2; } break; case 'a': switch (c[1]) { case 'v': return AV$1; case 'd': if (/(1|[^i]i|a|א)$/i.test(monthName)) { return ADAR_I$2; } return ADAR_II$2; // else assume sheini } break; case 'ס': return SIVAN$1; case 'ט': return TEVET$2; case 'ש': return SHVAT$1; case 'א': switch (c[1]) { case 'ב': return AV$1; case 'ד': if (/(1|[^i]i|a|א)$/i.test(monthName)) { return ADAR_I$2; } return ADAR_II$2; // else assume sheini case 'י': return IYYAR$1; case 'ל': return ELUL$1; } break; case 'ת': switch (c[1]) { case 'מ': return TAMUZ$1; case 'ש': return TISHREI$2; } break; } throw new RangeError(`bad monthName: ${monthName}`); } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ const NISAN$3 = months.NISAN; const CHESHVAN = months.CHESHVAN; const KISLEV$1 = months.KISLEV; const TEVET$1 = months.TEVET; const SHVAT = months.SHVAT; const ADAR_I$1 = months.ADAR_I; const ADAR_II$1 = months.ADAR_II; /** * Returns true if the object is a SimpleHebrewDate * @private */ function isSimpleHebrewDate$1(obj) { return typeof obj === 'object' && obj !== null && typeof obj.yy === 'number' && typeof obj.mm === 'number' && typeof obj.dd === 'number'; } /** * @private */ function toSimpleHebrewDate(obj) { if (isSimpleHebrewDate$1(obj)) { return obj; } else if (isDate(obj)) { const abs = greg2abs(obj); return abs2hebrew(abs); } else { // typeof obj === 'number' return abs2hebrew(obj); } } function getYahrzeitHD(hyear, date) { let hDeath = toSimpleHebrewDate(date); if (hyear <= hDeath.yy) { // Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy} return undefined; } if (hDeath.mm === CHESHVAN && hDeath.dd === 30 && !longCheshvan(hDeath.yy + 1)) { // If it's Heshvan 30 it depends on the first anniversary; // if that was not Heshvan 30, use the day before Kislev 1. hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV$1, 1) - 1); } else if (hDeath.mm === KISLEV$1 && hDeath.dd === 30 && shortKislev(hDeath.yy + 1)) { // If it's Kislev 30 it depends on the first anniversary; // if that was not Kislev 30, use the day before Teveth 1. hDeath = abs2hebrew(hebrew2abs(hyear, TEVET$1, 1) - 1); } else if (hDeath.mm === ADAR_II$1) { // If it's Adar II, use the same day in last month of year (Adar or Adar II). hDeath.mm = monthsInYear(hyear); } else if (hDeath.mm === ADAR_I$1 && hDeath.dd === 30 && !isLeapYear(hyear)) { // If it's the 30th in Adar I and year is not a leap year // (so Adar has only 29 days), use the last day in Shevat. hDeath.dd = 30; hDeath.mm = SHVAT; } // In all other cases, use the normal anniversary of the date of death. // advance day to rosh chodesh if needed if (hDeath.mm === CHESHVAN && hDeath.dd === 30 && !longCheshvan(hyear)) { hDeath.mm = KISLEV$1; hDeath.dd = 1; } else if (hDeath.mm === KISLEV$1 && hDeath.dd === 30 && shortKislev(hyear)) { hDeath.mm = TEVET$1; hDeath.dd = 1; } hDeath.yy = hyear; return hDeath; } function getBirthdayHD(hyear, date) { const orig = toSimpleHebrewDate(date); const origYear = orig.yy; if (hyear === origYear) { return orig; } else if (hyear < origYear) { // Hebrew year ${hyear} occurs on or before original date in ${origYear} return undefined; } const isOrigLeap = isLeapYear(origYear); let month = orig.mm; let day = orig.dd; if (month === ADAR_I$1 && !isOrigLeap || month === ADAR_II$1 && isOrigLeap) { month = monthsInYear(hyear); } else if (month === CHESHVAN && day === 30 && !longCheshvan(hyear)) { month = KISLEV$1; day = 1; } else if (month === KISLEV$1 && day === 30 && shortKislev(hyear)) { month = TEVET$1; day = 1; } else if (month === ADAR_I$1 && day === 30 && isOrigLeap && !isLeapYear(hyear)) { month = NISAN$3; day = 1; } return { yy: hyear, mm: month, dd: day }; } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ const GERESH = '׳'; const GERSHAYIM = '״'; const heb2num = { א: 1, ב: 2, ג: 3, ד: 4, ה: 5, ו: 6, ז: 7, ח: 8, ט: 9, י: 10, כ: 20, ל: 30, מ: 40, נ: 50, ס: 60, ע: 70, פ: 80, צ: 90, ק: 100, ר: 200, ש: 300, ת: 400 }; const num2heb = {}; for (const [key, val] of Object.entries(heb2num)) { num2heb[val] = key; } function num2digits(num) { const digits = []; while (num > 0) { if (num === 15 || num === 16) { digits.push(9); digits.push(num - 9); break; } let incr = 100; let i; for (i = 400; i > num; i -= incr) { if (i === incr) { incr = incr / 10; } } digits.push(i); num -= i; } return digits; } /** * Converts a numerical value to a string of Hebrew letters. * * When specifying years of the Hebrew calendar in the present millennium, * we omit the thousands (which is presently 5 [ה]). * @example * gematriya(5774) // 'תשע״ד' - cropped to 774 * gematriya(25) // 'כ״ה' * gematriya(60) // 'ס׳' * gematriya(3761) // 'ג׳תשס״א' * gematriya(1123) // 'א׳קכ״ג' */ function gematriya(num) { const num1 = parseInt(num, 10); if (!num1 || num1 < 0) { throw new TypeError(`invalid number: ${num}`); } let str = ''; const thousands = Math.floor(num1 / 1000); if (thousands > 0 && thousands !== 5) { const tdigits = num2digits(thousands); for (const tdig of tdigits) { str += num2heb[tdig]; } str += GERESH; } const digits = num2digits(num1 % 1000); if (digits.length === 1) { return str + num2heb[digits[0]] + GERESH; } for (let i = 0; i < digits.length; i++) { if (i + 1 === digits.length) { str += GERSHAYIM; } str += num2heb[digits[i]]; } return str; } /** * Converts a string of Hebrew letters to a numerical value. * * Only considers the value of Hebrew letters `א` through `ת`. * Ignores final Hebrew letters such as `ך` (kaf sofit) or `ם` (mem sofit) * and vowels (nekudot). */ function gematriyaStrToNum(str) { let num = 0; const gereshIdx = str.indexOf(GERESH); if (gereshIdx !== -1 && gereshIdx !== str.length - 1) { const thousands = str.substring(0, gereshIdx); num += gematriyaStrToNum(thousands) * 1000; str = str.substring(gereshIdx); } for (const ch of str) { const n = heb2num[ch]; if (typeof n === 'number') { num += n; } } return num; } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /** * Calculates the molad for a Hebrew month */ function molad(year, month) { let m_adj = month - 7; if (m_adj < 0) { m_adj += monthsInYear(year); } const mElapsed = 235 * Math.floor((year - 1) / 19) + // Months in complete 19 year lunar (Metonic) cycles so far 12 * ((year - 1) % 19) + // Regular months in this cycle Math.floor((7 * ((year - 1) % 19) + 1) / 19) + // Leap months this cycle m_adj; // add elapsed months till the start of the molad of the month const pElapsed = 204 + Math.floor(793 * (mElapsed % 1080)); const hElapsed = 5 + 12 * mElapsed + 793 * Math.floor(mElapsed / 1080) + Math.floor(pElapsed / 1080) - 6; const parts = pElapsed % 1080 + 1080 * (hElapsed % 24); const chalakim = parts % 1080; const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24); return { year, month, dayOfWeek: day % 7, hour: hElapsed % 24, minutes: Math.floor(chalakim / 18), chalakim: chalakim % 18 }; } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /** * Formats a number with leading zeros so the resulting string is 4 digits long. * Similar to `string.padStart(4, '0')` but will also format * negative numbers similar to how the JavaScript date formats * negative year numbers (e.g. `-37` is formatted as `-000037`). */ function pad4(num) { if (num < 0) { return '-00' + pad4(-num); } else if (num < 10) { return '000' + num; } else if (num < 100) { return '00' + num; } else if (num < 1000) { return '0' + num; } return String(num); } /** * Formats a number with leading zeros so the resulting string is 2 digits long. * Similar to `string.padStart(2, '0')`. */ function pad2(num) { if (num >= 0 && num < 10) { return '0' + num; } return String(num); } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ const _formatters = new Map(); /** * @private */ function getFormatter$1(tzid) { const fmt = _formatters.get(tzid); if (fmt) return fmt; const f = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: tzid }); _formatters.set(tzid, f); return f; } const dateFormatRegex = /^(\d+).(\d+).(\d+),?\s+(\d+).(\d+).(\d+)/; /** * Returns a string similar to `Date.toISOString()` but in the * timezone `tzid`. Contrary to the typical meaning of `Z` at the end * of the string, this is not actually a UTC date. */ function getPseudoISO(tzid, date) { const str = getFormatter$1(tzid).format(date); const m = dateFormatRegex.exec(str); if (m === null) { throw new Error(`Unable to parse formatted string: ${str}`); } let hour = m[4]; if (hour === '24') { hour = '00'; } m[3] = pad4(parseInt(m[3], 10)); return `${m[3]}-${m[1]}-${m[2]}T${hour}:${m[5]}:${m[6]}Z`; } /** * Returns number of minutes `tzid` is offset from UTC on date `date`. */ function getTimezoneOffset(tzid, date) { const utcStr = getPseudoISO('UTC', date); const localStr = getPseudoISO(tzid, date); const diffMs = new Date(utcStr).getTime() - new Date(localStr).getTime(); return Math.ceil(diffMs / 1000 / 60); } /** * Returns YYYY-MM-DD in the local timezone */ function isoDateString(dt) { return pad4(dt.getFullYear()) + '-' + pad2(dt.getMonth() + 1) + '-' + pad2(dt.getDate()); } /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ var poAshkenazi$1 = { "headers": { "plural-forms": "nplurals=2; plural=(n > 1);", "language": "en_CA@ashkenazi" }, "contexts": { "": { "Tevet": ["Teves"] } } }; /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ var poHe$1 = { "headers": { "plural-forms": "nplurals=2; plural=(n > 1);", "language": "he" }, "contexts": { "": { "Adar": ["אַדָר"], "Adar I": ["אַדָר א׳"], "Adar II": ["אַדָר ב׳"], "Av": ["אָב"], "Cheshvan": ["חֶשְׁוָן"], "Elul": ["אֱלוּל"], "Iyyar": ["אִיָיר"], "Kislev": ["כִּסְלֵו"], "Nisan": ["נִיסָן"], "Sh'vat": ["שְׁבָט"], "Sivan": ["סִיוָן"], "Tamuz": ["תַּמּוּז"], "Tevet": ["טֵבֵת"], "Tishrei": ["תִּשְׁרֵי"] } } }; /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ const noopLocale = { headers: { 'plural-forms': 'nplurals=2; plural=(n!=1);' }, contexts: { '': {} } }; const alias = { h: 'he', a: 'ashkenazi', s: 'en', '': 'en' }; /** @private */ const locales = new Map(); /** @private */ let activeLocale; /** @private */ let activeName; /** @private */ function getEnOrdinal(n) { const s = ['th', 'st', 'nd', 'rd']; const v = n % 100; return n + (s[(v - 20) % 10] || s[v] || s[0]); } /** @private */ function checkLocale(locale) { if (typeof locale !== 'string') { throw new TypeError(`Invalid locale name: ${locale}`); } return locale.toLowerCase(); } /** @private */ function getExistingLocale(locale) { const locale1 = checkLocale(locale); const loc = locales.get(locale1); if (!loc) { throw new RangeError(`Locale '${locale}' not found`); } return loc; } /** * A locale in Hebcal is used for translations/transliterations of * holidays. `@hebcal/hdate` supports four locales by default * * `en` - default, Sephardic transliterations (e.g. "Shabbat") * * `ashkenazi` - Ashkenazi transliterations (e.g. "Shabbos") * * `he` - Hebrew (e.g. "שַׁבָּת") * * `he-x-NoNikud` - Hebrew without nikud (e.g. "שבת") */ class Locale { /** * Returns translation only if `locale` offers a non-empty translation for `id`. * Otherwise, returns `undefined`. * @param id Message ID to translate * @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale. */ static lookupTranslation(id, locale) { const loc = typeof locale === 'string' && locales.get(locale.toLowerCase()) || activeLocale; const array = loc[id]; if ((array === null || array === void 0 ? void 0 : array.length) && array[0].length) { return array[0]; } return undefined; } /** * By default, if no translation was found, returns `id`. * @param id Message ID to translate * @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale. */ static gettext(id, locale) { const text = this.lookupTranslation(id, locale); if (typeof text === 'undefined') { return id; } return text; } /** * Register locale translations. * @param locale Locale name (i.e.: `'he'`, `'fr'`) * @param data parsed data from a `.po` file. */ static addLocale(locale, data) { locale = checkLocale(locale); if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') { throw new TypeError(`Locale '${locale}' invalid compact format`); } locales.set(locale, data.contexts['']); } /** * Adds a translation to `locale`, replacing any previous translation. * @param locale Locale name (i.e: `'he'`, `'fr'`). * @param id Message ID to translate * @param translation Translation text */ static addTranslation(locale, id, translation) { const loc = getExistingLocale(locale); if (typeof id !== 'string' || id.length === 0) { throw new TypeError(`Invalid id string: ${id}`); } const isArray = Array.isArray(translation); if (isArray) { const t0 = translation[0]; if (typeof t0 !== 'string' || t0.length === 0) { throw new TypeError(`Invalid translation array: ${translation}`); } } else if (typeof translation !== 'string') { throw new TypeError(`Invalid translation string: ${translation}`); } loc[id] = isArray ? translation : [translation]; } /** * Adds multiple translations to `locale`, replacing any previous translations. * @param locale Locale name (i.e: `'he'`, `'fr'`). * @param data parsed data from a `.po` file. */ static addTranslations(locale, data) { const loc = getExistingLocale(locale); if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') { throw new TypeError(`Locale '${locale}' invalid compact format`); } const ctx = data.contexts['']; Object.assign(loc, ctx); } /** * Activates a locale. Throws an error if the locale has not been previously added. * After setting the locale to be used, all strings marked for translations * will be represented by the corresponding translation in the specified locale. * @param locale Locale name (i.e: `'he'`, `'fr'`) * @deprecated */ static useLocale(locale) { const locale0 = checkLocale(locale); const obj = getExistingLocale(locale0); activeName = alias[locale0] || locale0; activeLocale = obj; return activeLocale; } /** * Returns the name of the active locale (i.e. 'he', 'ashkenazi', 'fr') * @deprecated */ static getLocaleName() { return activeName; } /** * Returns the names of registered locales */ static getLocaleNames() { const keys = Array.from(locales.keys()); return keys.sort((a, b) => a.localeCompare(b)); } /** * Renders a number in ordinal, such as 1st, 2nd or 3rd * @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale. */ static ordinal(n, locale) { const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase(); const locale0 = locale1 || activeName; if (!locale0) { return getEnOrdinal(n); } switch (locale0) { case 'en': case 's': case 'a': return getEnOrdinal(n); case 'es': return n + 'º'; case 'h': case 'he': case 'he-x-nonikud': return String(n); } if (locale0.startsWith('ashkenazi')) { return getEnOrdinal(n); } return n + '.'; } /** * Removes nekudot from Hebrew string */ static hebrewStripNikkud(str) { const a = str.normalize(); // now strip out niqqud and trope return a.replace(/[\u0590-\u05bd]/g, '').replace(/[\u05bf-\u05c7]/g, ''); } } Locale.addLocale('en', noopLocale); Locale.addLocale('s', noopLocale); Locale.addLocale('', noopLocale); Locale.useLocale('en'); /* Ashkenazic transliterations */ Locale.addLocale('ashkenazi', poAshkenazi$1); Locale.addLocale('a', poAshkenazi$1); /* Hebrew with nikkud */ Locale.addLocale('he', poHe$1); Locale.addLocale('h', poHe$1); /* Hebrew without nikkud */ const heStrs$1 = poHe$1.contexts['']; const heNoNikud$1 = {}; for (const [key, val] of Object.entries(heStrs$1)) { heNoNikud$1[key] = [Locale.hebrewStripNikkud(val[0])]; } const poHeNoNikud$1 = { headers: poHe$1.headers, contexts: { '': heNoNikud$1 } }; Locale.addLocale('he-x-NoNikud', poHeNoNikud$1); /*! @hebcal/hdate v0.14.2, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */ /* Hebcal - A Jewish Calendar Generator Copyright (c) 1994-2020 Danny Sadinoff Portions copyright Eyal Schachter and Michael J. Radwin https://github.com/hebcal/hebcal-es6 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ function mod(x, y) { return x - y * Math.floor(x / y); } function isSimpleHebrewDate(obj) { return obj.yy !== undefined; } const UNITS_DAY = 'day'; const UNITS_WEEK = 'week'; const UNITS_MONTH = 'month'; const UNITS_YEAR = 'year'; /** * A `HDate` represents a Hebrew calendar date. * * An instance of this class encapsulates a date in the Hebrew calendar system. * It consists of a year, month, and day, without any associated time or location data. * The Hebrew calendar is a lunisolar calendar, meaning it is based on both lunar and solar cycles. * * A Hebrew date internally stores three numbers: * - year: The Hebrew year (1-9999). Counted from the traditional Hebrew date of creation (3761 BCE in the Gregorian calendar) * - month: The Hebrew month (1-13). Month 1 is Nisan, month 7 is Tishrei. There are 12 months in a regular year and 13 months in a leap year. * - day: The day of the month (1-30) * * This class uses Rata Die to convert between the Hebrew and Gregorian calendars. * * To calculate times of day, use `Zmanim` class from `@hebcal/core` * @see {@link https://en.wikipedia.org/wiki/Rata_Die | Rata Die} * @see {@link https://hebcal.github.io/api/core/classes/Zmanim.html | Zmanim} */ class HDate { /** * Create a Hebrew date. There are 3 basic forms for the `HDate()` constructor. * * 1. No parameters - represents the current Hebrew date at time of instantiation * 2. One parameter * * `Date` - represents the Hebrew date corresponding to the Gregorian date using * local time. Hours, minutes, seconds and milliseconds are ignored. * * `HDate` - clones a copy of the given Hebrew date * * `number` - Converts absolute R.D. days to Hebrew date. * R.D. 1 == the imaginary date January 1, 1 (Gregorian) * 3. Three parameters: Hebrew day, Hebrew month, Hebrew year. Hebrew day should * be a number between 1-30, Hebrew month can be a number or string, and * Hebrew year is always a number. * @example * import {HDate, months} from '@hebcal/hdate'; * * const hd1 = new HDate(); * const hd2 = new HDate(new Date(2008, 10, 13)); * const hd3 = new HDate(15, 'Cheshvan', 5769); * const hd4 = new HDate(15, months.CHESHVAN, 5769); * const hd5 = new HDate(733359); // ==> 15 Cheshvan 5769 * const monthName = 'אייר'; * const hd6 = new HDate(5, monthName, 5773); * @param [day] - Day of month (1-30) if a `number`. * If a `Date` is specified, represents the Hebrew date corresponding to the * Gregorian date using local time. * If an `HDate` is specified, clones a copy of the given Hebrew date. * @param [month] - Hebrew month of year (1=NISAN, 7=TISHREI) * @param [year] - Hebrew year */ constructor(day, month, year) { if (arguments.length === 2 || arguments.length > 3) { throw new TypeError('HDate constructor requires 0, 1 or 3 arguments'); } if (arguments.length === 3) { // Hebrew day, Hebrew month, Hebrew year this.dd = this.mm = 1; const yy = typeof year === 'string' ? parseInt(year, 10) : year; if (isNaN(yy)) { throw new TypeError(`HDate called with bad year: ${year}`); } this.yy = yy; setMonth(this, month); // will throw if we can't parse const dd = typeof day === 'string' ? parseInt(day, 10) : day; if (isNaN(dd)) { throw new TypeError(`HDate called with bad day: ${day}`); } setDate(this, dd); } else { // 0 arguments if (typeof day === 'undefined' || day === null) { day = new Date(); } // 1 argument const abs0 = typeof day === 'number' && !isNaN(day) ? day : isDate(day) ? greg2abs(day) : isSimpleHebrewDate(day) ? day : null; if (abs0 === null) { throw new TypeError(`HDate called with bad arg: ${day}`); } const isNumber = typeof abs0 === 'number'; const d = isNumber ? abs2hebrew(abs0) : abs0; this.yy = d.yy; this.mm = d.mm; this.dd = d.dd; if (isNumber) { this.rd = abs0; } } } /** * Returns the Hebrew year of this Hebrew date * @returns an integer >= 1 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getFullYear(); // 5769 */ getFullYear() { return this.yy; } /** * Returns `true` if this Hebrew date occurs during a Hebrew leap year * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.isLeapYear(); // false */ isLeapYear() { return isLeapYear(this.yy); } /** * Returns the Hebrew month (1=NISAN, 7=TISHREI) of this Hebrew date * @returns an integer 1-13 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getMonth(); // 8 */ getMonth() { return this.mm; } /** * The Tishrei-based month of this Hebrew date. 1 is Tishrei, 7 is Nisan, 13 is Elul in a leap year * @returns an integer 1-13 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getTishreiMonth(); // 2 */ getTishreiMonth() { const nummonths = monthsInYear(this.getFullYear()); return (this.getMonth() + nummonths - 6) % nummonths || nummonths; } /** * Number of days in the month of this Hebrew date (29 or 30) * @returns an integer 29-30 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.daysInMonth(); // 29 */ daysInMonth() { return daysInMonth(this.getMonth(), this.getFullYear()); } /** * Gets the day within the month (1-30) * @returns an integer 1-30 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getDate(); // 15 */ getDate() { return this.dd; } /** * Returns the day of the week for this Hebrew date, * where 0 represents Sunday, 1 represents Monday, 6 represents Saturday. * * For the day of the month, see `getDate()` * @returns an integer 0-6 * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getDate(); // 4 */ getDay() { return mod(this.abs(), 7); } /** * Converts this Hebrew date to the corresponding Gregorian date. * * The returned `Date` object will be in the local (i.e. host system) time zone. * Hours, minutes, seconds and milliseconds will all be zero. * * Note that this function returns the daytime portion of the date. * For example, the 15th of Cheshvan 5769 began at sundown on * 12 November 2008 and continues through 13 November 2008. This * function would return only the date 13 November 2008. * @example * const hd = new HDate(15, 'Cheshvan', 5769); * const date = hd.greg(); // 13 November 2008 * const year = date.getFullYear(); // 2008 * const monthNum = date.getMonth() + 1; // 11 * const day = date.getDate(); // 13 */ greg() { return abs2greg(this.abs()); } /** * Converts from Hebrew date representation to R.D. (Rata Die) fixed days. * R.D. 1 is the imaginary date Monday, January 1, 1 (Gregorian). * Note also that R.D. = Julian Date − 1,721,424.5 * @see {@link https://en.wikipedia.org/wiki/Rata_Die | Rata Die} * @example * const hd = new HDate(15, 'Cheshvan', 5769); * hd.abs(); // 733359 */ abs() { if (typeof this.rd !== 'number') { this.rd = hebrew2abs(this.yy, this.mm, this.dd); } return this.rd; } /** * Converts Hebrew date to R.D. (Rata Die) fixed days. * R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian * Calendar. * @param year Hebrew year * @param month Hebrew month (1=NISAN, 7=TISHREI) * @param day Hebrew date (1-30) * @example * import {HDate, months} from '@hebcal/hdate'; * HDate.hebrew2abs(5769, months.CHESHVAN, 15); // 733359 */ static hebrew2abs(year, month, day) { return hebrew2abs(year, month, day); } /** * Returns a transliterated Hebrew month name, e.g. `'Elul'` or `'Cheshvan'`. * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.getMonthName(); // 'Cheshvan' */ getMonthName() { return getMonthName(this.getMonth(), this.getFullYear()); } /** * Renders this Hebrew date as a translated or transliterated string, * including ordinal e.g. `'15th of Cheshvan, 5769'`. * @example * import {HDate, months} from '@hebcal/hdate'; * * const hd = new HDate(15, months.CHESHVAN, 5769); * console.log(hd.render('en')); // '15th of Cheshvan, 5769' * console.log(hd.render('he')); // '15 חֶשְׁוָן, 5769' * console.log(hd.render('en', false)); // '15th of Cheshvan' * console.log(hd.render('he', false)); // '15 חֶשְׁוָן' * @param [locale] Optional locale name (defaults to active locale). * @param [showYear=true] Display year (defaults to true). * @see {@link Locale} */ render(locale) { let showYear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; const locale0 = locale || Locale.getLocaleName(); const day = this.getDate(); const monthName0 = Locale.gettext(this.getMonthName(), locale0); const monthName = monthName0.replace(/'/g, '’'); const nth = Locale.ordinal(day, locale0); const dayOf = getDayOfTranslation(locale0); const dateStr = `${nth}${dayOf} ${monthName}`; if (showYear) { const fullYear = this.getFullYear(); return `${dateStr}, ${fullYear}`; } else { return dateStr; } } /** * Renders this Hebrew date in Hebrew gematriya, regardless of locale. * @example * import {HDate, months} from '@hebcal/hdate'; * const hd = new HDate(15, months.CHESHVAN, 5769); * hd.renderGematriya(); // 'ט״ו חֶשְׁוָן תשס״ט' * hd.renderGematriya(true); // 'ט״ו חשון תשס״ט' */ renderGematriya() { let suppressNikud = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; const d = this.getDate(); const locale = suppressNikud ? 'he-x-NoNikud' : 'he'; const m = Locale.gettext(this.getMonthName(), locale); const y = this.getFullYear(); return gematriya(d) + ' ' + m + ' ' + gematriya(y); } /** * Returns an `HDate` corresponding to the specified day of week * **before** this Hebrew date * @example * new HDate(new Date('Wednesday February 19, 2014')).before(6).greg() // Sat Feb 15 2014 * @param dayOfWeek day of week: Sunday=0, Saturday=6 */ before(dayOfWeek) { return onOrBefore(dayOfWeek, this, -1); } /** * Returns an `HDate` corresponding to the specified day of week * **on or before** this Hebrew date * @example * new HDate(new Date('Wednesday February 19, 2014')).onOrBefore(6).greg() // Sat Feb 15 2014 * new HDate(new Date('Saturday February 22, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014 * new HDate(new Date('Sunday February 23, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014 * @param dayOfWeek day of week: Sunday=0, Saturday=6 */ onOrBefore(dayOfWeek) { return onOrBefore(dayOfWeek, this, 0); } /** * Returns an `HDate` corresponding to the specified day of week * **nearest** to this Hebrew date * @example * new HDate(new Date('Wednesday February 19, 2014')).nearest(6).greg() // Sat Feb 22 2014 * new HDate(new Date('Tuesday February 18, 2014')).nearest(6).greg() // Sat Feb 15 2014 * @param dayOfWeek day of week: Sunday=0, Saturday=6 */ nearest(dayOfWeek) { return onOrBefore(dayOfWeek, this, 3); } /** * Returns an `HDate` corresponding to the specified day of week * **on or after** this Hebrew date * @example * new HDate(new Date('Wednesday February 19, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014 * new HDate(new Date('Saturday February 22, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014 * new HDate(new Date('Sunday February 23, 2014')).onOrAfter(6).greg() // Sat Mar 01 2014 * @param dayOfWeek day of week: Sunday=0, Saturday=6 */ onOrAfter(dayOfWeek) { return onOrBefore(dayOfWeek, this, 6); } /** * Returns an `HDate` corresponding to the specified day of week * **after** this Hebrew date * @example * new HDate(new Date('Wednesday February 19, 2014')).after(6).greg() // Sat Feb 22 2014 * new HDate(new Date('Saturday February 22, 2014')).after(6).greg() // Sat Mar 01 2014 * new HDate(new Date('Sunday February 23, 2014')).after(6).greg() // Sat Mar 01 2014 * @param dayOfWeek day of week: Sunday=0, Saturday=6 */ after(dayOfWeek) { return onOrBefore(dayOfWeek, this, 7); } /** * Returns the next Hebrew date * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.next(); // '16 Cheshvan 5769' */ next() { return new HDate(this.abs() + 1); } /** * Returns the previous Hebrew date * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.prev(); // '14 Cheshvan 5769' */ prev() { return new HDate(this.abs() - 1); } /** * Returns a cloned `HDate` object with a specified amount of time added * * Units are case insensitive, and support plural and short forms. * Note, short forms are case sensitive. * * | Unit | Shorthand | Description * | --- | --- | --- | * | `day` | `d` | days | * | `week` | `w` | weeks | * | `month` | `M` | months | * | `year` | `y` | years | */ add(amount) { let units = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd'; amount = typeof amount === 'string' ? parseInt(amount, 10) : amount; if (!amount) { return new HDate(this); } units = standardizeUnits(units); if (units === UNITS_DAY) { return new HDate(this.abs() + amount); } else if (units === UNITS_WEEK) { return new HDate(this.abs() + 7 * amount); } else if (units === UNITS_YEAR) { return new HDate(this.getDate(), this.getMonth(), this.getFullYear() + amount); } else { // units === UNITS_MONTH let hd = new HDate(this); const sign = amount > 0 ? 1 : -1; amount = Math.abs(amount); for (let i = 0; i < amount; i++) { hd = new HDate(hd.abs() + sign * hd.daysInMonth()); } return hd; } } /** * Returns a cloned `HDate` object with a specified amount of time subracted * * Units are case insensitive, and support plural and short forms. * Note, short forms are case sensitive. * * | Unit | Shorthand | Description * | --- | --- | --- | * | `day` | `d` | days | * | `week` | `w` | weeks | * | `month` | `M` | months | * | `year` | `y` | years | * @example * import {HDate, months} from '@hebcal/hdate'; * * const hd1 = new HDate(15, months.CHESHVAN, 5769); * const hd2 = hd1.add(1, 'weeks'); // 7 Kislev 5769 * const hd3 = hd1.add(-3, 'M'); // 30 Av 5768 */ subtract(amount) { let units = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd'; return this.add(amount * -1, units); } /** * Returns the difference in days between the two given HDates. * * The result is positive if `this` date is comes chronologically * after the `other` date, and negative * if the order of the two dates is reversed. * * The result is zero if the two dates are identical. * @example * import {HDate, months} from '@hebcal/hdate'; * * const hd1 = new HDate(25, months.KISLEV, 5770); * const hd2 = new HDate(15, months.CHESHVAN, 5769); * const days = hd1.deltaDays(hd2); // 394 * @param other Hebrew date to compare */ deltaDays(other) { return this.abs() - other.abs(); } /** * Compares this Hebrew date to another date, returning `true` if the dates match. * @param other Hebrew date to compare * @example * const hd1 = new HDate(new Date(2008, 10, 13)); * const hd2 = new HDate(15, 'Cheshvan', 5769); * hd1.isSameDate(hd2); // true */ isSameDate(other) { return this.yy === other.yy && this.mm === other.mm && this.dd === other.dd; } /** * Returns a string representation of this Hebrew date using English transliterations * @example * const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769 * hd.toString(); // '15 Cheshvan 5769' */ toString() { const day = this.getDate(); const fullYear = this.getFullYear(); const monthName = this.getMonthName(); return `${day} ${monthName} ${fullYear}`; } /** * Returns true if Hebrew year is a leap year * @param year Hebrew year * @example * HDate.isLeapYear(5783); // false * HDate.isLeapYear(5784); // true */ static isLeapYear(year) { return isLeapYear(year); } /** * Number of months in this Hebrew year (either 12 or 13 depending on leap year) * @param year Hebrew year * @example * HDate.monthsInYear(5783); // 12 * HDate.monthsInYear(5784); // 13 */ static monthsInYear(year) { return monthsInYear(year); } /** * Number of days in Hebrew month in a given year (29 or 30) * @param month Hebrew month (e.g. months.TISHREI) * @param year Hebrew year * @example * import {HDate, months} from '@hebcal/hdate'; * HDate.daysInMonth(months.CHESHVAN, 5769); // 29 */ static daysInMonth(month, year) { return daysInMonth(month, year); } /** * Returns a transliterated string name of Hebrew month in year, * for example 'Elul' or 'Cheshvan'. * @param month Hebrew month (e.g. months.TISHREI) * @param year Hebrew year * @example * import {HDate, months} from '@hebcal/hdate'; * HDate.getMonthName(months.CHESHVAN, 5769); // 'Cheshvan' */ static getMonthName(month, year) { return getMonthName(month, year); } /** * Returns the Hebrew month number (NISAN=1, TISHREI=7) * @param month A number, or Hebrew month name string * @example * import {HDate, months} from '@hebcal/hdate'; * HDate.monthNum(months.CHESHVAN); // 8 * HDate.monthNum('Cheshvan'); // 8 * HDate.monthNum('חשון'); // 8 */ static monthNum(month) { if (typeof month === 'number') { if (isNaN(month) || month > 14) { throw new RangeError(`bad monthNum: ${month