@hebcal/core 5.9.5 → 5.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.js +6 -4
- package/dist/bundle.js.map +1 -1
- package/dist/bundle.min.js +4 -4
- package/dist/bundle.min.js.map +1 -1
- package/dist/esm/DailyLearning.js +1 -1
- package/dist/esm/HebrewDateEvent.js +1 -1
- package/dist/esm/HolidayEvent.js +1 -1
- package/dist/esm/MevarchimChodeshEvent.js +1 -1
- package/dist/esm/ParshaEvent.js +1 -1
- package/dist/esm/TimedEvent.js +1 -1
- package/dist/esm/YomKippurKatanEvent.js +1 -1
- package/dist/esm/ashkenazi.po.js +1 -1
- package/dist/esm/calendar.js +1 -1
- package/dist/esm/candles.js +1 -1
- package/dist/esm/event.js +1 -1
- package/dist/esm/getStartAndEnd.js +1 -1
- package/dist/esm/hallel.js +1 -1
- package/dist/esm/he.po.js +1 -1
- package/dist/esm/hebcal.js +1 -1
- package/dist/esm/holidays.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/locale.js +1 -1
- package/dist/esm/location.js +1 -1
- package/dist/esm/modern.js +1 -1
- package/dist/esm/molad.js +1 -1
- package/dist/esm/omer.js +1 -1
- package/dist/esm/parshaName.js +1 -1
- package/dist/esm/parshaYear.js +1 -1
- package/dist/esm/pkgVersion.d.ts +1 -1
- package/dist/esm/pkgVersion.js +2 -2
- package/dist/esm/pkgVersion.js.map +1 -1
- package/dist/esm/reformatTimeStr.js +1 -1
- package/dist/esm/sedra.d.ts +1 -0
- package/dist/esm/sedra.js +5 -3
- package/dist/esm/sedra.js.map +1 -1
- package/dist/esm/staticHolidays.js +1 -1
- package/dist/esm/tachanun.js +1 -1
- package/dist/esm/zmanim.js +1 -1
- package/dist/index.cjs +3182 -243
- package/dist/index.cjs.map +1 -1
- package/dist/pkgVersion.d.ts +1 -1
- package/dist/sedra.d.ts +1 -0
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1,32 +1,1894 @@
|
|
|
1
|
-
/*! @hebcal/core v5.9.
|
|
1
|
+
/*! @hebcal/core v5.9.6, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var hdate = require('@hebcal/hdate');
|
|
5
|
-
var noaa = require('@hebcal/noaa');
|
|
6
4
|
require('temporal-polyfill/global');
|
|
7
5
|
|
|
8
6
|
/** DO NOT EDIT THIS AUTO-GENERATED FILE! */
|
|
9
|
-
const version = '5.9.
|
|
7
|
+
const version = '5.9.6';
|
|
8
|
+
|
|
9
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-namespace, no-inner-declarations */
|
|
11
|
+
/** @private */
|
|
12
|
+
const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
13
|
+
/** @private */
|
|
14
|
+
const monthLengths = [lengths, lengths.slice()];
|
|
15
|
+
monthLengths[1][2] = 29;
|
|
16
|
+
/**
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
function mod$1(x, y) {
|
|
20
|
+
return x - y * Math.floor(x / y);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
function quotient(x, y) {
|
|
26
|
+
return Math.floor(x / y);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @private
|
|
30
|
+
* @param abs - R.D. number of days
|
|
31
|
+
*/
|
|
32
|
+
function yearFromFixed(abs) {
|
|
33
|
+
const l0 = abs - 1;
|
|
34
|
+
const n400 = quotient(l0, 146097);
|
|
35
|
+
const d1 = mod$1(l0, 146097);
|
|
36
|
+
const n100 = quotient(d1, 36524);
|
|
37
|
+
const d2 = mod$1(d1, 36524);
|
|
38
|
+
const n4 = quotient(d2, 1461);
|
|
39
|
+
const d3 = mod$1(d2, 1461);
|
|
40
|
+
const n1 = quotient(d3, 365);
|
|
41
|
+
const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
42
|
+
return n100 !== 4 && n1 !== 4 ? year + 1 : year;
|
|
43
|
+
}
|
|
44
|
+
/*
|
|
45
|
+
const ABS_14SEP1752 = 639797;
|
|
46
|
+
const ABS_2SEP1752 = 639785;
|
|
47
|
+
*/
|
|
48
|
+
/*
|
|
49
|
+
* Formerly in namespace, now top-level
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Returns true if the Gregorian year is a leap year
|
|
53
|
+
* @param year Gregorian year
|
|
54
|
+
*/
|
|
55
|
+
function isGregLeapYear(year) {
|
|
56
|
+
return !(year % 4) && (!!(year % 100) || !(year % 400));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Number of days in the Gregorian month for given year
|
|
60
|
+
* @param month Gregorian month (1=January, 12=December)
|
|
61
|
+
* @param year Gregorian year
|
|
62
|
+
*/
|
|
63
|
+
function daysInGregMonth(month, year) {
|
|
64
|
+
// 1 based months
|
|
65
|
+
return monthLengths[+isGregLeapYear(year)][month];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns true if the object is a Javascript Date
|
|
69
|
+
*/
|
|
70
|
+
function isDate(obj) {
|
|
71
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
72
|
+
return typeof obj === 'object' && Date.prototype.isPrototypeOf(obj);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @private
|
|
76
|
+
* @param year
|
|
77
|
+
* @param month (1-12)
|
|
78
|
+
* @param day (1-31)
|
|
79
|
+
*/
|
|
80
|
+
function toFixed(year, month, day) {
|
|
81
|
+
const py = year - 1;
|
|
82
|
+
return (365 * py +
|
|
83
|
+
quotient(py, 4) -
|
|
84
|
+
quotient(py, 100) +
|
|
85
|
+
quotient(py, 400) +
|
|
86
|
+
quotient(367 * month - 362, 12) +
|
|
87
|
+
(month <= 2 ? 0 : isGregLeapYear(year) ? -1 : -2) +
|
|
88
|
+
day);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
92
|
+
* @param date Gregorian date
|
|
93
|
+
*/
|
|
94
|
+
function greg2abs(date) {
|
|
95
|
+
if (!isDate(date)) {
|
|
96
|
+
throw new TypeError(`not a Date: ${date}`);
|
|
97
|
+
}
|
|
98
|
+
else if (isNaN(date.getTime())) {
|
|
99
|
+
throw new RangeError('Invalid Date');
|
|
100
|
+
}
|
|
101
|
+
const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
102
|
+
/*
|
|
103
|
+
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
104
|
+
throw new RangeError(`Invalid Date: ${date}`);
|
|
105
|
+
}
|
|
106
|
+
*/
|
|
107
|
+
return abs;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Converts from Rata Die (R.D. number) to Gregorian date.
|
|
111
|
+
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
|
|
112
|
+
* Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
|
|
113
|
+
* Clamen, Software--Practice and Experience, Volume 23, Number 4
|
|
114
|
+
* (April, 1993), pages 383-404 for an explanation.
|
|
115
|
+
*
|
|
116
|
+
* Note that this function returns the daytime portion of the date.
|
|
117
|
+
* For example, the 15th of Cheshvan 5769 began at sundown on
|
|
118
|
+
* 12 November 2008 and continues through 13 November 2008. This
|
|
119
|
+
* function would return only the date 13 November 2008.
|
|
120
|
+
* @param abs - R.D. number of days
|
|
121
|
+
* @example
|
|
122
|
+
* const abs = hebrew2abs(5769, months.CHESHVAN, 15);
|
|
123
|
+
* const date = abs2greg(abs); // 13 November 2008
|
|
124
|
+
* const year = date.getFullYear(); // 2008
|
|
125
|
+
* const monthNum = date.getMonth() + 1; // 11
|
|
126
|
+
* const day = date.getDate(); // 13
|
|
127
|
+
*/
|
|
128
|
+
function abs2greg(abs) {
|
|
129
|
+
if (typeof abs !== 'number' || isNaN(abs)) {
|
|
130
|
+
throw new TypeError(`not a Number: ${abs}`);
|
|
131
|
+
}
|
|
132
|
+
abs = Math.trunc(abs);
|
|
133
|
+
/*
|
|
134
|
+
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
135
|
+
throw new RangeError(`Invalid Date: ${abs}`);
|
|
136
|
+
}
|
|
137
|
+
*/
|
|
138
|
+
const year = yearFromFixed(abs);
|
|
139
|
+
const priorDays = abs - toFixed(year, 1, 1);
|
|
140
|
+
const correction = abs < toFixed(year, 3, 1) ? 0 : isGregLeapYear(year) ? 1 : 2;
|
|
141
|
+
const month = quotient(12 * (priorDays + correction) + 373, 367);
|
|
142
|
+
const day = abs - toFixed(year, month, 1) + 1;
|
|
143
|
+
const dt = new Date(year, month - 1, day);
|
|
144
|
+
if (year < 100 && year >= 0) {
|
|
145
|
+
dt.setFullYear(year);
|
|
146
|
+
}
|
|
147
|
+
return dt;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
151
|
+
|
|
152
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-namespace */
|
|
153
|
+
/**
|
|
154
|
+
* Gregorian date helper functions
|
|
155
|
+
*/
|
|
156
|
+
exports.greg = void 0;
|
|
157
|
+
(function (greg) {
|
|
158
|
+
})(exports.greg || (exports.greg = {}));
|
|
159
|
+
exports.greg.abs2greg = abs2greg;
|
|
160
|
+
exports.greg.daysInMonth = daysInGregMonth;
|
|
161
|
+
exports.greg.greg2abs = greg2abs;
|
|
162
|
+
exports.greg.isDate = isDate;
|
|
163
|
+
exports.greg.isLeapYear = isGregLeapYear;
|
|
164
|
+
|
|
165
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
166
|
+
/*
|
|
167
|
+
* More minimal HDate
|
|
168
|
+
*/
|
|
169
|
+
const NISAN$4 = 1;
|
|
170
|
+
const IYYAR$1 = 2;
|
|
171
|
+
const SIVAN$1 = 3;
|
|
172
|
+
const TAMUZ$1 = 4;
|
|
173
|
+
const AV$1 = 5;
|
|
174
|
+
const ELUL$1 = 6;
|
|
175
|
+
const TISHREI$2 = 7;
|
|
176
|
+
const CHESHVAN$1 = 8;
|
|
177
|
+
const KISLEV$2 = 9;
|
|
178
|
+
const TEVET$2 = 10;
|
|
179
|
+
const SHVAT$1 = 11;
|
|
180
|
+
const ADAR_I$2 = 12;
|
|
181
|
+
const ADAR_II$2 = 13;
|
|
182
|
+
/**
|
|
183
|
+
* Hebrew months of the year (NISAN=1, TISHREI=7)
|
|
184
|
+
* @readonly
|
|
185
|
+
* @enum {number}
|
|
186
|
+
*/
|
|
187
|
+
const months = {
|
|
188
|
+
/** Nissan / ניסן */
|
|
189
|
+
NISAN: NISAN$4,
|
|
190
|
+
/** Iyyar / אייר */
|
|
191
|
+
IYYAR: IYYAR$1,
|
|
192
|
+
/** Sivan / סיון */
|
|
193
|
+
SIVAN: SIVAN$1,
|
|
194
|
+
/** Tamuz (sometimes Tammuz) / תמוז */
|
|
195
|
+
TAMUZ: TAMUZ$1,
|
|
196
|
+
/** Av / אב */
|
|
197
|
+
AV: AV$1,
|
|
198
|
+
/** Elul / אלול */
|
|
199
|
+
ELUL: ELUL$1,
|
|
200
|
+
/** Tishrei / תִּשְׁרֵי */
|
|
201
|
+
TISHREI: TISHREI$2,
|
|
202
|
+
/** Cheshvan / חשון */
|
|
203
|
+
CHESHVAN: CHESHVAN$1,
|
|
204
|
+
/** Kislev / כסלו */
|
|
205
|
+
KISLEV: KISLEV$2,
|
|
206
|
+
/** Tevet / טבת */
|
|
207
|
+
TEVET: TEVET$2,
|
|
208
|
+
/** Sh'vat / שבט */
|
|
209
|
+
SHVAT: SHVAT$1,
|
|
210
|
+
/** Adar or Adar Rishon / אדר */
|
|
211
|
+
ADAR_I: ADAR_I$2,
|
|
212
|
+
/** Adar Sheini (only on leap years) / אדר ב׳ */
|
|
213
|
+
ADAR_II: ADAR_II$2,
|
|
214
|
+
};
|
|
215
|
+
const NISAN_STR = 'Nisan';
|
|
216
|
+
const monthNames0 = [
|
|
217
|
+
'',
|
|
218
|
+
NISAN_STR,
|
|
219
|
+
'Iyyar',
|
|
220
|
+
'Sivan',
|
|
221
|
+
'Tamuz',
|
|
222
|
+
'Av',
|
|
223
|
+
'Elul',
|
|
224
|
+
'Tishrei',
|
|
225
|
+
'Cheshvan',
|
|
226
|
+
'Kislev',
|
|
227
|
+
'Tevet',
|
|
228
|
+
"Sh'vat",
|
|
229
|
+
];
|
|
230
|
+
/*
|
|
231
|
+
* Transliterations of Hebrew month names.
|
|
232
|
+
* Regular years are index 0 and leap years are index 1.
|
|
233
|
+
* @private
|
|
234
|
+
*/
|
|
235
|
+
const monthNames = [
|
|
236
|
+
[...monthNames0, 'Adar', NISAN_STR],
|
|
237
|
+
[...monthNames0, 'Adar I', 'Adar II', NISAN_STR],
|
|
238
|
+
];
|
|
239
|
+
const edCache = new Map();
|
|
240
|
+
const EPOCH = -1373428;
|
|
241
|
+
// Avg year length in the cycle (19 solar years with 235 lunar months)
|
|
242
|
+
const AVG_HEBYEAR_DAYS = 365.24682220597794;
|
|
243
|
+
/**
|
|
244
|
+
* @private
|
|
245
|
+
*/
|
|
246
|
+
function assertNumber(n, name) {
|
|
247
|
+
if (typeof n !== 'number' || isNaN(n)) {
|
|
248
|
+
throw new TypeError(`param '${name}' not a number: ${n}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Converts Hebrew date to R.D. (Rata Die) fixed days.
|
|
253
|
+
* R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian
|
|
254
|
+
* Calendar.
|
|
255
|
+
* @param year Hebrew year
|
|
256
|
+
* @param month Hebrew month
|
|
257
|
+
* @param day Hebrew date (1-30)
|
|
258
|
+
* @example
|
|
259
|
+
* const abs = hebrew2abs(5769, months.CHESHVAN, 15);
|
|
260
|
+
*/
|
|
261
|
+
function hebrew2abs(year, month, day) {
|
|
262
|
+
assertNumber(year, 'year');
|
|
263
|
+
assertNumber(month, 'month');
|
|
264
|
+
assertNumber(day, 'day');
|
|
265
|
+
if (year < 1) {
|
|
266
|
+
throw new RangeError(`hebrew2abs: invalid year ${year}`);
|
|
267
|
+
}
|
|
268
|
+
let tempabs = day;
|
|
269
|
+
if (month < TISHREI$2) {
|
|
270
|
+
for (let m = TISHREI$2; m <= monthsInYear(year); m++) {
|
|
271
|
+
tempabs += daysInMonth(m, year);
|
|
272
|
+
}
|
|
273
|
+
for (let m = NISAN$4; m < month; m++) {
|
|
274
|
+
tempabs += daysInMonth(m, year);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
for (let m = TISHREI$2; m < month; m++) {
|
|
279
|
+
tempabs += daysInMonth(m, year);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return EPOCH + elapsedDays(year) + tempabs - 1;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* @private
|
|
286
|
+
*/
|
|
287
|
+
function newYear(year) {
|
|
288
|
+
return EPOCH + elapsedDays(year);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Converts absolute R.D. days to Hebrew date
|
|
292
|
+
* @param abs absolute R.D. days
|
|
293
|
+
*/
|
|
294
|
+
function abs2hebrew(abs) {
|
|
295
|
+
assertNumber(abs, 'abs');
|
|
296
|
+
abs = Math.trunc(abs);
|
|
297
|
+
if (abs <= EPOCH) {
|
|
298
|
+
throw new RangeError(`abs2hebrew: ${abs} is before epoch`);
|
|
299
|
+
}
|
|
300
|
+
// first, quickly approximate year
|
|
301
|
+
let year = Math.floor((abs - EPOCH) / AVG_HEBYEAR_DAYS);
|
|
302
|
+
while (newYear(year) <= abs) {
|
|
303
|
+
++year;
|
|
304
|
+
}
|
|
305
|
+
--year;
|
|
306
|
+
let month = abs < hebrew2abs(year, 1, 1) ? 7 : 1;
|
|
307
|
+
while (abs > hebrew2abs(year, month, daysInMonth(month, year))) {
|
|
308
|
+
++month;
|
|
309
|
+
}
|
|
310
|
+
const day = 1 + abs - hebrew2abs(year, month, 1);
|
|
311
|
+
return { yy: year, mm: month, dd: day };
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Returns true if Hebrew year is a leap year
|
|
315
|
+
* @param year Hebrew year
|
|
316
|
+
*/
|
|
317
|
+
function isLeapYear(year) {
|
|
318
|
+
return (1 + year * 7) % 19 < 7;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Number of months in this Hebrew year (either 12 or 13 depending on leap year)
|
|
322
|
+
* @param year Hebrew year
|
|
323
|
+
*/
|
|
324
|
+
function monthsInYear(year) {
|
|
325
|
+
return 12 + +isLeapYear(year); // boolean is cast to 1 or 0
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Number of days in Hebrew month in a given year (29 or 30)
|
|
329
|
+
* @param month Hebrew month (e.g. months.TISHREI)
|
|
330
|
+
* @param year Hebrew year
|
|
331
|
+
*/
|
|
332
|
+
function daysInMonth(month, year) {
|
|
333
|
+
switch (month) {
|
|
334
|
+
case IYYAR$1:
|
|
335
|
+
case TAMUZ$1:
|
|
336
|
+
case ELUL$1:
|
|
337
|
+
case TEVET$2:
|
|
338
|
+
case ADAR_II$2:
|
|
339
|
+
return 29;
|
|
340
|
+
}
|
|
341
|
+
if ((month === ADAR_I$2 && !isLeapYear(year)) ||
|
|
342
|
+
(month === CHESHVAN$1 && !longCheshvan(year)) ||
|
|
343
|
+
(month === KISLEV$2 && shortKislev(year))) {
|
|
344
|
+
return 29;
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
return 30;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Returns a transliterated string name of Hebrew month in year,
|
|
352
|
+
* for example 'Elul' or 'Cheshvan'.
|
|
353
|
+
* @param month Hebrew month (e.g. months.TISHREI)
|
|
354
|
+
* @param year Hebrew year
|
|
355
|
+
*/
|
|
356
|
+
function getMonthName(month, year) {
|
|
357
|
+
assertNumber(month, 'month');
|
|
358
|
+
assertNumber(year, 'year');
|
|
359
|
+
if (month < 1 || month > 14) {
|
|
360
|
+
throw new TypeError(`bad monthNum: ${month}`);
|
|
361
|
+
}
|
|
362
|
+
return monthNames[+isLeapYear(year)][month];
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Days from sunday prior to start of Hebrew calendar to mean
|
|
366
|
+
* conjunction of Tishrei in Hebrew YEAR
|
|
367
|
+
* @param year Hebrew year
|
|
368
|
+
*/
|
|
369
|
+
function elapsedDays(year) {
|
|
370
|
+
const n = edCache.get(year);
|
|
371
|
+
if (typeof n === 'number') {
|
|
372
|
+
return n;
|
|
373
|
+
}
|
|
374
|
+
const elapsed = elapsedDays0(year);
|
|
375
|
+
edCache.set(year, elapsed);
|
|
376
|
+
return elapsed;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Days from sunday prior to start of Hebrew calendar to mean
|
|
380
|
+
* conjunction of Tishrei in Hebrew YEAR
|
|
381
|
+
* @private
|
|
382
|
+
* @param year Hebrew year
|
|
383
|
+
*/
|
|
384
|
+
function elapsedDays0(year) {
|
|
385
|
+
const prevYear = year - 1;
|
|
386
|
+
const mElapsed = 235 * Math.floor(prevYear / 19) + // Months in complete 19 year lunar (Metonic) cycles so far
|
|
387
|
+
12 * (prevYear % 19) + // Regular months in this cycle
|
|
388
|
+
Math.floor(((prevYear % 19) * 7 + 1) / 19); // Leap months this cycle
|
|
389
|
+
const pElapsed = 204 + 793 * (mElapsed % 1080);
|
|
390
|
+
const hElapsed = 5 +
|
|
391
|
+
12 * mElapsed +
|
|
392
|
+
793 * Math.floor(mElapsed / 1080) +
|
|
393
|
+
Math.floor(pElapsed / 1080);
|
|
394
|
+
const parts = (pElapsed % 1080) + 1080 * (hElapsed % 24);
|
|
395
|
+
const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24);
|
|
396
|
+
let altDay = day;
|
|
397
|
+
if (parts >= 19440 ||
|
|
398
|
+
(2 === day % 7 && parts >= 9924 && !isLeapYear(year)) ||
|
|
399
|
+
(1 === day % 7 && parts >= 16789 && isLeapYear(prevYear))) {
|
|
400
|
+
altDay++;
|
|
401
|
+
}
|
|
402
|
+
if (altDay % 7 === 0 || altDay % 7 === 3 || altDay % 7 === 5) {
|
|
403
|
+
return altDay + 1;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
return altDay;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Number of days in the hebrew YEAR.
|
|
411
|
+
* A common Hebrew calendar year can have a length of 353, 354 or 355 days
|
|
412
|
+
* A leap Hebrew calendar year can have a length of 383, 384 or 385 days
|
|
413
|
+
* @param year Hebrew year
|
|
414
|
+
*/
|
|
415
|
+
function daysInYear(year) {
|
|
416
|
+
return elapsedDays(year + 1) - elapsedDays(year);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* true if Cheshvan is long in Hebrew year
|
|
420
|
+
* @param year Hebrew year
|
|
421
|
+
*/
|
|
422
|
+
function longCheshvan(year) {
|
|
423
|
+
return daysInYear(year) % 10 === 5;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* true if Kislev is short in Hebrew year
|
|
427
|
+
* @param year Hebrew year
|
|
428
|
+
*/
|
|
429
|
+
function shortKislev(year) {
|
|
430
|
+
return daysInYear(year) % 10 === 3;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Converts Hebrew month string name to numeric
|
|
434
|
+
* @param monthName monthName
|
|
435
|
+
*/
|
|
436
|
+
function monthFromName(monthName) {
|
|
437
|
+
if (typeof monthName === 'number') {
|
|
438
|
+
if (isNaN(monthName) || monthName < 1 || monthName > 14) {
|
|
439
|
+
throw new RangeError(`bad monthName: ${monthName}`);
|
|
440
|
+
}
|
|
441
|
+
return monthName;
|
|
442
|
+
}
|
|
443
|
+
let c = monthName.trim().toLowerCase();
|
|
444
|
+
// If Hebrew month starts with a bet (for example `בתמוז`) then ignore it
|
|
445
|
+
if (c[0] === 'ב') {
|
|
446
|
+
c = c.substring(1);
|
|
447
|
+
}
|
|
448
|
+
/*
|
|
449
|
+
the Hebrew months are unique to their second letter
|
|
450
|
+
N Nisan (November?)
|
|
451
|
+
I Iyyar
|
|
452
|
+
E Elul
|
|
453
|
+
C Cheshvan
|
|
454
|
+
K Kislev
|
|
455
|
+
1 1Adar
|
|
456
|
+
2 2Adar
|
|
457
|
+
Si Sh Sivan, Shvat
|
|
458
|
+
Ta Ti Te Tamuz, Tishrei, Tevet
|
|
459
|
+
Av Ad Av, Adar
|
|
460
|
+
|
|
461
|
+
אב אד אי אל אב אדר אייר אלול
|
|
462
|
+
ח חשון
|
|
463
|
+
ט טבת
|
|
464
|
+
כ כסלו
|
|
465
|
+
נ ניסן
|
|
466
|
+
ס סיון
|
|
467
|
+
ש שבט
|
|
468
|
+
תמ תש תמוז תשרי
|
|
469
|
+
*/
|
|
470
|
+
switch (c[0]) {
|
|
471
|
+
case 'n':
|
|
472
|
+
case 'נ':
|
|
473
|
+
if (c[1] === 'o') {
|
|
474
|
+
break; /* this catches "november" */
|
|
475
|
+
}
|
|
476
|
+
return NISAN$4;
|
|
477
|
+
case 'i':
|
|
478
|
+
return IYYAR$1;
|
|
479
|
+
case 'e':
|
|
480
|
+
return ELUL$1;
|
|
481
|
+
case 'c':
|
|
482
|
+
case 'ח':
|
|
483
|
+
return CHESHVAN$1;
|
|
484
|
+
case 'k':
|
|
485
|
+
case 'כ':
|
|
486
|
+
return KISLEV$2;
|
|
487
|
+
case 's':
|
|
488
|
+
switch (c[1]) {
|
|
489
|
+
case 'i':
|
|
490
|
+
return SIVAN$1;
|
|
491
|
+
case 'h':
|
|
492
|
+
return SHVAT$1;
|
|
493
|
+
}
|
|
494
|
+
break;
|
|
495
|
+
case 't':
|
|
496
|
+
switch (c[1]) {
|
|
497
|
+
case 'a':
|
|
498
|
+
return TAMUZ$1;
|
|
499
|
+
case 'i':
|
|
500
|
+
return TISHREI$2;
|
|
501
|
+
case 'e':
|
|
502
|
+
return TEVET$2;
|
|
503
|
+
}
|
|
504
|
+
break;
|
|
505
|
+
case 'a':
|
|
506
|
+
switch (c[1]) {
|
|
507
|
+
case 'v':
|
|
508
|
+
return AV$1;
|
|
509
|
+
case 'd':
|
|
510
|
+
if (/(1|[^i]i|a|א)$/i.test(monthName)) {
|
|
511
|
+
return ADAR_I$2;
|
|
512
|
+
}
|
|
513
|
+
return ADAR_II$2; // else assume sheini
|
|
514
|
+
}
|
|
515
|
+
break;
|
|
516
|
+
case 'ס':
|
|
517
|
+
return SIVAN$1;
|
|
518
|
+
case 'ט':
|
|
519
|
+
return TEVET$2;
|
|
520
|
+
case 'ש':
|
|
521
|
+
return SHVAT$1;
|
|
522
|
+
case 'א':
|
|
523
|
+
switch (c[1]) {
|
|
524
|
+
case 'ב':
|
|
525
|
+
return AV$1;
|
|
526
|
+
case 'ד':
|
|
527
|
+
if (/(1|[^i]i|a|א)$/i.test(monthName)) {
|
|
528
|
+
return ADAR_I$2;
|
|
529
|
+
}
|
|
530
|
+
return ADAR_II$2; // else assume sheini
|
|
531
|
+
case 'י':
|
|
532
|
+
return IYYAR$1;
|
|
533
|
+
case 'ל':
|
|
534
|
+
return ELUL$1;
|
|
535
|
+
}
|
|
536
|
+
break;
|
|
537
|
+
case 'ת':
|
|
538
|
+
switch (c[1]) {
|
|
539
|
+
case 'מ':
|
|
540
|
+
return TAMUZ$1;
|
|
541
|
+
case 'ש':
|
|
542
|
+
return TISHREI$2;
|
|
543
|
+
}
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
throw new RangeError(`bad monthName: ${monthName}`);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
550
|
+
|
|
551
|
+
const NISAN$3 = months.NISAN;
|
|
552
|
+
const CHESHVAN = months.CHESHVAN;
|
|
553
|
+
const KISLEV$1 = months.KISLEV;
|
|
554
|
+
const TEVET$1 = months.TEVET;
|
|
555
|
+
const SHVAT = months.SHVAT;
|
|
556
|
+
const ADAR_I$1 = months.ADAR_I;
|
|
557
|
+
const ADAR_II$1 = months.ADAR_II;
|
|
558
|
+
/**
|
|
559
|
+
* Returns true if the object is a SimpleHebrewDate
|
|
560
|
+
* @private
|
|
561
|
+
*/
|
|
562
|
+
function isSimpleHebrewDate$1(obj) {
|
|
563
|
+
return (typeof obj === 'object' &&
|
|
564
|
+
obj !== null &&
|
|
565
|
+
typeof obj.yy === 'number' &&
|
|
566
|
+
typeof obj.mm === 'number' &&
|
|
567
|
+
typeof obj.dd === 'number');
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* @private
|
|
571
|
+
*/
|
|
572
|
+
function toSimpleHebrewDate(obj) {
|
|
573
|
+
if (isSimpleHebrewDate$1(obj)) {
|
|
574
|
+
return obj;
|
|
575
|
+
}
|
|
576
|
+
else if (isDate(obj)) {
|
|
577
|
+
const abs = greg2abs(obj);
|
|
578
|
+
return abs2hebrew(abs);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
// typeof obj === 'number'
|
|
582
|
+
return abs2hebrew(obj);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function getYahrzeitHD(hyear, date) {
|
|
586
|
+
let hDeath = toSimpleHebrewDate(date);
|
|
587
|
+
if (hyear <= hDeath.yy) {
|
|
588
|
+
// Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy}
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
if (hDeath.mm === CHESHVAN &&
|
|
592
|
+
hDeath.dd === 30 &&
|
|
593
|
+
!longCheshvan(hDeath.yy + 1)) {
|
|
594
|
+
// If it's Heshvan 30 it depends on the first anniversary;
|
|
595
|
+
// if that was not Heshvan 30, use the day before Kislev 1.
|
|
596
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV$1, 1) - 1);
|
|
597
|
+
}
|
|
598
|
+
else if (hDeath.mm === KISLEV$1 &&
|
|
599
|
+
hDeath.dd === 30 &&
|
|
600
|
+
shortKislev(hDeath.yy + 1)) {
|
|
601
|
+
// If it's Kislev 30 it depends on the first anniversary;
|
|
602
|
+
// if that was not Kislev 30, use the day before Teveth 1.
|
|
603
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, TEVET$1, 1) - 1);
|
|
604
|
+
}
|
|
605
|
+
else if (hDeath.mm === ADAR_II$1) {
|
|
606
|
+
// If it's Adar II, use the same day in last month of year (Adar or Adar II).
|
|
607
|
+
hDeath.mm = monthsInYear(hyear);
|
|
608
|
+
}
|
|
609
|
+
else if (hDeath.mm === ADAR_I$1 && hDeath.dd === 30 && !isLeapYear(hyear)) {
|
|
610
|
+
// If it's the 30th in Adar I and year is not a leap year
|
|
611
|
+
// (so Adar has only 29 days), use the last day in Shevat.
|
|
612
|
+
hDeath.dd = 30;
|
|
613
|
+
hDeath.mm = SHVAT;
|
|
614
|
+
}
|
|
615
|
+
// In all other cases, use the normal anniversary of the date of death.
|
|
616
|
+
// advance day to rosh chodesh if needed
|
|
617
|
+
if (hDeath.mm === CHESHVAN && hDeath.dd === 30 && !longCheshvan(hyear)) {
|
|
618
|
+
hDeath.mm = KISLEV$1;
|
|
619
|
+
hDeath.dd = 1;
|
|
620
|
+
}
|
|
621
|
+
else if (hDeath.mm === KISLEV$1 && hDeath.dd === 30 && shortKislev(hyear)) {
|
|
622
|
+
hDeath.mm = TEVET$1;
|
|
623
|
+
hDeath.dd = 1;
|
|
624
|
+
}
|
|
625
|
+
hDeath.yy = hyear;
|
|
626
|
+
return hDeath;
|
|
627
|
+
}
|
|
628
|
+
function getBirthdayHD(hyear, date) {
|
|
629
|
+
const orig = toSimpleHebrewDate(date);
|
|
630
|
+
const origYear = orig.yy;
|
|
631
|
+
if (hyear === origYear) {
|
|
632
|
+
return orig;
|
|
633
|
+
}
|
|
634
|
+
else if (hyear < origYear) {
|
|
635
|
+
// Hebrew year ${hyear} occurs on or before original date in ${origYear}
|
|
636
|
+
return undefined;
|
|
637
|
+
}
|
|
638
|
+
const isOrigLeap = isLeapYear(origYear);
|
|
639
|
+
let month = orig.mm;
|
|
640
|
+
let day = orig.dd;
|
|
641
|
+
if ((month === ADAR_I$1 && !isOrigLeap) || (month === ADAR_II$1 && isOrigLeap)) {
|
|
642
|
+
month = monthsInYear(hyear);
|
|
643
|
+
}
|
|
644
|
+
else if (month === CHESHVAN && day === 30 && !longCheshvan(hyear)) {
|
|
645
|
+
month = KISLEV$1;
|
|
646
|
+
day = 1;
|
|
647
|
+
}
|
|
648
|
+
else if (month === KISLEV$1 && day === 30 && shortKislev(hyear)) {
|
|
649
|
+
month = TEVET$1;
|
|
650
|
+
day = 1;
|
|
651
|
+
}
|
|
652
|
+
else if (month === ADAR_I$1 &&
|
|
653
|
+
day === 30 &&
|
|
654
|
+
isOrigLeap &&
|
|
655
|
+
!isLeapYear(hyear)) {
|
|
656
|
+
month = NISAN$3;
|
|
657
|
+
day = 1;
|
|
658
|
+
}
|
|
659
|
+
return { yy: hyear, mm: month, dd: day };
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
663
|
+
const GERESH = '׳';
|
|
664
|
+
const GERSHAYIM = '״';
|
|
665
|
+
const heb2num = {
|
|
666
|
+
א: 1,
|
|
667
|
+
ב: 2,
|
|
668
|
+
ג: 3,
|
|
669
|
+
ד: 4,
|
|
670
|
+
ה: 5,
|
|
671
|
+
ו: 6,
|
|
672
|
+
ז: 7,
|
|
673
|
+
ח: 8,
|
|
674
|
+
ט: 9,
|
|
675
|
+
י: 10,
|
|
676
|
+
כ: 20,
|
|
677
|
+
ל: 30,
|
|
678
|
+
מ: 40,
|
|
679
|
+
נ: 50,
|
|
680
|
+
ס: 60,
|
|
681
|
+
ע: 70,
|
|
682
|
+
פ: 80,
|
|
683
|
+
צ: 90,
|
|
684
|
+
ק: 100,
|
|
685
|
+
ר: 200,
|
|
686
|
+
ש: 300,
|
|
687
|
+
ת: 400,
|
|
688
|
+
};
|
|
689
|
+
const num2heb = {};
|
|
690
|
+
for (const [key, val] of Object.entries(heb2num)) {
|
|
691
|
+
num2heb[val] = key;
|
|
692
|
+
}
|
|
693
|
+
function num2digits(num) {
|
|
694
|
+
const digits = [];
|
|
695
|
+
while (num > 0) {
|
|
696
|
+
if (num === 15 || num === 16) {
|
|
697
|
+
digits.push(9);
|
|
698
|
+
digits.push(num - 9);
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
let incr = 100;
|
|
702
|
+
let i;
|
|
703
|
+
for (i = 400; i > num; i -= incr) {
|
|
704
|
+
if (i === incr) {
|
|
705
|
+
incr = incr / 10;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
digits.push(i);
|
|
709
|
+
num -= i;
|
|
710
|
+
}
|
|
711
|
+
return digits;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Converts a numerical value to a string of Hebrew letters.
|
|
715
|
+
*
|
|
716
|
+
* When specifying years of the Hebrew calendar in the present millennium,
|
|
717
|
+
* we omit the thousands (which is presently 5 [ה]).
|
|
718
|
+
* @example
|
|
719
|
+
* gematriya(5774) // 'תשע״ד' - cropped to 774
|
|
720
|
+
* gematriya(25) // 'כ״ה'
|
|
721
|
+
* gematriya(60) // 'ס׳'
|
|
722
|
+
* gematriya(3761) // 'ג׳תשס״א'
|
|
723
|
+
* gematriya(1123) // 'א׳קכ״ג'
|
|
724
|
+
*/
|
|
725
|
+
function gematriya(num) {
|
|
726
|
+
const num1 = parseInt(num, 10);
|
|
727
|
+
if (!num1 || num1 < 0) {
|
|
728
|
+
throw new TypeError(`invalid number: ${num}`);
|
|
729
|
+
}
|
|
730
|
+
let str = '';
|
|
731
|
+
const thousands = Math.floor(num1 / 1000);
|
|
732
|
+
if (thousands > 0 && thousands !== 5) {
|
|
733
|
+
const tdigits = num2digits(thousands);
|
|
734
|
+
for (const tdig of tdigits) {
|
|
735
|
+
str += num2heb[tdig];
|
|
736
|
+
}
|
|
737
|
+
str += GERESH;
|
|
738
|
+
}
|
|
739
|
+
const digits = num2digits(num1 % 1000);
|
|
740
|
+
if (digits.length === 1) {
|
|
741
|
+
return str + num2heb[digits[0]] + GERESH;
|
|
742
|
+
}
|
|
743
|
+
for (let i = 0; i < digits.length; i++) {
|
|
744
|
+
if (i + 1 === digits.length) {
|
|
745
|
+
str += GERSHAYIM;
|
|
746
|
+
}
|
|
747
|
+
str += num2heb[digits[i]];
|
|
748
|
+
}
|
|
749
|
+
return str;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Converts a string of Hebrew letters to a numerical value.
|
|
753
|
+
*
|
|
754
|
+
* Only considers the value of Hebrew letters `א` through `ת`.
|
|
755
|
+
* Ignores final Hebrew letters such as `ך` (kaf sofit) or `ם` (mem sofit)
|
|
756
|
+
* and vowels (nekudot).
|
|
757
|
+
*/
|
|
758
|
+
function gematriyaStrToNum(str) {
|
|
759
|
+
let num = 0;
|
|
760
|
+
const gereshIdx = str.indexOf(GERESH);
|
|
761
|
+
if (gereshIdx !== -1 && gereshIdx !== str.length - 1) {
|
|
762
|
+
const thousands = str.substring(0, gereshIdx);
|
|
763
|
+
num += gematriyaStrToNum(thousands) * 1000;
|
|
764
|
+
str = str.substring(gereshIdx);
|
|
765
|
+
}
|
|
766
|
+
for (const ch of str) {
|
|
767
|
+
const n = heb2num[ch];
|
|
768
|
+
if (typeof n === 'number') {
|
|
769
|
+
num += n;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return num;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Calculates the molad for a Hebrew month
|
|
779
|
+
*/
|
|
780
|
+
function molad(year, month) {
|
|
781
|
+
let m_adj = month - 7;
|
|
782
|
+
if (m_adj < 0) {
|
|
783
|
+
m_adj += monthsInYear(year);
|
|
784
|
+
}
|
|
785
|
+
const mElapsed = 235 * Math.floor((year - 1) / 19) + // Months in complete 19 year lunar (Metonic) cycles so far
|
|
786
|
+
12 * ((year - 1) % 19) + // Regular months in this cycle
|
|
787
|
+
Math.floor((7 * ((year - 1) % 19) + 1) / 19) + // Leap months this cycle
|
|
788
|
+
m_adj; // add elapsed months till the start of the molad of the month
|
|
789
|
+
const pElapsed = 204 + Math.floor(793 * (mElapsed % 1080));
|
|
790
|
+
const hElapsed = 5 +
|
|
791
|
+
12 * mElapsed +
|
|
792
|
+
793 * Math.floor(mElapsed / 1080) +
|
|
793
|
+
Math.floor(pElapsed / 1080) -
|
|
794
|
+
6;
|
|
795
|
+
const parts = (pElapsed % 1080) + 1080 * (hElapsed % 24);
|
|
796
|
+
const chalakim = parts % 1080;
|
|
797
|
+
const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24);
|
|
798
|
+
return {
|
|
799
|
+
year,
|
|
800
|
+
month,
|
|
801
|
+
dayOfWeek: day % 7,
|
|
802
|
+
hour: hElapsed % 24,
|
|
803
|
+
minutes: Math.floor(chalakim / 18),
|
|
804
|
+
chalakim: chalakim % 18,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
809
|
+
/**
|
|
810
|
+
* Formats a number with leading zeros so the resulting string is 4 digits long.
|
|
811
|
+
* Similar to `string.padStart(4, '0')` but will also format
|
|
812
|
+
* negative numbers similar to how the JavaScript date formats
|
|
813
|
+
* negative year numbers (e.g. `-37` is formatted as `-000037`).
|
|
814
|
+
*/
|
|
815
|
+
function pad4(num) {
|
|
816
|
+
if (num < 0) {
|
|
817
|
+
return '-00' + pad4(-num);
|
|
818
|
+
}
|
|
819
|
+
else if (num < 10) {
|
|
820
|
+
return '000' + num;
|
|
821
|
+
}
|
|
822
|
+
else if (num < 100) {
|
|
823
|
+
return '00' + num;
|
|
824
|
+
}
|
|
825
|
+
else if (num < 1000) {
|
|
826
|
+
return '0' + num;
|
|
827
|
+
}
|
|
828
|
+
return String(num);
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Formats a number with leading zeros so the resulting string is 2 digits long.
|
|
832
|
+
* Similar to `string.padStart(2, '0')`.
|
|
833
|
+
*/
|
|
834
|
+
function pad2(num) {
|
|
835
|
+
if (num >= 0 && num < 10) {
|
|
836
|
+
return '0' + num;
|
|
837
|
+
}
|
|
838
|
+
return String(num);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
842
|
+
|
|
843
|
+
const _formatters = new Map();
|
|
844
|
+
/**
|
|
845
|
+
* @private
|
|
846
|
+
*/
|
|
847
|
+
function getFormatter$1(tzid) {
|
|
848
|
+
const fmt = _formatters.get(tzid);
|
|
849
|
+
if (fmt)
|
|
850
|
+
return fmt;
|
|
851
|
+
const f = new Intl.DateTimeFormat('en-US', {
|
|
852
|
+
year: 'numeric',
|
|
853
|
+
month: '2-digit',
|
|
854
|
+
day: '2-digit',
|
|
855
|
+
hour: '2-digit',
|
|
856
|
+
minute: '2-digit',
|
|
857
|
+
second: '2-digit',
|
|
858
|
+
hour12: false,
|
|
859
|
+
timeZone: tzid,
|
|
860
|
+
});
|
|
861
|
+
_formatters.set(tzid, f);
|
|
862
|
+
return f;
|
|
863
|
+
}
|
|
864
|
+
const dateFormatRegex = /^(\d+).(\d+).(\d+),?\s+(\d+).(\d+).(\d+)/;
|
|
865
|
+
/**
|
|
866
|
+
* Returns a string similar to `Date.toISOString()` but in the
|
|
867
|
+
* timezone `tzid`. Contrary to the typical meaning of `Z` at the end
|
|
868
|
+
* of the string, this is not actually a UTC date.
|
|
869
|
+
*/
|
|
870
|
+
function getPseudoISO(tzid, date) {
|
|
871
|
+
const str = getFormatter$1(tzid).format(date);
|
|
872
|
+
const m = dateFormatRegex.exec(str);
|
|
873
|
+
if (m === null) {
|
|
874
|
+
throw new Error(`Unable to parse formatted string: ${str}`);
|
|
875
|
+
}
|
|
876
|
+
let hour = m[4];
|
|
877
|
+
if (hour === '24') {
|
|
878
|
+
hour = '00';
|
|
879
|
+
}
|
|
880
|
+
m[3] = pad4(parseInt(m[3], 10));
|
|
881
|
+
return `${m[3]}-${m[1]}-${m[2]}T${hour}:${m[5]}:${m[6]}Z`;
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Returns number of minutes `tzid` is offset from UTC on date `date`.
|
|
885
|
+
*/
|
|
886
|
+
function getTimezoneOffset(tzid, date) {
|
|
887
|
+
const utcStr = getPseudoISO('UTC', date);
|
|
888
|
+
const localStr = getPseudoISO(tzid, date);
|
|
889
|
+
const diffMs = new Date(utcStr).getTime() - new Date(localStr).getTime();
|
|
890
|
+
return Math.ceil(diffMs / 1000 / 60);
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Returns YYYY-MM-DD in the local timezone
|
|
894
|
+
*/
|
|
895
|
+
function isoDateString(dt) {
|
|
896
|
+
return (pad4(dt.getFullYear()) +
|
|
897
|
+
'-' +
|
|
898
|
+
pad2(dt.getMonth() + 1) +
|
|
899
|
+
'-' +
|
|
900
|
+
pad2(dt.getDate()));
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
904
|
+
var poAshkenazi$1 = { "headers": { "plural-forms": "nplurals=2; plural=(n > 1);", "language": "en_CA@ashkenazi" }, "contexts": { "": { "Tevet": ["Teves"] } } };
|
|
905
|
+
|
|
906
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
907
|
+
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": ["תִּשְׁרֵי"] } } };
|
|
908
|
+
|
|
909
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
910
|
+
|
|
911
|
+
const noopLocale = {
|
|
912
|
+
headers: { 'plural-forms': 'nplurals=2; plural=(n!=1);' },
|
|
913
|
+
contexts: { '': {} },
|
|
914
|
+
};
|
|
915
|
+
const alias = {
|
|
916
|
+
h: 'he',
|
|
917
|
+
a: 'ashkenazi',
|
|
918
|
+
s: 'en',
|
|
919
|
+
'': 'en',
|
|
920
|
+
};
|
|
921
|
+
/** @private */
|
|
922
|
+
const locales = new Map();
|
|
923
|
+
/** @private */
|
|
924
|
+
let activeLocale;
|
|
925
|
+
/** @private */
|
|
926
|
+
let activeName;
|
|
927
|
+
/** @private */
|
|
928
|
+
function getEnOrdinal(n) {
|
|
929
|
+
const s = ['th', 'st', 'nd', 'rd'];
|
|
930
|
+
const v = n % 100;
|
|
931
|
+
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
932
|
+
}
|
|
933
|
+
/** @private */
|
|
934
|
+
function checkLocale(locale) {
|
|
935
|
+
if (typeof locale !== 'string') {
|
|
936
|
+
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
937
|
+
}
|
|
938
|
+
return locale.toLowerCase();
|
|
939
|
+
}
|
|
940
|
+
/** @private */
|
|
941
|
+
function getExistingLocale(locale) {
|
|
942
|
+
const locale1 = checkLocale(locale);
|
|
943
|
+
const loc = locales.get(locale1);
|
|
944
|
+
if (!loc) {
|
|
945
|
+
throw new RangeError(`Locale '${locale}' not found`);
|
|
946
|
+
}
|
|
947
|
+
return loc;
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* A locale in Hebcal is used for translations/transliterations of
|
|
951
|
+
* holidays. `@hebcal/hdate` supports four locales by default
|
|
952
|
+
* * `en` - default, Sephardic transliterations (e.g. "Shabbat")
|
|
953
|
+
* * `ashkenazi` - Ashkenazi transliterations (e.g. "Shabbos")
|
|
954
|
+
* * `he` - Hebrew (e.g. "שַׁבָּת")
|
|
955
|
+
* * `he-x-NoNikud` - Hebrew without nikud (e.g. "שבת")
|
|
956
|
+
*/
|
|
957
|
+
class Locale {
|
|
958
|
+
/**
|
|
959
|
+
* Returns translation only if `locale` offers a non-empty translation for `id`.
|
|
960
|
+
* Otherwise, returns `undefined`.
|
|
961
|
+
* @param id Message ID to translate
|
|
962
|
+
* @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
963
|
+
*/
|
|
964
|
+
static lookupTranslation(id, locale) {
|
|
965
|
+
const loc = (typeof locale === 'string' && locales.get(locale.toLowerCase())) ||
|
|
966
|
+
activeLocale;
|
|
967
|
+
const array = loc[id];
|
|
968
|
+
if ((array === null || array === void 0 ? void 0 : array.length) && array[0].length) {
|
|
969
|
+
return array[0];
|
|
970
|
+
}
|
|
971
|
+
return undefined;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* By default, if no translation was found, returns `id`.
|
|
975
|
+
* @param id Message ID to translate
|
|
976
|
+
* @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
977
|
+
*/
|
|
978
|
+
static gettext(id, locale) {
|
|
979
|
+
const text = this.lookupTranslation(id, locale);
|
|
980
|
+
if (typeof text === 'undefined') {
|
|
981
|
+
return id;
|
|
982
|
+
}
|
|
983
|
+
return text;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Register locale translations.
|
|
987
|
+
* @param locale Locale name (i.e.: `'he'`, `'fr'`)
|
|
988
|
+
* @param data parsed data from a `.po` file.
|
|
989
|
+
*/
|
|
990
|
+
static addLocale(locale, data) {
|
|
991
|
+
locale = checkLocale(locale);
|
|
992
|
+
if (typeof data.contexts !== 'object' ||
|
|
993
|
+
typeof data.contexts[''] !== 'object') {
|
|
994
|
+
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
995
|
+
}
|
|
996
|
+
locales.set(locale, data.contexts['']);
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Adds a translation to `locale`, replacing any previous translation.
|
|
1000
|
+
* @param locale Locale name (i.e: `'he'`, `'fr'`).
|
|
1001
|
+
* @param id Message ID to translate
|
|
1002
|
+
* @param translation Translation text
|
|
1003
|
+
*/
|
|
1004
|
+
static addTranslation(locale, id, translation) {
|
|
1005
|
+
const loc = getExistingLocale(locale);
|
|
1006
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
1007
|
+
throw new TypeError(`Invalid id string: ${id}`);
|
|
1008
|
+
}
|
|
1009
|
+
const isArray = Array.isArray(translation);
|
|
1010
|
+
if (isArray) {
|
|
1011
|
+
const t0 = translation[0];
|
|
1012
|
+
if (typeof t0 !== 'string' || t0.length === 0) {
|
|
1013
|
+
throw new TypeError(`Invalid translation array: ${translation}`);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
else if (typeof translation !== 'string') {
|
|
1017
|
+
throw new TypeError(`Invalid translation string: ${translation}`);
|
|
1018
|
+
}
|
|
1019
|
+
loc[id] = isArray ? translation : [translation];
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Adds multiple translations to `locale`, replacing any previous translations.
|
|
1023
|
+
* @param locale Locale name (i.e: `'he'`, `'fr'`).
|
|
1024
|
+
* @param data parsed data from a `.po` file.
|
|
1025
|
+
*/
|
|
1026
|
+
static addTranslations(locale, data) {
|
|
1027
|
+
const loc = getExistingLocale(locale);
|
|
1028
|
+
if (typeof data.contexts !== 'object' ||
|
|
1029
|
+
typeof data.contexts[''] !== 'object') {
|
|
1030
|
+
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
1031
|
+
}
|
|
1032
|
+
const ctx = data.contexts[''];
|
|
1033
|
+
Object.assign(loc, ctx);
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Activates a locale. Throws an error if the locale has not been previously added.
|
|
1037
|
+
* After setting the locale to be used, all strings marked for translations
|
|
1038
|
+
* will be represented by the corresponding translation in the specified locale.
|
|
1039
|
+
* @param locale Locale name (i.e: `'he'`, `'fr'`)
|
|
1040
|
+
* @deprecated
|
|
1041
|
+
*/
|
|
1042
|
+
static useLocale(locale) {
|
|
1043
|
+
const locale0 = checkLocale(locale);
|
|
1044
|
+
const obj = getExistingLocale(locale0);
|
|
1045
|
+
activeName = alias[locale0] || locale0;
|
|
1046
|
+
activeLocale = obj;
|
|
1047
|
+
return activeLocale;
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Returns the name of the active locale (i.e. 'he', 'ashkenazi', 'fr')
|
|
1051
|
+
* @deprecated
|
|
1052
|
+
*/
|
|
1053
|
+
static getLocaleName() {
|
|
1054
|
+
return activeName;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Returns the names of registered locales
|
|
1058
|
+
*/
|
|
1059
|
+
static getLocaleNames() {
|
|
1060
|
+
const keys = Array.from(locales.keys());
|
|
1061
|
+
return keys.sort((a, b) => a.localeCompare(b));
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Renders a number in ordinal, such as 1st, 2nd or 3rd
|
|
1065
|
+
* @param [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
1066
|
+
*/
|
|
1067
|
+
static ordinal(n, locale) {
|
|
1068
|
+
const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
1069
|
+
const locale0 = locale1 || activeName;
|
|
1070
|
+
if (!locale0) {
|
|
1071
|
+
return getEnOrdinal(n);
|
|
1072
|
+
}
|
|
1073
|
+
switch (locale0) {
|
|
1074
|
+
case 'en':
|
|
1075
|
+
case 's':
|
|
1076
|
+
case 'a':
|
|
1077
|
+
return getEnOrdinal(n);
|
|
1078
|
+
case 'es':
|
|
1079
|
+
return n + 'º';
|
|
1080
|
+
case 'h':
|
|
1081
|
+
case 'he':
|
|
1082
|
+
case 'he-x-nonikud':
|
|
1083
|
+
return String(n);
|
|
1084
|
+
}
|
|
1085
|
+
if (locale0.startsWith('ashkenazi')) {
|
|
1086
|
+
return getEnOrdinal(n);
|
|
1087
|
+
}
|
|
1088
|
+
return n + '.';
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Removes nekudot from Hebrew string
|
|
1092
|
+
*/
|
|
1093
|
+
static hebrewStripNikkud(str) {
|
|
1094
|
+
return str.replace(/[\u0590-\u05bd]/g, '').replace(/[\u05bf-\u05c7]/g, '');
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
Locale.addLocale('en', noopLocale);
|
|
1098
|
+
Locale.addLocale('s', noopLocale);
|
|
1099
|
+
Locale.addLocale('', noopLocale);
|
|
1100
|
+
Locale.useLocale('en');
|
|
1101
|
+
/* Ashkenazic transliterations */
|
|
1102
|
+
Locale.addLocale('ashkenazi', poAshkenazi$1);
|
|
1103
|
+
Locale.addLocale('a', poAshkenazi$1);
|
|
1104
|
+
/* Hebrew with nikkud */
|
|
1105
|
+
Locale.addLocale('he', poHe$1);
|
|
1106
|
+
Locale.addLocale('h', poHe$1);
|
|
1107
|
+
/* Hebrew without nikkud */
|
|
1108
|
+
const heStrs$1 = poHe$1.contexts[''];
|
|
1109
|
+
const heNoNikud$1 = {};
|
|
1110
|
+
for (const [key, val] of Object.entries(heStrs$1)) {
|
|
1111
|
+
heNoNikud$1[key] = [Locale.hebrewStripNikkud(val[0])];
|
|
1112
|
+
}
|
|
1113
|
+
const poHeNoNikud$1 = {
|
|
1114
|
+
headers: poHe$1.headers,
|
|
1115
|
+
contexts: { '': heNoNikud$1 },
|
|
1116
|
+
};
|
|
1117
|
+
Locale.addLocale('he-x-NoNikud', poHeNoNikud$1);
|
|
1118
|
+
|
|
1119
|
+
/*! @hebcal/hdate v0.14.0, distributed under GPLv2 https://www.gnu.org/licenses/gpl-2.0.txt */
|
|
1120
|
+
|
|
1121
|
+
/*
|
|
1122
|
+
Hebcal - A Jewish Calendar Generator
|
|
1123
|
+
Copyright (c) 1994-2020 Danny Sadinoff
|
|
1124
|
+
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
1125
|
+
|
|
1126
|
+
https://github.com/hebcal/hebcal-es6
|
|
1127
|
+
|
|
1128
|
+
This program is free software; you can redistribute it and/or
|
|
1129
|
+
modify it under the terms of the GNU General Public License
|
|
1130
|
+
as published by the Free Software Foundation; either version 2
|
|
1131
|
+
of the License, or (at your option) any later version.
|
|
1132
|
+
|
|
1133
|
+
This program is distributed in the hope that it will be useful,
|
|
1134
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
1135
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
1136
|
+
GNU General Public License for more details.
|
|
1137
|
+
|
|
1138
|
+
You should have received a copy of the GNU General Public License
|
|
1139
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
1140
|
+
*/
|
|
1141
|
+
function mod(x, y) {
|
|
1142
|
+
return x - y * Math.floor(x / y);
|
|
1143
|
+
}
|
|
1144
|
+
function isSimpleHebrewDate(obj) {
|
|
1145
|
+
return obj.yy !== undefined;
|
|
1146
|
+
}
|
|
1147
|
+
const UNITS_DAY = 'day';
|
|
1148
|
+
const UNITS_WEEK = 'week';
|
|
1149
|
+
const UNITS_MONTH = 'month';
|
|
1150
|
+
const UNITS_YEAR = 'year';
|
|
1151
|
+
/**
|
|
1152
|
+
* A `HDate` represents a Hebrew calendar date.
|
|
1153
|
+
*
|
|
1154
|
+
* An instance of this class encapsulates a date in the Hebrew calendar system.
|
|
1155
|
+
* It consists of a year, month, and day, without any associated time or location data.
|
|
1156
|
+
* The Hebrew calendar is a lunisolar calendar, meaning it is based on both lunar and solar cycles.
|
|
1157
|
+
*
|
|
1158
|
+
* A Hebrew date internally stores three numbers:
|
|
1159
|
+
* - year: The Hebrew year (1-9999). Counted from the traditional Hebrew date of creation (3761 BCE in the Gregorian calendar)
|
|
1160
|
+
* - 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.
|
|
1161
|
+
* - day: The day of the month (1-30)
|
|
1162
|
+
*
|
|
1163
|
+
* This class uses Rata Die to convert between the Hebrew and Gregorian calendars.
|
|
1164
|
+
*
|
|
1165
|
+
* To calculate times of day, use `Zmanim` class from `@hebcal/core`
|
|
1166
|
+
* @see {@link https://en.wikipedia.org/wiki/Rata_Die | Rata Die}
|
|
1167
|
+
* @see {@link https://hebcal.github.io/api/core/classes/Zmanim.html | Zmanim}
|
|
1168
|
+
*/
|
|
1169
|
+
class HDate {
|
|
1170
|
+
/**
|
|
1171
|
+
* Create a Hebrew date. There are 3 basic forms for the `HDate()` constructor.
|
|
1172
|
+
*
|
|
1173
|
+
* 1. No parameters - represents the current Hebrew date at time of instantiation
|
|
1174
|
+
* 2. One parameter
|
|
1175
|
+
* * `Date` - represents the Hebrew date corresponding to the Gregorian date using
|
|
1176
|
+
* local time. Hours, minutes, seconds and milliseconds are ignored.
|
|
1177
|
+
* * `HDate` - clones a copy of the given Hebrew date
|
|
1178
|
+
* * `number` - Converts absolute R.D. days to Hebrew date.
|
|
1179
|
+
* R.D. 1 == the imaginary date January 1, 1 (Gregorian)
|
|
1180
|
+
* 3. Three parameters: Hebrew day, Hebrew month, Hebrew year. Hebrew day should
|
|
1181
|
+
* be a number between 1-30, Hebrew month can be a number or string, and
|
|
1182
|
+
* Hebrew year is always a number.
|
|
1183
|
+
* @example
|
|
1184
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1185
|
+
*
|
|
1186
|
+
* const hd1 = new HDate();
|
|
1187
|
+
* const hd2 = new HDate(new Date(2008, 10, 13));
|
|
1188
|
+
* const hd3 = new HDate(15, 'Cheshvan', 5769);
|
|
1189
|
+
* const hd4 = new HDate(15, months.CHESHVAN, 5769);
|
|
1190
|
+
* const hd5 = new HDate(733359); // ==> 15 Cheshvan 5769
|
|
1191
|
+
* const monthName = 'אייר';
|
|
1192
|
+
* const hd6 = new HDate(5, monthName, 5773);
|
|
1193
|
+
* @param [day] - Day of month (1-30) if a `number`.
|
|
1194
|
+
* If a `Date` is specified, represents the Hebrew date corresponding to the
|
|
1195
|
+
* Gregorian date using local time.
|
|
1196
|
+
* If an `HDate` is specified, clones a copy of the given Hebrew date.
|
|
1197
|
+
* @param [month] - Hebrew month of year (1=NISAN, 7=TISHREI)
|
|
1198
|
+
* @param [year] - Hebrew year
|
|
1199
|
+
*/
|
|
1200
|
+
constructor(day, month, year) {
|
|
1201
|
+
if (arguments.length === 2 || arguments.length > 3) {
|
|
1202
|
+
throw new TypeError('HDate constructor requires 0, 1 or 3 arguments');
|
|
1203
|
+
}
|
|
1204
|
+
if (arguments.length === 3) {
|
|
1205
|
+
// Hebrew day, Hebrew month, Hebrew year
|
|
1206
|
+
this.dd = this.mm = 1;
|
|
1207
|
+
const yy = typeof year === 'string' ? parseInt(year, 10) : year;
|
|
1208
|
+
if (isNaN(yy)) {
|
|
1209
|
+
throw new TypeError(`HDate called with bad year: ${year}`);
|
|
1210
|
+
}
|
|
1211
|
+
this.yy = yy;
|
|
1212
|
+
setMonth(this, month); // will throw if we can't parse
|
|
1213
|
+
const dd = typeof day === 'string' ? parseInt(day, 10) : day;
|
|
1214
|
+
if (isNaN(dd)) {
|
|
1215
|
+
throw new TypeError(`HDate called with bad day: ${day}`);
|
|
1216
|
+
}
|
|
1217
|
+
setDate(this, dd);
|
|
1218
|
+
}
|
|
1219
|
+
else {
|
|
1220
|
+
// 0 arguments
|
|
1221
|
+
if (typeof day === 'undefined' || day === null) {
|
|
1222
|
+
day = new Date();
|
|
1223
|
+
}
|
|
1224
|
+
// 1 argument
|
|
1225
|
+
const abs0 = typeof day === 'number' && !isNaN(day)
|
|
1226
|
+
? day
|
|
1227
|
+
: isDate(day)
|
|
1228
|
+
? greg2abs(day)
|
|
1229
|
+
: isSimpleHebrewDate(day)
|
|
1230
|
+
? day
|
|
1231
|
+
: null;
|
|
1232
|
+
if (abs0 === null) {
|
|
1233
|
+
throw new TypeError(`HDate called with bad arg: ${day}`);
|
|
1234
|
+
}
|
|
1235
|
+
const isNumber = typeof abs0 === 'number';
|
|
1236
|
+
const d = isNumber ? abs2hebrew(abs0) : abs0;
|
|
1237
|
+
this.yy = d.yy;
|
|
1238
|
+
this.mm = d.mm;
|
|
1239
|
+
this.dd = d.dd;
|
|
1240
|
+
if (isNumber) {
|
|
1241
|
+
this.rd = abs0;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Returns the Hebrew year of this Hebrew date
|
|
1247
|
+
* @returns an integer >= 1
|
|
1248
|
+
* @example
|
|
1249
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1250
|
+
* hd.getFullYear(); // 5769
|
|
1251
|
+
*/
|
|
1252
|
+
getFullYear() {
|
|
1253
|
+
return this.yy;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Returns `true` if this Hebrew date occurs during a Hebrew leap year
|
|
1257
|
+
* @example
|
|
1258
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1259
|
+
* hd.isLeapYear(); // false
|
|
1260
|
+
*/
|
|
1261
|
+
isLeapYear() {
|
|
1262
|
+
return isLeapYear(this.yy);
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Returns the Hebrew month (1=NISAN, 7=TISHREI) of this Hebrew date
|
|
1266
|
+
* @returns an integer 1-13
|
|
1267
|
+
* @example
|
|
1268
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1269
|
+
* hd.getMonth(); // 8
|
|
1270
|
+
*/
|
|
1271
|
+
getMonth() {
|
|
1272
|
+
return this.mm;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* The Tishrei-based month of this Hebrew date. 1 is Tishrei, 7 is Nisan, 13 is Elul in a leap year
|
|
1276
|
+
* @returns an integer 1-13
|
|
1277
|
+
* @example
|
|
1278
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1279
|
+
* hd.getTishreiMonth(); // 2
|
|
1280
|
+
*/
|
|
1281
|
+
getTishreiMonth() {
|
|
1282
|
+
const nummonths = monthsInYear(this.getFullYear());
|
|
1283
|
+
return (this.getMonth() + nummonths - 6) % nummonths || nummonths;
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Number of days in the month of this Hebrew date (29 or 30)
|
|
1287
|
+
* @returns an integer 29-30
|
|
1288
|
+
* @example
|
|
1289
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1290
|
+
* hd.daysInMonth(); // 29
|
|
1291
|
+
*/
|
|
1292
|
+
daysInMonth() {
|
|
1293
|
+
return daysInMonth(this.getMonth(), this.getFullYear());
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Gets the day within the month (1-30)
|
|
1297
|
+
* @returns an integer 1-30
|
|
1298
|
+
* @example
|
|
1299
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1300
|
+
* hd.getDate(); // 15
|
|
1301
|
+
*/
|
|
1302
|
+
getDate() {
|
|
1303
|
+
return this.dd;
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Returns the day of the week for this Hebrew date,
|
|
1307
|
+
* where 0 represents Sunday, 1 represents Monday, 6 represents Saturday.
|
|
1308
|
+
*
|
|
1309
|
+
* For the day of the month, see `getDate()`
|
|
1310
|
+
* @returns an integer 0-6
|
|
1311
|
+
* @example
|
|
1312
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1313
|
+
* hd.getDate(); // 4
|
|
1314
|
+
*/
|
|
1315
|
+
getDay() {
|
|
1316
|
+
return mod(this.abs(), 7);
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Converts this Hebrew date to the corresponding Gregorian date.
|
|
1320
|
+
*
|
|
1321
|
+
* The returned `Date` object will be in the local (i.e. host system) time zone.
|
|
1322
|
+
* Hours, minutes, seconds and milliseconds will all be zero.
|
|
1323
|
+
*
|
|
1324
|
+
* Note that this function returns the daytime portion of the date.
|
|
1325
|
+
* For example, the 15th of Cheshvan 5769 began at sundown on
|
|
1326
|
+
* 12 November 2008 and continues through 13 November 2008. This
|
|
1327
|
+
* function would return only the date 13 November 2008.
|
|
1328
|
+
* @example
|
|
1329
|
+
* const hd = new HDate(15, 'Cheshvan', 5769);
|
|
1330
|
+
* const date = hd.greg(); // 13 November 2008
|
|
1331
|
+
* const year = date.getFullYear(); // 2008
|
|
1332
|
+
* const monthNum = date.getMonth() + 1; // 11
|
|
1333
|
+
* const day = date.getDate(); // 13
|
|
1334
|
+
*/
|
|
1335
|
+
greg() {
|
|
1336
|
+
return abs2greg(this.abs());
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Converts from Hebrew date representation to R.D. (Rata Die) fixed days.
|
|
1340
|
+
* R.D. 1 is the imaginary date Monday, January 1, 1 (Gregorian).
|
|
1341
|
+
* Note also that R.D. = Julian Date − 1,721,424.5
|
|
1342
|
+
* @see {@link https://en.wikipedia.org/wiki/Rata_Die | Rata Die}
|
|
1343
|
+
* @example
|
|
1344
|
+
* const hd = new HDate(15, 'Cheshvan', 5769);
|
|
1345
|
+
* hd.abs(); // 733359
|
|
1346
|
+
*/
|
|
1347
|
+
abs() {
|
|
1348
|
+
if (typeof this.rd !== 'number') {
|
|
1349
|
+
this.rd = hebrew2abs(this.yy, this.mm, this.dd);
|
|
1350
|
+
}
|
|
1351
|
+
return this.rd;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Converts Hebrew date to R.D. (Rata Die) fixed days.
|
|
1355
|
+
* R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian
|
|
1356
|
+
* Calendar.
|
|
1357
|
+
* @param year Hebrew year
|
|
1358
|
+
* @param month Hebrew month (1=NISAN, 7=TISHREI)
|
|
1359
|
+
* @param day Hebrew date (1-30)
|
|
1360
|
+
* @example
|
|
1361
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1362
|
+
* HDate.hebrew2abs(5769, months.CHESHVAN, 15); // 733359
|
|
1363
|
+
*/
|
|
1364
|
+
static hebrew2abs(year, month, day) {
|
|
1365
|
+
return hebrew2abs(year, month, day);
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns a transliterated Hebrew month name, e.g. `'Elul'` or `'Cheshvan'`.
|
|
1369
|
+
* @example
|
|
1370
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1371
|
+
* hd.getMonthName(); // 'Cheshvan'
|
|
1372
|
+
*/
|
|
1373
|
+
getMonthName() {
|
|
1374
|
+
return getMonthName(this.getMonth(), this.getFullYear());
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Renders this Hebrew date as a translated or transliterated string,
|
|
1378
|
+
* including ordinal e.g. `'15th of Cheshvan, 5769'`.
|
|
1379
|
+
* @example
|
|
1380
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1381
|
+
*
|
|
1382
|
+
* const hd = new HDate(15, months.CHESHVAN, 5769);
|
|
1383
|
+
* console.log(hd.render('en')); // '15th of Cheshvan, 5769'
|
|
1384
|
+
* console.log(hd.render('he')); // '15 חֶשְׁוָן, 5769'
|
|
1385
|
+
* console.log(hd.render('en', false)); // '15th of Cheshvan'
|
|
1386
|
+
* console.log(hd.render('he', false)); // '15 חֶשְׁוָן'
|
|
1387
|
+
* @param [locale] Optional locale name (defaults to active locale).
|
|
1388
|
+
* @param [showYear=true] Display year (defaults to true).
|
|
1389
|
+
* @see {@link Locale}
|
|
1390
|
+
*/
|
|
1391
|
+
render(locale, showYear = true) {
|
|
1392
|
+
const locale0 = locale || Locale.getLocaleName();
|
|
1393
|
+
const day = this.getDate();
|
|
1394
|
+
const monthName0 = Locale.gettext(this.getMonthName(), locale0);
|
|
1395
|
+
const monthName = monthName0.replace(/'/g, '’');
|
|
1396
|
+
const nth = Locale.ordinal(day, locale0);
|
|
1397
|
+
const dayOf = getDayOfTranslation(locale0);
|
|
1398
|
+
const dateStr = `${nth}${dayOf} ${monthName}`;
|
|
1399
|
+
if (showYear) {
|
|
1400
|
+
const fullYear = this.getFullYear();
|
|
1401
|
+
return `${dateStr}, ${fullYear}`;
|
|
1402
|
+
}
|
|
1403
|
+
else {
|
|
1404
|
+
return dateStr;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Renders this Hebrew date in Hebrew gematriya, regardless of locale.
|
|
1409
|
+
* @example
|
|
1410
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1411
|
+
* const hd = new HDate(15, months.CHESHVAN, 5769);
|
|
1412
|
+
* hd.renderGematriya(); // 'ט״ו חֶשְׁוָן תשס״ט'
|
|
1413
|
+
* hd.renderGematriya(true); // 'ט״ו חשון תשס״ט'
|
|
1414
|
+
*/
|
|
1415
|
+
renderGematriya(suppressNikud = false) {
|
|
1416
|
+
const d = this.getDate();
|
|
1417
|
+
const locale = suppressNikud ? 'he-x-NoNikud' : 'he';
|
|
1418
|
+
const m = Locale.gettext(this.getMonthName(), locale);
|
|
1419
|
+
const y = this.getFullYear();
|
|
1420
|
+
return gematriya(d) + ' ' + m + ' ' + gematriya(y);
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Returns an `HDate` corresponding to the specified day of week
|
|
1424
|
+
* **before** this Hebrew date
|
|
1425
|
+
* @example
|
|
1426
|
+
* new HDate(new Date('Wednesday February 19, 2014')).before(6).greg() // Sat Feb 15 2014
|
|
1427
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1428
|
+
*/
|
|
1429
|
+
before(dayOfWeek) {
|
|
1430
|
+
return onOrBefore(dayOfWeek, this, -1);
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Returns an `HDate` corresponding to the specified day of week
|
|
1434
|
+
* **on or before** this Hebrew date
|
|
1435
|
+
* @example
|
|
1436
|
+
* new HDate(new Date('Wednesday February 19, 2014')).onOrBefore(6).greg() // Sat Feb 15 2014
|
|
1437
|
+
* new HDate(new Date('Saturday February 22, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014
|
|
1438
|
+
* new HDate(new Date('Sunday February 23, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014
|
|
1439
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1440
|
+
*/
|
|
1441
|
+
onOrBefore(dayOfWeek) {
|
|
1442
|
+
return onOrBefore(dayOfWeek, this, 0);
|
|
1443
|
+
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Returns an `HDate` corresponding to the specified day of week
|
|
1446
|
+
* **nearest** to this Hebrew date
|
|
1447
|
+
* @example
|
|
1448
|
+
* new HDate(new Date('Wednesday February 19, 2014')).nearest(6).greg() // Sat Feb 22 2014
|
|
1449
|
+
* new HDate(new Date('Tuesday February 18, 2014')).nearest(6).greg() // Sat Feb 15 2014
|
|
1450
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1451
|
+
*/
|
|
1452
|
+
nearest(dayOfWeek) {
|
|
1453
|
+
return onOrBefore(dayOfWeek, this, 3);
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Returns an `HDate` corresponding to the specified day of week
|
|
1457
|
+
* **on or after** this Hebrew date
|
|
1458
|
+
* @example
|
|
1459
|
+
* new HDate(new Date('Wednesday February 19, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014
|
|
1460
|
+
* new HDate(new Date('Saturday February 22, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014
|
|
1461
|
+
* new HDate(new Date('Sunday February 23, 2014')).onOrAfter(6).greg() // Sat Mar 01 2014
|
|
1462
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1463
|
+
*/
|
|
1464
|
+
onOrAfter(dayOfWeek) {
|
|
1465
|
+
return onOrBefore(dayOfWeek, this, 6);
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Returns an `HDate` corresponding to the specified day of week
|
|
1469
|
+
* **after** this Hebrew date
|
|
1470
|
+
* @example
|
|
1471
|
+
* new HDate(new Date('Wednesday February 19, 2014')).after(6).greg() // Sat Feb 22 2014
|
|
1472
|
+
* new HDate(new Date('Saturday February 22, 2014')).after(6).greg() // Sat Mar 01 2014
|
|
1473
|
+
* new HDate(new Date('Sunday February 23, 2014')).after(6).greg() // Sat Mar 01 2014
|
|
1474
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1475
|
+
*/
|
|
1476
|
+
after(dayOfWeek) {
|
|
1477
|
+
return onOrBefore(dayOfWeek, this, 7);
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Returns the next Hebrew date
|
|
1481
|
+
* @example
|
|
1482
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1483
|
+
* hd.next(); // '16 Cheshvan 5769'
|
|
1484
|
+
*/
|
|
1485
|
+
next() {
|
|
1486
|
+
return new HDate(this.abs() + 1);
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Returns the previous Hebrew date
|
|
1490
|
+
* @example
|
|
1491
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1492
|
+
* hd.prev(); // '14 Cheshvan 5769'
|
|
1493
|
+
*/
|
|
1494
|
+
prev() {
|
|
1495
|
+
return new HDate(this.abs() - 1);
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Returns a cloned `HDate` object with a specified amount of time added
|
|
1499
|
+
*
|
|
1500
|
+
* Units are case insensitive, and support plural and short forms.
|
|
1501
|
+
* Note, short forms are case sensitive.
|
|
1502
|
+
*
|
|
1503
|
+
* | Unit | Shorthand | Description
|
|
1504
|
+
* | --- | --- | --- |
|
|
1505
|
+
* | `day` | `d` | days |
|
|
1506
|
+
* | `week` | `w` | weeks |
|
|
1507
|
+
* | `month` | `M` | months |
|
|
1508
|
+
* | `year` | `y` | years |
|
|
1509
|
+
*/
|
|
1510
|
+
add(amount, units = 'd') {
|
|
1511
|
+
amount =
|
|
1512
|
+
typeof amount === 'string' ? parseInt(amount, 10) : amount;
|
|
1513
|
+
if (!amount) {
|
|
1514
|
+
return new HDate(this);
|
|
1515
|
+
}
|
|
1516
|
+
units = standardizeUnits(units);
|
|
1517
|
+
if (units === UNITS_DAY) {
|
|
1518
|
+
return new HDate(this.abs() + amount);
|
|
1519
|
+
}
|
|
1520
|
+
else if (units === UNITS_WEEK) {
|
|
1521
|
+
return new HDate(this.abs() + 7 * amount);
|
|
1522
|
+
}
|
|
1523
|
+
else if (units === UNITS_YEAR) {
|
|
1524
|
+
return new HDate(this.getDate(), this.getMonth(), this.getFullYear() + amount);
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
// units === UNITS_MONTH
|
|
1528
|
+
let hd = new HDate(this);
|
|
1529
|
+
const sign = amount > 0 ? 1 : -1;
|
|
1530
|
+
amount = Math.abs(amount);
|
|
1531
|
+
for (let i = 0; i < amount; i++) {
|
|
1532
|
+
hd = new HDate(hd.abs() + sign * hd.daysInMonth());
|
|
1533
|
+
}
|
|
1534
|
+
return hd;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Returns a cloned `HDate` object with a specified amount of time subracted
|
|
1539
|
+
*
|
|
1540
|
+
* Units are case insensitive, and support plural and short forms.
|
|
1541
|
+
* Note, short forms are case sensitive.
|
|
1542
|
+
*
|
|
1543
|
+
* | Unit | Shorthand | Description
|
|
1544
|
+
* | --- | --- | --- |
|
|
1545
|
+
* | `day` | `d` | days |
|
|
1546
|
+
* | `week` | `w` | weeks |
|
|
1547
|
+
* | `month` | `M` | months |
|
|
1548
|
+
* | `year` | `y` | years |
|
|
1549
|
+
* @example
|
|
1550
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1551
|
+
*
|
|
1552
|
+
* const hd1 = new HDate(15, months.CHESHVAN, 5769);
|
|
1553
|
+
* const hd2 = hd1.add(1, 'weeks'); // 7 Kislev 5769
|
|
1554
|
+
* const hd3 = hd1.add(-3, 'M'); // 30 Av 5768
|
|
1555
|
+
*/
|
|
1556
|
+
subtract(amount, units = 'd') {
|
|
1557
|
+
return this.add(amount * -1, units);
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Returns the difference in days between the two given HDates.
|
|
1561
|
+
*
|
|
1562
|
+
* The result is positive if `this` date is comes chronologically
|
|
1563
|
+
* after the `other` date, and negative
|
|
1564
|
+
* if the order of the two dates is reversed.
|
|
1565
|
+
*
|
|
1566
|
+
* The result is zero if the two dates are identical.
|
|
1567
|
+
* @example
|
|
1568
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1569
|
+
*
|
|
1570
|
+
* const hd1 = new HDate(25, months.KISLEV, 5770);
|
|
1571
|
+
* const hd2 = new HDate(15, months.CHESHVAN, 5769);
|
|
1572
|
+
* const days = hd1.deltaDays(hd2); // 394
|
|
1573
|
+
* @param other Hebrew date to compare
|
|
1574
|
+
*/
|
|
1575
|
+
deltaDays(other) {
|
|
1576
|
+
return this.abs() - other.abs();
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Compares this Hebrew date to another date, returning `true` if the dates match.
|
|
1580
|
+
* @param other Hebrew date to compare
|
|
1581
|
+
* @example
|
|
1582
|
+
* const hd1 = new HDate(new Date(2008, 10, 13));
|
|
1583
|
+
* const hd2 = new HDate(15, 'Cheshvan', 5769);
|
|
1584
|
+
* hd1.isSameDate(hd2); // true
|
|
1585
|
+
*/
|
|
1586
|
+
isSameDate(other) {
|
|
1587
|
+
return this.yy === other.yy && this.mm === other.mm && this.dd === other.dd;
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1590
|
+
* Returns a string representation of this Hebrew date using English transliterations
|
|
1591
|
+
* @example
|
|
1592
|
+
* const hd = new HDate(new Date(2008, 10, 13)); // 15 Cheshvan 5769
|
|
1593
|
+
* hd.toString(); // '15 Cheshvan 5769'
|
|
1594
|
+
*/
|
|
1595
|
+
toString() {
|
|
1596
|
+
const day = this.getDate();
|
|
1597
|
+
const fullYear = this.getFullYear();
|
|
1598
|
+
const monthName = this.getMonthName();
|
|
1599
|
+
return `${day} ${monthName} ${fullYear}`;
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* Returns true if Hebrew year is a leap year
|
|
1603
|
+
* @param year Hebrew year
|
|
1604
|
+
* @example
|
|
1605
|
+
* HDate.isLeapYear(5783); // false
|
|
1606
|
+
* HDate.isLeapYear(5784); // true
|
|
1607
|
+
*/
|
|
1608
|
+
static isLeapYear(year) {
|
|
1609
|
+
return isLeapYear(year);
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Number of months in this Hebrew year (either 12 or 13 depending on leap year)
|
|
1613
|
+
* @param year Hebrew year
|
|
1614
|
+
* @example
|
|
1615
|
+
* HDate.monthsInYear(5783); // 12
|
|
1616
|
+
* HDate.monthsInYear(5784); // 13
|
|
1617
|
+
*/
|
|
1618
|
+
static monthsInYear(year) {
|
|
1619
|
+
return monthsInYear(year);
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Number of days in Hebrew month in a given year (29 or 30)
|
|
1623
|
+
* @param month Hebrew month (e.g. months.TISHREI)
|
|
1624
|
+
* @param year Hebrew year
|
|
1625
|
+
* @example
|
|
1626
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1627
|
+
* HDate.daysInMonth(months.CHESHVAN, 5769); // 29
|
|
1628
|
+
*/
|
|
1629
|
+
static daysInMonth(month, year) {
|
|
1630
|
+
return daysInMonth(month, year);
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Returns a transliterated string name of Hebrew month in year,
|
|
1634
|
+
* for example 'Elul' or 'Cheshvan'.
|
|
1635
|
+
* @param month Hebrew month (e.g. months.TISHREI)
|
|
1636
|
+
* @param year Hebrew year
|
|
1637
|
+
* @example
|
|
1638
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1639
|
+
* HDate.getMonthName(months.CHESHVAN, 5769); // 'Cheshvan'
|
|
1640
|
+
*/
|
|
1641
|
+
static getMonthName(month, year) {
|
|
1642
|
+
return getMonthName(month, year);
|
|
1643
|
+
}
|
|
1644
|
+
/**
|
|
1645
|
+
* Returns the Hebrew month number (NISAN=1, TISHREI=7)
|
|
1646
|
+
* @param month A number, or Hebrew month name string
|
|
1647
|
+
* @example
|
|
1648
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1649
|
+
* HDate.monthNum(months.CHESHVAN); // 8
|
|
1650
|
+
* HDate.monthNum('Cheshvan'); // 8
|
|
1651
|
+
* HDate.monthNum('חשון'); // 8
|
|
1652
|
+
*/
|
|
1653
|
+
static monthNum(month) {
|
|
1654
|
+
if (typeof month === 'number') {
|
|
1655
|
+
if (isNaN(month) || month > 14) {
|
|
1656
|
+
throw new RangeError(`bad monthNum: ${month}`);
|
|
1657
|
+
}
|
|
1658
|
+
return month;
|
|
1659
|
+
}
|
|
1660
|
+
return month.charCodeAt(0) >= 48 && month.charCodeAt(0) <= 57 /* number */
|
|
1661
|
+
? parseInt(month, 10)
|
|
1662
|
+
: HDate.monthFromName(month);
|
|
1663
|
+
}
|
|
1664
|
+
/**
|
|
1665
|
+
* Number of days in the Hebrew year.
|
|
1666
|
+
* Regular years can have 353, 354, or 355 days.
|
|
1667
|
+
* Leap years can have 383, 384, or 385 days.
|
|
1668
|
+
* @param year Hebrew year
|
|
1669
|
+
* @example
|
|
1670
|
+
* HDate.daysInYear(5783); // 355
|
|
1671
|
+
* HDate.daysInYear(5784); // 383
|
|
1672
|
+
*/
|
|
1673
|
+
static daysInYear(year) {
|
|
1674
|
+
return daysInYear(year);
|
|
1675
|
+
}
|
|
1676
|
+
/**
|
|
1677
|
+
* true if Cheshvan is long in Hebrew year
|
|
1678
|
+
* @param year Hebrew year
|
|
1679
|
+
* @example
|
|
1680
|
+
* HDate.longCheshvan(5783); // true
|
|
1681
|
+
* HDate.longCheshvan(5784); // false
|
|
1682
|
+
*/
|
|
1683
|
+
static longCheshvan(year) {
|
|
1684
|
+
return longCheshvan(year);
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* true if Kislev is short in Hebrew year
|
|
1688
|
+
* @param year Hebrew year
|
|
1689
|
+
* @example
|
|
1690
|
+
* HDate.shortKislev(5783); // false
|
|
1691
|
+
* HDate.shortKislev(5784); // true
|
|
1692
|
+
*/
|
|
1693
|
+
static shortKislev(year) {
|
|
1694
|
+
return shortKislev(year);
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Converts Hebrew month string name to numeric
|
|
1698
|
+
* @example
|
|
1699
|
+
* import {HDate, months} from '@hebcal/hdate';
|
|
1700
|
+
* HDate.monthFromName(months.CHESHVAN); // 8
|
|
1701
|
+
* HDate.monthFromName('Cheshvan'); // 8
|
|
1702
|
+
* HDate.monthFromName('חשון'); // 8
|
|
1703
|
+
*/
|
|
1704
|
+
static monthFromName(monthName) {
|
|
1705
|
+
if (typeof monthName === 'number') {
|
|
1706
|
+
if (isNaN(monthName) || monthName < 1 || monthName > 14) {
|
|
1707
|
+
throw new RangeError(`bad monthName: ${monthName}`);
|
|
1708
|
+
}
|
|
1709
|
+
return monthName;
|
|
1710
|
+
}
|
|
1711
|
+
const name = Locale.hebrewStripNikkud(monthName);
|
|
1712
|
+
return monthFromName(name);
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Convenience function for determining the R.D. date
|
|
1716
|
+
* near a specified R.D. date, corresponding to the specified day of week.
|
|
1717
|
+
*
|
|
1718
|
+
* Note: Applying this function to d+6 gives us the `dayOfWeek` on or after an
|
|
1719
|
+
* absolute day d. Similarly, applying it to d+3 gives the `dayOfWeek` nearest to
|
|
1720
|
+
* absolute date d, applying it to d-1 gives the `dayOfWeek` previous to absolute
|
|
1721
|
+
* date d, and applying it to d+7 gives the `dayOfWeek` following absolute date d.
|
|
1722
|
+
* @param dayOfWeek day of week: Sunday=0, Saturday=6
|
|
1723
|
+
*/
|
|
1724
|
+
static dayOnOrBefore(dayOfWeek, absdate) {
|
|
1725
|
+
return absdate - ((absdate - dayOfWeek) % 7);
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* Tests if the object is an instance of `HDate`
|
|
1729
|
+
* @example
|
|
1730
|
+
* HDate.isHDate(new HDate()); // true
|
|
1731
|
+
* HDate.isHDate(new Date()); // false
|
|
1732
|
+
* HDate.isHDate(null); // false
|
|
1733
|
+
* HDate.isHDate(12345); // false
|
|
1734
|
+
* HDate.isHDate('15 Cheshvan 5769'); // false
|
|
1735
|
+
*/
|
|
1736
|
+
static isHDate(obj) {
|
|
1737
|
+
return (obj !== null &&
|
|
1738
|
+
typeof obj === 'object' &&
|
|
1739
|
+
typeof obj.yy === 'number' &&
|
|
1740
|
+
typeof obj.mm === 'number' &&
|
|
1741
|
+
typeof obj.dd === 'number' &&
|
|
1742
|
+
typeof obj.greg === 'function' &&
|
|
1743
|
+
typeof obj.abs === 'function');
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Construct a new instance of `HDate` from a Gematriya-formatted string
|
|
1747
|
+
* @example
|
|
1748
|
+
* HDate.fromGematriyaString('כ״ז בְּתַמּוּז תשפ״ג') // 27 Tamuz 5783
|
|
1749
|
+
* HDate.fromGematriyaString('כ׳ סיון תש״ד') // 20 Sivan 5704
|
|
1750
|
+
* HDate.fromGematriyaString('ה׳ אִיָיר תש״ח') // 5 Iyyar 5708
|
|
1751
|
+
*/
|
|
1752
|
+
static fromGematriyaString(str, currentThousands = 5000) {
|
|
1753
|
+
const parts = str.split(' ').filter(x => x.length !== 0);
|
|
1754
|
+
const numParts = parts.length;
|
|
1755
|
+
if (numParts !== 3 && numParts !== 4) {
|
|
1756
|
+
throw new RangeError(`cannot parse gematriya str: "${str}"`);
|
|
1757
|
+
}
|
|
1758
|
+
const day = gematriyaStrToNum(parts[0]);
|
|
1759
|
+
const monthStr = numParts === 3 ? parts[1] : parts[1] + ' ' + parts[2];
|
|
1760
|
+
const month = HDate.monthFromName(monthStr);
|
|
1761
|
+
const yearStr = numParts === 3 ? parts[2] : parts[3];
|
|
1762
|
+
let year = gematriyaStrToNum(yearStr);
|
|
1763
|
+
if (year < 1000) {
|
|
1764
|
+
year += currentThousands;
|
|
1765
|
+
}
|
|
1766
|
+
return new HDate(day, month, year);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
function standardizeUnits(units) {
|
|
1770
|
+
switch (units) {
|
|
1771
|
+
case 'd':
|
|
1772
|
+
return UNITS_DAY;
|
|
1773
|
+
case 'w':
|
|
1774
|
+
return UNITS_WEEK;
|
|
1775
|
+
case 'M':
|
|
1776
|
+
return UNITS_MONTH;
|
|
1777
|
+
case 'y':
|
|
1778
|
+
return UNITS_YEAR;
|
|
1779
|
+
}
|
|
1780
|
+
const str = String(units || '')
|
|
1781
|
+
.toLowerCase()
|
|
1782
|
+
.replace(/s$/, '');
|
|
1783
|
+
switch (str) {
|
|
1784
|
+
case UNITS_DAY:
|
|
1785
|
+
case UNITS_WEEK:
|
|
1786
|
+
case UNITS_MONTH:
|
|
1787
|
+
case UNITS_YEAR:
|
|
1788
|
+
return str;
|
|
1789
|
+
}
|
|
1790
|
+
throw new TypeError(`Invalid units '${units}'`);
|
|
1791
|
+
}
|
|
1792
|
+
function getDayOfTranslation(locale) {
|
|
1793
|
+
switch (locale) {
|
|
1794
|
+
case 'en':
|
|
1795
|
+
case 's':
|
|
1796
|
+
case 'a':
|
|
1797
|
+
case 'ashkenazi':
|
|
1798
|
+
return ' of';
|
|
1799
|
+
}
|
|
1800
|
+
const ofStr = Locale.lookupTranslation('of', locale);
|
|
1801
|
+
if (ofStr) {
|
|
1802
|
+
return ' ' + ofStr;
|
|
1803
|
+
}
|
|
1804
|
+
if (locale.startsWith('ashkenazi')) {
|
|
1805
|
+
return ' of';
|
|
1806
|
+
}
|
|
1807
|
+
return '';
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Sets the day of the month of the date. Returns the object it was called upon
|
|
1811
|
+
* @private
|
|
1812
|
+
* @param month A number, or Hebrew month name string
|
|
1813
|
+
*/
|
|
1814
|
+
function setMonth(hd, month) {
|
|
1815
|
+
hd.mm = HDate.monthNum(month);
|
|
1816
|
+
fix(hd);
|
|
1817
|
+
return hd;
|
|
1818
|
+
}
|
|
1819
|
+
function setDate(hd, date) {
|
|
1820
|
+
hd.dd = date;
|
|
1821
|
+
fix(hd);
|
|
1822
|
+
return hd;
|
|
1823
|
+
}
|
|
1824
|
+
function fix(hd) {
|
|
1825
|
+
fixMonth(hd);
|
|
1826
|
+
fixDate(hd);
|
|
1827
|
+
}
|
|
1828
|
+
function fixDate(hd) {
|
|
1829
|
+
if (hd.dd < 1) {
|
|
1830
|
+
if (hd.mm === months.TISHREI) {
|
|
1831
|
+
hd.yy -= 1;
|
|
1832
|
+
}
|
|
1833
|
+
hd.dd += daysInMonth(hd.mm, hd.yy);
|
|
1834
|
+
hd.mm -= 1;
|
|
1835
|
+
fix(hd);
|
|
1836
|
+
}
|
|
1837
|
+
if (hd.dd > daysInMonth(hd.mm, hd.yy)) {
|
|
1838
|
+
if (hd.mm === months.ELUL) {
|
|
1839
|
+
hd.yy += 1;
|
|
1840
|
+
}
|
|
1841
|
+
hd.dd -= daysInMonth(hd.mm, hd.yy);
|
|
1842
|
+
if (hd.mm === monthsInYear(hd.yy)) {
|
|
1843
|
+
hd.mm = 1; // rollover to NISAN
|
|
1844
|
+
}
|
|
1845
|
+
else {
|
|
1846
|
+
hd.mm += 1;
|
|
1847
|
+
}
|
|
1848
|
+
fix(hd);
|
|
1849
|
+
}
|
|
1850
|
+
fixMonth(hd);
|
|
1851
|
+
}
|
|
1852
|
+
function fixMonth(hd) {
|
|
1853
|
+
if (hd.mm === months.ADAR_II && !hd.isLeapYear()) {
|
|
1854
|
+
hd.mm -= 1; // to Adar I
|
|
1855
|
+
fix(hd);
|
|
1856
|
+
}
|
|
1857
|
+
else if (hd.mm < 1) {
|
|
1858
|
+
hd.mm += monthsInYear(hd.yy);
|
|
1859
|
+
hd.yy -= 1;
|
|
1860
|
+
fix(hd);
|
|
1861
|
+
}
|
|
1862
|
+
else if (hd.mm > monthsInYear(hd.yy)) {
|
|
1863
|
+
hd.mm -= monthsInYear(hd.yy);
|
|
1864
|
+
hd.yy += 1;
|
|
1865
|
+
fix(hd);
|
|
1866
|
+
}
|
|
1867
|
+
delete hd.rd;
|
|
1868
|
+
}
|
|
1869
|
+
function onOrBefore(day, t, offset) {
|
|
1870
|
+
return new HDate(HDate.dayOnOrBefore(day, t.abs() + offset));
|
|
1871
|
+
}
|
|
10
1872
|
|
|
11
1873
|
var poAshkenazi = { "headers": { "plural-forms": "nplurals=2; plural=(n > 1);", "language": "en_CA@ashkenazi" }, "contexts": { "": { "Shabbat": ["Shabbos"], "Achrei Mot": ["Achrei Mos"], "Bechukotai": ["Bechukosai"], "Beha'alotcha": ["Beha’aloscha"], "Bereshit": ["Bereshis"], "Chukat": ["Chukas"], "Erev Shavuot": ["Erev Shavuos"], "Erev Sukkot": ["Erev Sukkos"], "Ki Tavo": ["Ki Savo"], "Ki Teitzei": ["Ki Seitzei"], "Ki Tisa": ["Ki Sisa"], "Matot": ["Matos"], "Purim Katan": ["Purim Koton"], "Shabbat Chazon": ["Shabbos Chazon"], "Shabbat HaChodesh": ["Shabbos HaChodesh"], "Shabbat HaGadol": ["Shabbos HaGadol"], "Shabbat Nachamu": ["Shabbos Nachamu"], "Shabbat Parah": ["Shabbos Parah"], "Shabbat Shekalim": ["Shabbos Shekalim"], "Shabbat Shuva": ["Shabbos Shuvah"], "Shabbat Zachor": ["Shabbos Zachor"], "Shavuot": ["Shavuos"], "Shavuot I": ["Shavuos I"], "Shavuot II": ["Shavuos II"], "Shemot": ["Shemos"], "Shmini Atzeret": ["Shmini Atzeres"], "Simchat Torah": ["Simchas Torah"], "Sukkot": ["Sukkos"], "Sukkot I": ["Sukkos I"], "Sukkot II": ["Sukkos II"], "Sukkot II (CH''M)": ["Sukkos II (CH’’M)"], "Sukkot III (CH''M)": ["Sukkos III (CH’’M)"], "Sukkot IV (CH''M)": ["Sukkos IV (CH’’M)"], "Sukkot V (CH''M)": ["Sukkos V (CH’’M)"], "Sukkot VI (CH''M)": ["Sukkos VI (CH’’M)"], "Sukkot VII (Hoshana Raba)": ["Sukkos VII (Hoshana Raba)"], "Ta'anit Bechorot": ["Ta’anis Bechoros"], "Ta'anit Esther": ["Ta’anis Esther"], "Toldot": ["Toldos"], "Vaetchanan": ["Vaeschanan"], "Yitro": ["Yisro"], "Vezot Haberakhah": ["Vezos Haberakhah"], "Parashat": ["Parshas"], "Leil Selichot": ["Leil Selichos"], "Shabbat Mevarchim Chodesh": ["Shabbos Mevorchim Chodesh"], "Shabbat Shirah": ["Shabbos Shirah"], "Asara B'Tevet": ["Asara B’Teves"], "Alot HaShachar": ["Alos HaShachar"], "Kriat Shema, sof zeman": ["Krias Shema, sof zman"], "Tefilah, sof zeman": ["Tefilah, sof zman"], "Kriat Shema, sof zeman (MGA)": ["Krias Shema, sof zman (MGA)"], "Tefilah, sof zeman (MGA)": ["Tefilah, sof zman (MGA)"], "Chatzot HaLailah": ["Chatzos HaLailah"], "Chatzot hayom": ["Chatzos"], "Tzeit HaKochavim": ["Tzeis HaKochavim"], "Birkat Hachamah": ["Birkas Hachamah"], "Shushan Purim Katan": ["Shushan Purim Koton"] } } };
|
|
12
1874
|
|
|
13
1875
|
var poHe = { "headers": { "plural-forms": "nplurals=2; plural=(n > 1);", "language": "he_IL" }, "contexts": { "": { "Shabbat": ["שַׁבָּת"], "Daf Yomi": ["דַף יוֹמִי"], "Parashat": ["פָּרָשַׁת"], "Achrei Mot": ["אַחֲרֵי מוֹת"], "Balak": ["בָּלָק"], "Bamidbar": ["בְּמִדְבַּר"], "Bechukotai": ["בְּחֻקֹּתַי"], "Beha'alotcha": ["בְּהַעֲלֹתְךָ"], "Behar": ["בְּהַר"], "Bereshit": ["בְּרֵאשִׁית"], "Beshalach": ["בְּשַׁלַּח"], "Bo": ["בֹּא"], "Chayei Sara": ["חַיֵּי שָֹרָה"], "Chukat": ["חֻקַּת"], "Devarim": ["דְּבָרִים"], "Eikev": ["עֵקֶב"], "Emor": ["אֱמוֹר"], "Ha'azinu": ["הַאֲזִינוּ"], "Kedoshim": ["קְדשִׁים"], "Ki Tavo": ["כִּי־תָבוֹא"], "Ki Teitzei": ["כִּי־תֵצֵא"], "Ki Tisa": ["כִּי תִשָּׂא"], "Korach": ["קוֹרַח"], "Lech-Lecha": ["לֶךְ־לְךָ"], "Masei": ["מַסְעֵי"], "Matot": ["מַּטּוֹת"], "Metzora": ["מְּצֹרָע"], "Miketz": ["מִקֵּץ"], "Mishpatim": ["מִּשְׁפָּטִים"], "Nasso": ["נָשׂא"], "Nitzavim": ["נִצָּבִים"], "Noach": ["נֹחַ"], "Pekudei": ["פְקוּדֵי"], "Pinchas": ["פִּינְחָס"], "Re'eh": ["רְאֵה"], "Sh'lach": ["שְׁלַח־לְךָ"], "Shemot": ["שְׁמוֹת"], "Shmini": ["שְּׁמִינִי"], "Shoftim": ["שׁוֹפְטִים"], "Tazria": ["תַזְרִיעַ"], "Terumah": ["תְּרוּמָה"], "Tetzaveh": ["תְּצַוֶּה"], "Toldot": ["תּוֹלְדוֹת"], "Tzav": ["צַו"], "Vaera": ["וָאֵרָא"], "Vaetchanan": ["וָאֶתְחַנַּן"], "Vayakhel": ["וַיַּקְהֵל"], "Vayechi": ["וַיְחִי"], "Vayeilech": ["וַיֵּלֶךְ"], "Vayera": ["וַיֵּרָא"], "Vayeshev": ["וַיֵּשֶׁב"], "Vayetzei": ["וַיֵּצֵא"], "Vayigash": ["וַיִּגַּשׁ"], "Vayikra": ["וַיִּקְרָא"], "Vayishlach": ["וַיִּשְׁלַח"], "Vezot Haberakhah": ["וְזֹאת הַבְּרָכָה"], "Yitro": ["יִתְרוֹ"], "Asara B'Tevet": ["עֲשָׂרָה בְּטֵבֵת"], "Candle lighting": ["הַדְלָקַת נֵרוֹת"], "Chanukah": ["חֲנוּכָּה"], "Chanukah: 1 Candle": ["חֲנוּכָּה: א׳ נֵר"], "Chanukah: 2 Candles": ["חֲנוּכָּה: ב׳ נֵרוֹת"], "Chanukah: 3 Candles": ["חֲנוּכָּה: ג׳ נֵרוֹת"], "Chanukah: 4 Candles": ["חֲנוּכָּה: ד׳ נֵרוֹת"], "Chanukah: 5 Candles": ["חֲנוּכָּה: ה׳ נֵרוֹת"], "Chanukah: 6 Candles": ["חֲנוּכָּה: ו׳ נֵרוֹת"], "Chanukah: 7 Candles": ["חֲנוּכָּה: ז׳ נֵרוֹת"], "Chanukah: 8 Candles": ["חֲנוּכָּה: ח׳ נֵרוֹת"], "Chanukah: 8th Day": ["חֲנוּכָּה: יוֹם ח׳"], "Days of the Omer": ["סְפִירַת הָעוֹמֶר"], "Omer": ["עוֹמֶר"], "day of the Omer": ["בָּעוֹמֶר"], "Erev Pesach": ["עֶרֶב פֶּסַח"], "Erev Purim": ["עֶרֶב פּוּרִים"], "Erev Rosh Hashana": ["עֶרֶב רֹאשׁ הַשָּׁנָה"], "Erev Shavuot": ["עֶרֶב שָׁבוּעוֹת"], "Erev Simchat Torah": ["עֶרֶב שִׂמְחַת תּוֹרָה"], "Erev Sukkot": ["עֶרֶב סוּכּוֹת"], "Erev Tish'a B'Av": ["עֶרֶב תִּשְׁעָה בְּאָב"], "Erev Yom Kippur": ["עֶרֶב יוֹם כִּפּוּר"], "Havdalah": ["הַבְדָּלָה"], "Lag BaOmer": ["ל״ג בָּעוֹמֶר"], "Leil Selichot": ["סליחות"], "Pesach": ["פֶּסַח"], "Pesach I": ["פֶּסַח א׳"], "Pesach II": ["פֶּסַח ב׳"], "Pesach II (CH''M)": ["פֶּסַח ב׳ (חוה״מ)"], "Pesach III (CH''M)": ["פֶּסַח ג׳ (חוה״מ)"], "Pesach IV (CH''M)": ["פֶּסַח ד׳ (חוה״מ)"], "Pesach Sheni": ["פֶּסַח שני"], "Pesach V (CH''M)": ["פֶּסַח ה׳ (חוה״מ)"], "Pesach VI (CH''M)": ["פֶּסַח ו׳ (חוה״מ)"], "Pesach VII": ["פֶּסַח ז׳"], "Pesach VIII": ["פֶּסַח ח׳"], "Purim": ["פּוּרִים"], "Purim Katan": ["פּוּרִים קָטָן"], "Rosh Chodesh %s": ["רֹאשׁ חוֹדֶשׁ %s"], "Rosh Chodesh": ["רֹאשׁ חוֹדֶשׁ"], "Rosh Hashana": ["רֹאשׁ הַשָּׁנָה"], "Rosh Hashana I": ["רֹאשׁ הַשָּׁנָה א׳"], "Rosh Hashana II": ["רֹאשׁ הַשָּׁנָה ב׳"], "Shabbat Chazon": ["שַׁבָּת חֲזוֹן"], "Shabbat HaChodesh": ["שַׁבָּת הַחֹדֶשׁ"], "Shabbat HaGadol": ["שַׁבָּת הַגָּדוֹל"], "Shabbat Nachamu": ["שַׁבָּת נַחֲמוּ"], "Shabbat Parah": ["שַׁבָּת פּרה"], "Shabbat Shekalim": ["שַׁבָּת שְׁקָלִים"], "Shabbat Shuva": ["שַׁבָּת שׁוּבָה"], "Shabbat Zachor": ["שַׁבָּת זָכוֹר"], "Shavuot": ["שָׁבוּעוֹת"], "Shavuot I": ["שָׁבוּעוֹת א׳"], "Shavuot II": ["שָׁבוּעוֹת ב׳"], "Shmini Atzeret": ["שְׁמִינִי עֲצֶרֶת"], "Shushan Purim": ["שׁוּשָׁן פּוּרִים"], "Sigd": ["סיגד"], "Simchat Torah": ["שִׂמְחַת תּוֹרָה"], "Sukkot": ["סוּכּוֹת"], "Sukkot I": ["סוּכּוֹת א׳"], "Sukkot II": ["סוּכּוֹת ב׳"], "Sukkot II (CH''M)": ["סוּכּוֹת ב׳ (חוה״מ)"], "Sukkot III (CH''M)": ["סוּכּוֹת ג׳ (חוה״מ)"], "Sukkot IV (CH''M)": ["סוּכּוֹת ד׳ (חוה״מ)"], "Sukkot V (CH''M)": ["סוּכּוֹת ה׳ (חוה״מ)"], "Sukkot VI (CH''M)": ["סוּכּוֹת ו׳ (חוה״מ)"], "Sukkot VII (Hoshana Raba)": ["סוּכּוֹת ז׳ (הוֹשַׁעְנָא רַבָּה)"], "Ta'anit Bechorot": ["תַּעֲנִית בְּכוֹרוֹת"], "Ta'anit Esther": ["תַּעֲנִית אֶסְתֵּר"], "Tish'a B'Av": ["תִּשְׁעָה בְּאָב"], "Tu B'Av": ["טוּ בְּאָב"], "Tu BiShvat": ["טוּ בִּשְׁבָט"], "Tu B'Shvat": ["טוּ בִּשְׁבָט"], "Tzom Gedaliah": ["צוֹם גְּדַלְיָה"], "Tzom Tammuz": ["צוֹם תָּמוּז"], "Yom HaAtzma'ut": ["יוֹם הָעַצְמָאוּת"], "Yom HaShoah": ["יוֹם הַשּׁוֹאָה"], "Yom HaZikaron": ["יוֹם הַזִּכָּרוֹן"], "Yom Kippur": ["יוֹם כִּפּוּר"], "Yom Yerushalayim": ["יוֹם יְרוּשָׁלַיִם"], "Yom HaAliyah": ["יוֹם הַעֲלִיָּה"], "Yom HaAliyah School Observance": ["שְׁמִירָת בֵּית הַסֵפֶר לְיוֹם הַעֲלִיָּה"], "Rosh Chodesh Adar": ["רֹאשׁ חוֹדֶשׁ אַדָר"], "Rosh Chodesh Adar I": ["רֹאשׁ חוֹדֶשׁ אַדָר א׳"], "Rosh Chodesh Adar II": ["רֹאשׁ חוֹדֶשׁ אַדָר ב׳"], "Rosh Chodesh Av": ["רֹאשׁ חוֹדֶשׁ אָב"], "Rosh Chodesh Cheshvan": ["רֹאשׁ חוֹדֶשׁ חֶשְׁוָן"], "Rosh Chodesh Elul": ["רֹאשׁ חוֹדֶשׁ אֱלוּל"], "Rosh Chodesh Iyyar": ["רֹאשׁ חוֹדֶשׁ אִיָיר"], "Rosh Chodesh Kislev": ["רֹאשׁ חוֹדֶשׁ כִּסְלֵו"], "Rosh Chodesh Nisan": ["רֹאשׁ חוֹדֶשׁ נִיסָן"], "Rosh Chodesh Sh'vat": ["רֹאשׁ חוֹדֶשׁ שְׁבָט"], "Rosh Chodesh Sivan": ["רֹאשׁ חוֹדֶשׁ סִיוָן"], "Rosh Chodesh Tamuz": ["רֹאשׁ חוֹדֶשׁ תָּמוּז"], "Rosh Chodesh Tevet": ["רֹאשׁ חוֹדֶשׁ טֵבֵת"], "min": ["דַּקּוֹת"], "Fast begins": ["תחילת הַצוֹם"], "Fast ends": ["סִיּוּם הַצוֹם"], "Rosh Hashana LaBehemot": ["רֹאשׁ הַשָּׁנָה לְמַעְשַׂר בְּהֵמָה"], "Tish'a B'Av (observed)": ["תִּשְׁעָה בְּאָב נִדחֶה"], "Shabbat Mevarchim Chodesh": ["שַׁבָּת מְבָרְכִים חוֹדֶשׁ"], "Shabbat Shirah": ["שַׁבָּת שִׁירָה"], "Chatzot HaLailah": ["חֲצוֹת הַלַיְלָה"], "Alot haShachar": ["עֲלוֹת הַשַּׁחַר"], "Misheyakir": ["מִשֶּׁיַּכִּיר"], "Misheyakir Machmir": ["מִשֶּׁיַּכִּיר מַחמִיר"], "Dawn": ["דִּימְדּוּמֵי בּוֹקֵר"], "Sunrise": ["הַנֵץ הַחַמָּה"], "Kriat Shema, sof zeman": ["סוֹף זְמַן קְרִיאַת שְׁמַע גר״א"], "Tefilah, sof zeman": ["סוֹף זְמַן תְּפִלָּה גר״א"], "Kriat Shema, sof zeman (MGA)": ["סוֹף זְמַן קְרִיאַת שְׁמַע מג״א"], "Tefilah, sof zeman (MGA)": ["סוֹף זְמַן תְּפִלָּה מג״א"], "Chatzot hayom": ["חֲצוֹת הַיּוֹם"], "Mincha Gedolah": ["מִנְחָה גְּדוֹלָה"], "Mincha Ketanah": ["מִנְחָה קְטַנָּה"], "Plag HaMincha": ["פְּלַג הַמִּנְחָה"], "Dusk": ["דִּימְדּוּמֵי עֶרֶב"], "Sunset": ["שְׁקִיעָה"], "Nightfall - End of ordained fasts": ["לַיְלָה - גמר תעניות דרבנן"], "Tzeit HaKochavim": ["צֵאת הַכּוֹכָבִים"], "Lovingkindness": ["חֶֽסֶד"], "Might": ["גְבוּרָה"], "Beauty": ["תִּפְאֶֽרֶת"], "Eternity": ["נֶּֽצַח"], "Splendor": ["הוֹד"], "Foundation": ["יְּסוֹד"], "Majesty": ["מַּלְכוּת"], "day": ["יוֹם"], "Yom Kippur Katan": ["יוֹם כִּפּוּר קָטָן"], "Yizkor": ["יִזְכּוֹר"], "Family Day": ["יוֹם הַמִּשׁפָּחָה"], "Yitzhak Rabin Memorial Day": ["יוֹם הַזִּכָּרוֹן ליצחק רבין"], "Jabotinsky Day": ["יוֹם ז׳בוטינסקי"], "Herzl Day": ["יוֹם הרצל"], "Ben-Gurion Day": ["יוֹם בן־גוריון"], "Hebrew Language Day": ["יוֹם הַשָׂפָה הַעִברִית"], "Birkat Hachamah": ["בִרְכַּת הַחַמָּה"], "Shushan Purim Katan": ["שׁוּשָׁן פּוּרִים קָטָן"], "Purim Meshulash": ["פּוּרִים מְשׁוּלָּשׁ"], "after sunset": ["לְאַחַר הַשְׁקִיעָה"], "Yerushalmi": ["יְרוּשַׁלְמִי"], "Chag HaBanot": ["חַג הַבָּנוֹת"], "Joshua": ["יְהוֹשׁוּעַ"], "Judges": ["שׁוֹפְטִים"], "I Samuel": ["שְׁמוּאֵל רִאשׁוֹן"], "II Samuel": ["שְׁמוּאֵל שֵׁנִי"], "I Kings": ["מְלָכִים רִאשׁוֹן"], "II Kings": ["מְלָכִים שֵׁנִי"], "Isaiah": ["יְשַׁעְיָהוּ"], "Jeremiah": ["יִרְמְיָהוּ"], "Ezekiel": ["יְחֶזְקֵאל"], "Hosea": ["הוֹשֵׁעַ"], "Joel": ["יוֹאֵל"], "Amos": ["עָמוּס"], "Obadiah": ["עוֹבַדְיָה"], "Jonah": ["יוֹנָה"], "Micah": ["מִיכָה"], "Nachum": ["נַחוּם"], "Habakkuk": ["חֲבַקּוּק"], "Zephaniah": ["צְפַנְיָה"], "Haggai": ["חַגַּי"], "Zechariah": ["זְכַרְיָה"], "Malachi": ["מַלְאָכִי"], "Psalms": ["תְּהִלִּים"], "Proverbs": ["מִשְׁלֵי"], "Job": ["אִיּוֹב"], "Song of Songs": ["שִׁיר הַשִּׁירִים"], "Ruth": ["רוּת"], "Lamentations": ["אֵיכָה"], "Ecclesiastes": ["קֹהֶלֶת"], "Esther": ["אֶסְתֵּר"], "Daniel": ["דָּנִיֵּאל"], "Ezra": ["עֶזְרָא"], "Nehemiah": ["נְחֶמְיָה"], "I Chronicles": ["דִברֵי הַיָמִים רִאשׁוֹן"], "II Chronicles": ["דִברֵי הַיָמִים שֵׁנִי"], "Molad": ["מוֹלָד הָלְּבָנָה"], "chalakim": ["חֲלָקִים"], "Pirkei Avot": ["פִּרְקֵי אָבוֹת"] } } };
|
|
14
1876
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1877
|
+
Locale.addTranslations('he', poHe);
|
|
1878
|
+
Locale.addTranslations('h', poHe);
|
|
1879
|
+
Locale.addTranslations('ashkenazi', poAshkenazi);
|
|
1880
|
+
Locale.addTranslations('a', poAshkenazi);
|
|
19
1881
|
/* Hebrew without nikkud */
|
|
20
1882
|
const heStrs = poHe.contexts[''];
|
|
21
1883
|
const heNoNikud = {};
|
|
22
1884
|
for (const [key, val] of Object.entries(heStrs)) {
|
|
23
|
-
heNoNikud[key] = [
|
|
1885
|
+
heNoNikud[key] = [Locale.hebrewStripNikkud(val[0])];
|
|
24
1886
|
}
|
|
25
1887
|
const poHeNoNikud = {
|
|
26
1888
|
headers: poHe.headers,
|
|
27
1889
|
contexts: { '': heNoNikud },
|
|
28
1890
|
};
|
|
29
|
-
|
|
1891
|
+
Locale.addTranslations('he-x-NoNikud', poHeNoNikud);
|
|
30
1892
|
|
|
31
1893
|
/**
|
|
32
1894
|
* Holiday flags for Event. These flags are typically
|
|
@@ -126,7 +1988,7 @@ class Event {
|
|
|
126
1988
|
* @param [attrs={}] optional additional attributes (e.g. `eventTimeStr`, `cholHaMoedDay`)
|
|
127
1989
|
*/
|
|
128
1990
|
constructor(date, desc, mask = 0, attrs) {
|
|
129
|
-
if (!
|
|
1991
|
+
if (!HDate.isHDate(date)) {
|
|
130
1992
|
throw new TypeError(`Invalid Event date: ${date}`);
|
|
131
1993
|
}
|
|
132
1994
|
else if (typeof desc !== 'string') {
|
|
@@ -170,7 +2032,7 @@ class Event {
|
|
|
170
2032
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
171
2033
|
*/
|
|
172
2034
|
render(locale) {
|
|
173
|
-
return
|
|
2035
|
+
return Locale.gettext(this.desc, locale);
|
|
174
2036
|
}
|
|
175
2037
|
/**
|
|
176
2038
|
* Returns a brief (translated) description of this event.
|
|
@@ -284,7 +2146,7 @@ class HebrewDateEvent extends Event {
|
|
|
284
2146
|
*/
|
|
285
2147
|
render(locale) {
|
|
286
2148
|
const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
287
|
-
const locale0 = locale1 !== null && locale1 !== void 0 ? locale1 :
|
|
2149
|
+
const locale0 = locale1 !== null && locale1 !== void 0 ? locale1 : Locale.getLocaleName();
|
|
288
2150
|
const hd = this.getDate();
|
|
289
2151
|
switch (locale0) {
|
|
290
2152
|
case 'h':
|
|
@@ -303,8 +2165,8 @@ class HebrewDateEvent extends Event {
|
|
|
303
2165
|
renderBriefHebrew(locale) {
|
|
304
2166
|
const hd = this.getDate();
|
|
305
2167
|
const dd = hd.getDate();
|
|
306
|
-
const mm =
|
|
307
|
-
return
|
|
2168
|
+
const mm = Locale.gettext(hd.getMonthName(), locale);
|
|
2169
|
+
return gematriya(dd) + ' ' + mm;
|
|
308
2170
|
}
|
|
309
2171
|
/**
|
|
310
2172
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
@@ -318,9 +2180,9 @@ class HebrewDateEvent extends Event {
|
|
|
318
2180
|
*/
|
|
319
2181
|
renderBrief(locale) {
|
|
320
2182
|
const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
321
|
-
const locale0 = locale1 !== null && locale1 !== void 0 ? locale1 :
|
|
2183
|
+
const locale0 = locale1 !== null && locale1 !== void 0 ? locale1 : Locale.getLocaleName();
|
|
322
2184
|
const hd = this.getDate();
|
|
323
|
-
if (hd.getMonth() ===
|
|
2185
|
+
if (hd.getMonth() === months.TISHREI && hd.getDate() === 1) {
|
|
324
2186
|
return this.render(locale0);
|
|
325
2187
|
}
|
|
326
2188
|
switch (locale0) {
|
|
@@ -334,6 +2196,1106 @@ class HebrewDateEvent extends Event {
|
|
|
334
2196
|
}
|
|
335
2197
|
}
|
|
336
2198
|
|
|
2199
|
+
/**
|
|
2200
|
+
* java.lang.Math.toRadians
|
|
2201
|
+
* @private
|
|
2202
|
+
* @param degrees
|
|
2203
|
+
*/
|
|
2204
|
+
function degreesToRadians(degrees) {
|
|
2205
|
+
return (degrees * Math.PI) / 180;
|
|
2206
|
+
}
|
|
2207
|
+
/**
|
|
2208
|
+
* java.lang.Math.toDegrees
|
|
2209
|
+
* @private
|
|
2210
|
+
* @param radians
|
|
2211
|
+
*/
|
|
2212
|
+
function radiansToDegrees(radians) {
|
|
2213
|
+
return (radians * 180) / Math.PI;
|
|
2214
|
+
}
|
|
2215
|
+
/**
|
|
2216
|
+
* A class that contains location information such as latitude and longitude required for astronomical calculations. The
|
|
2217
|
+
* elevation field may not be used by some calculation engines and would be ignored if set.
|
|
2218
|
+
*
|
|
2219
|
+
* @author © Eliyahu Hershfeld 2004 - 2016
|
|
2220
|
+
* @version 1.1
|
|
2221
|
+
*/
|
|
2222
|
+
class GeoLocation {
|
|
2223
|
+
/**
|
|
2224
|
+
* GeoLocation constructor with parameters for all required fields.
|
|
2225
|
+
*
|
|
2226
|
+
* @param {string} name
|
|
2227
|
+
* The location name for display use such as "Lakewood, NJ"
|
|
2228
|
+
* @param {number} latitude
|
|
2229
|
+
* the latitude in a double format such as 40.095965 for Lakewood, NJ.
|
|
2230
|
+
* <b>Note: </b> For latitudes south of the equator, a negative value should be used.
|
|
2231
|
+
* @param {number} longitude
|
|
2232
|
+
* double the longitude in a double format such as -74.222130 for Lakewood, NJ.
|
|
2233
|
+
* <b>Note: </b> For longitudes west of the <a href="http://en.wikipedia.org/wiki/Prime_Meridian">Prime
|
|
2234
|
+
* Meridian </a> (Greenwich), a negative value should be used.
|
|
2235
|
+
* @param {number} elevation
|
|
2236
|
+
* the elevation above sea level in Meters. Elevation is not used in most algorithms used for calculating
|
|
2237
|
+
* sunrise and set.
|
|
2238
|
+
* @param {string} timeZoneId
|
|
2239
|
+
* the <code>TimeZone</code> for the location.
|
|
2240
|
+
*/
|
|
2241
|
+
constructor(name, latitude, longitude, elevation, timeZoneId) {
|
|
2242
|
+
/**
|
|
2243
|
+
* @private
|
|
2244
|
+
*/
|
|
2245
|
+
this.locationName = null;
|
|
2246
|
+
this.setLocationName(name);
|
|
2247
|
+
this.setLatitude(latitude);
|
|
2248
|
+
this.setLongitude(longitude);
|
|
2249
|
+
this.setElevation(elevation);
|
|
2250
|
+
this.setTimeZone(timeZoneId);
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Method to get the elevation in Meters.
|
|
2254
|
+
*
|
|
2255
|
+
* @return {number} Returns the elevation in Meters.
|
|
2256
|
+
*/
|
|
2257
|
+
getElevation() {
|
|
2258
|
+
return this.elevation;
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Method to set the elevation in Meters <b>above </b> sea level.
|
|
2262
|
+
*
|
|
2263
|
+
* @param {number} elevation
|
|
2264
|
+
* The elevation to set in Meters. An Error will be thrown if the value is a negative.
|
|
2265
|
+
*/
|
|
2266
|
+
setElevation(elevation) {
|
|
2267
|
+
if (typeof elevation !== 'number')
|
|
2268
|
+
throw new TypeError('Invalid elevation');
|
|
2269
|
+
if (elevation < 0) {
|
|
2270
|
+
throw new RangeError(`elevation ${elevation} must be zero or positive`);
|
|
2271
|
+
}
|
|
2272
|
+
this.elevation = elevation;
|
|
2273
|
+
}
|
|
2274
|
+
setLatitude(latitude) {
|
|
2275
|
+
if (typeof latitude !== 'number')
|
|
2276
|
+
throw new TypeError('Invalid latitude');
|
|
2277
|
+
if (latitude < -90 || latitude > 90) {
|
|
2278
|
+
throw new RangeError(`Latitude ${latitude} out of range [-90,90]`);
|
|
2279
|
+
}
|
|
2280
|
+
this.latitude = latitude;
|
|
2281
|
+
}
|
|
2282
|
+
/**
|
|
2283
|
+
* @return {number} Returns the latitude.
|
|
2284
|
+
*/
|
|
2285
|
+
getLatitude() {
|
|
2286
|
+
return this.latitude;
|
|
2287
|
+
}
|
|
2288
|
+
setLongitude(longitude) {
|
|
2289
|
+
if (typeof longitude !== 'number')
|
|
2290
|
+
throw new TypeError('Invalid longitude');
|
|
2291
|
+
if (longitude < -180 || longitude > 180) {
|
|
2292
|
+
throw new RangeError(`Longitude ${longitude} out of range [-180,180]`);
|
|
2293
|
+
}
|
|
2294
|
+
this.longitude = longitude;
|
|
2295
|
+
}
|
|
2296
|
+
/**
|
|
2297
|
+
* @return {number} Returns the longitude.
|
|
2298
|
+
*/
|
|
2299
|
+
getLongitude() {
|
|
2300
|
+
return this.longitude;
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* @return {string|null} Returns the location name.
|
|
2304
|
+
*/
|
|
2305
|
+
getLocationName() {
|
|
2306
|
+
return this.locationName;
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* @param {string|null} name
|
|
2310
|
+
* The setter method for the display name.
|
|
2311
|
+
*/
|
|
2312
|
+
setLocationName(name) {
|
|
2313
|
+
this.locationName = name;
|
|
2314
|
+
}
|
|
2315
|
+
/**
|
|
2316
|
+
* @return {string} Returns the timeZone.
|
|
2317
|
+
*/
|
|
2318
|
+
getTimeZone() {
|
|
2319
|
+
return this.timeZoneId;
|
|
2320
|
+
}
|
|
2321
|
+
/**
|
|
2322
|
+
* Method to set the TimeZone.
|
|
2323
|
+
* @param {string} timeZoneId
|
|
2324
|
+
* The timeZone to set.
|
|
2325
|
+
*/
|
|
2326
|
+
setTimeZone(timeZoneId) {
|
|
2327
|
+
if (!timeZoneId) {
|
|
2328
|
+
throw new RangeError('Invalid timeZoneId');
|
|
2329
|
+
}
|
|
2330
|
+
this.timeZoneId = timeZoneId;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* The commonly used average solar refraction. Calendrical Calculations lists a more accurate global average of
|
|
2335
|
+
* 34.478885263888294
|
|
2336
|
+
* @private
|
|
2337
|
+
*/
|
|
2338
|
+
const refraction = 34 / 60;
|
|
2339
|
+
// private double refraction = 34.478885263888294 / 60d;
|
|
2340
|
+
/**
|
|
2341
|
+
* The commonly used average solar radius in minutes of a degree.
|
|
2342
|
+
* @private
|
|
2343
|
+
*/
|
|
2344
|
+
const solarRadius = 16 / 60;
|
|
2345
|
+
/**
|
|
2346
|
+
* The commonly used average earth radius in KM. At this time, this only affects elevation adjustment and not the
|
|
2347
|
+
* sunrise and sunset calculations. The value currently defaults to 6356.9 KM.
|
|
2348
|
+
* @private
|
|
2349
|
+
*/
|
|
2350
|
+
const earthRadius = 6356.9; // in KM
|
|
2351
|
+
/**
|
|
2352
|
+
* Implementation of sunrise and sunset methods to calculate astronomical times based on the <a
|
|
2353
|
+
* href="http://noaa.gov">NOAA</a> algorithm. This calculator uses the Java algorithm based on the implementation by <a
|
|
2354
|
+
* href="http://noaa.gov">NOAA - National Oceanic and Atmospheric Administration</a>'s <a href =
|
|
2355
|
+
* "http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html">Surface Radiation Research Branch</a>. NOAA's <a
|
|
2356
|
+
* href="http://www.srrb.noaa.gov/highlights/sunrise/solareqns.PDF">implementation</a> is based on equations from <a
|
|
2357
|
+
* href="http://www.willbell.com/math/mc1.htm">Astronomical Algorithms</a> by <a
|
|
2358
|
+
* href="http://en.wikipedia.org/wiki/Jean_Meeus">Jean Meeus</a>. Added to the algorithm is an adjustment of the zenith
|
|
2359
|
+
* to account for elevation. The algorithm can be found in the <a
|
|
2360
|
+
* href="http://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation</a> article.
|
|
2361
|
+
*
|
|
2362
|
+
* @author © Eliyahu Hershfeld 2011 - 2019
|
|
2363
|
+
*/
|
|
2364
|
+
class NOAACalculator {
|
|
2365
|
+
/**
|
|
2366
|
+
* A constructor that takes in <a href="http://en.wikipedia.org/wiki/Geolocation">geolocation</a> information as a
|
|
2367
|
+
* parameter.
|
|
2368
|
+
*
|
|
2369
|
+
* @param {GeoLocation} geoLocation
|
|
2370
|
+
* The location information used for calculating astronomical sun times.
|
|
2371
|
+
* @param {Temporal.PlainDate} date
|
|
2372
|
+
*/
|
|
2373
|
+
constructor(geoLocation, date) {
|
|
2374
|
+
this.date = date;
|
|
2375
|
+
this.geoLocation = geoLocation;
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* The getSunrise method Returns a `Date` representing the
|
|
2379
|
+
* {@link getElevationAdjustment elevation adjusted} sunrise time. The zenith used
|
|
2380
|
+
* for the calculation uses {@link GEOMETRIC_ZENITH geometric zenith} of 90° plus
|
|
2381
|
+
* {@link getElevationAdjustment}. This is adjusted
|
|
2382
|
+
* to add approximately 50/60 of a degree to account for 34 archminutes of refraction
|
|
2383
|
+
* and 16 archminutes for the sun's radius for a total of {@link adjustZenith 90.83333°}.
|
|
2384
|
+
*
|
|
2385
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` representing the exact sunrise time. If the calculation can't be computed such as
|
|
2386
|
+
* in the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it
|
|
2387
|
+
* does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2388
|
+
* @see adjustZenith
|
|
2389
|
+
* @see getSeaLevelSunrise()
|
|
2390
|
+
* @see getUTCSunrise
|
|
2391
|
+
*/
|
|
2392
|
+
getSunrise() {
|
|
2393
|
+
const sunrise = this.getUTCSunrise0(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2394
|
+
if (isNaN(sunrise))
|
|
2395
|
+
return null;
|
|
2396
|
+
return this.getDateFromTime(sunrise, true);
|
|
2397
|
+
}
|
|
2398
|
+
/**
|
|
2399
|
+
* A method that returns the sunrise without {@link getElevationAdjustment elevation
|
|
2400
|
+
* adjustment}. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible light,
|
|
2401
|
+
* something that is not affected by elevation. This method returns sunrise calculated at sea level. This forms the
|
|
2402
|
+
* base for dawn calculations that are calculated as a dip below the horizon before sunrise.
|
|
2403
|
+
*
|
|
2404
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` representing the exact sea-level sunrise time. If the calculation can't be computed
|
|
2405
|
+
* such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one
|
|
2406
|
+
* where it does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2407
|
+
* @see getSunrise
|
|
2408
|
+
* @see getUTCSeaLevelSunrise
|
|
2409
|
+
* @see getSeaLevelSunset()
|
|
2410
|
+
*/
|
|
2411
|
+
getSeaLevelSunrise() {
|
|
2412
|
+
const sunrise = this.getUTCSeaLevelSunrise(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2413
|
+
if (isNaN(sunrise))
|
|
2414
|
+
return null;
|
|
2415
|
+
return this.getDateFromTime(sunrise, true);
|
|
2416
|
+
}
|
|
2417
|
+
/**
|
|
2418
|
+
* A method that returns the beginning of civil twilight (dawn) using a zenith of {@link CIVIL_ZENITH 96°}.
|
|
2419
|
+
*
|
|
2420
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of civil twilight using a zenith of 96°. If the calculation
|
|
2421
|
+
* can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2422
|
+
* @see CIVIL_ZENITH
|
|
2423
|
+
*/
|
|
2424
|
+
getBeginCivilTwilight() {
|
|
2425
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.CIVIL_ZENITH);
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* A method that returns the beginning of nautical twilight using a zenith of {@link NAUTICAL_ZENITH 102°}.
|
|
2429
|
+
*
|
|
2430
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of nautical twilight using a zenith of 102°. If the
|
|
2431
|
+
* calculation can't be computed null will be returned. See detailed explanation on top of the page.
|
|
2432
|
+
* @see NAUTICAL_ZENITH
|
|
2433
|
+
*/
|
|
2434
|
+
getBeginNauticalTwilight() {
|
|
2435
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.NAUTICAL_ZENITH);
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* A method that returns the beginning of astronomical twilight using a zenith of {@link ASTRONOMICAL_ZENITH
|
|
2439
|
+
* 108°}.
|
|
2440
|
+
*
|
|
2441
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of astronomical twilight using a zenith of 108°. If the
|
|
2442
|
+
* calculation can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2443
|
+
* @see ASTRONOMICAL_ZENITH
|
|
2444
|
+
*/
|
|
2445
|
+
getBeginAstronomicalTwilight() {
|
|
2446
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.ASTRONOMICAL_ZENITH);
|
|
2447
|
+
}
|
|
2448
|
+
/**
|
|
2449
|
+
* The getSunset method Returns a `Date` representing the
|
|
2450
|
+
* {@link getElevationAdjustment elevation adjusted} sunset time. The zenith used for
|
|
2451
|
+
* the calculation uses {@link GEOMETRIC_ZENITH geometric zenith} of 90° plus
|
|
2452
|
+
* {@link getElevationAdjustment}. This is adjusted
|
|
2453
|
+
* to add approximately 50/60 of a degree to account for 34 archminutes of refraction
|
|
2454
|
+
* and 16 archminutes for the sun's radius for a total of {@link adjustZenith 90.83333°}.
|
|
2455
|
+
* Note:
|
|
2456
|
+
* In certain cases the calculates sunset will occur before sunrise. This will typically happen when a timezone
|
|
2457
|
+
* other than the local timezone is used (calculating Los Angeles sunset using a GMT timezone for example). In this
|
|
2458
|
+
* case the sunset date will be incremented to the following date.
|
|
2459
|
+
*
|
|
2460
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing the exact sunset time. If the calculation can't be computed such as in
|
|
2461
|
+
* the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it
|
|
2462
|
+
* does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2463
|
+
* @see adjustZenith
|
|
2464
|
+
* @see getSeaLevelSunset()
|
|
2465
|
+
* @see getUTCSunset
|
|
2466
|
+
*/
|
|
2467
|
+
getSunset() {
|
|
2468
|
+
const sunset = this.getUTCSunset0(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2469
|
+
if (isNaN(sunset))
|
|
2470
|
+
return null;
|
|
2471
|
+
return this.getDateFromTime(sunset, false);
|
|
2472
|
+
}
|
|
2473
|
+
/**
|
|
2474
|
+
* A method that returns the sunset without {@link getElevationAdjustment elevation
|
|
2475
|
+
* adjustment}. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible light,
|
|
2476
|
+
* something that is not affected by elevation. This method returns sunset calculated at sea level. This forms the
|
|
2477
|
+
* base for dusk calculations that are calculated as a dip below the horizon after sunset.
|
|
2478
|
+
*
|
|
2479
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing the exact sea-level sunset time. If the calculation can't be computed
|
|
2480
|
+
* such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one
|
|
2481
|
+
* where it does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2482
|
+
* @see getSunset
|
|
2483
|
+
* @see getUTCSeaLevelSunset
|
|
2484
|
+
*/
|
|
2485
|
+
getSeaLevelSunset() {
|
|
2486
|
+
const sunset = this.getUTCSeaLevelSunset(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2487
|
+
if (isNaN(sunset))
|
|
2488
|
+
return null;
|
|
2489
|
+
return this.getDateFromTime(sunset, false);
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* A method that returns the end of civil twilight using a zenith of {@link CIVIL_ZENITH 96°}.
|
|
2493
|
+
*
|
|
2494
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of civil twilight using a zenith of {@link CIVIL_ZENITH 96°}. If
|
|
2495
|
+
* the calculation can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2496
|
+
* @see CIVIL_ZENITH
|
|
2497
|
+
*/
|
|
2498
|
+
getEndCivilTwilight() {
|
|
2499
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.CIVIL_ZENITH);
|
|
2500
|
+
}
|
|
2501
|
+
/**
|
|
2502
|
+
* A method that returns the end of nautical twilight using a zenith of {@link NAUTICAL_ZENITH 102°}.
|
|
2503
|
+
*
|
|
2504
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of nautical twilight using a zenith of {@link NAUTICAL_ZENITH 102°}
|
|
2505
|
+
* . If the calculation can't be computed, null will be returned. See detailed explanation on top of the
|
|
2506
|
+
* page.
|
|
2507
|
+
* @see NAUTICAL_ZENITH
|
|
2508
|
+
*/
|
|
2509
|
+
getEndNauticalTwilight() {
|
|
2510
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.NAUTICAL_ZENITH);
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* A method that returns the end of astronomical twilight using a zenith of {@link ASTRONOMICAL_ZENITH 108°}.
|
|
2514
|
+
*
|
|
2515
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of astronomical twilight using a zenith of {@link ASTRONOMICAL_ZENITH
|
|
2516
|
+
* 108°}. If the calculation can't be computed, null will be returned. See detailed explanation on top
|
|
2517
|
+
* of the page.
|
|
2518
|
+
* @see ASTRONOMICAL_ZENITH
|
|
2519
|
+
*/
|
|
2520
|
+
getEndAstronomicalTwilight() {
|
|
2521
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.ASTRONOMICAL_ZENITH);
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* A utility method that returns a date offset by the offset time passed in. Please note that the level of light
|
|
2525
|
+
* during twilight is not affected by elevation, so if this is being used to calculate an offset before sunrise or
|
|
2526
|
+
* after sunset with the intent of getting a rough "level of light" calculation, the sunrise or sunset time passed
|
|
2527
|
+
* to this method should be sea level sunrise and sunset.
|
|
2528
|
+
*
|
|
2529
|
+
* @param {Temporal.ZonedDateTime | null} time
|
|
2530
|
+
* the start time
|
|
2531
|
+
* @param {number} offset
|
|
2532
|
+
* the offset in milliseconds to add to the time.
|
|
2533
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` with the offset in milliseconds added to it
|
|
2534
|
+
*/
|
|
2535
|
+
static getTimeOffset(time, offset) {
|
|
2536
|
+
if (time === null || isNaN(offset)) {
|
|
2537
|
+
return null;
|
|
2538
|
+
}
|
|
2539
|
+
return time.add({ milliseconds: offset });
|
|
2540
|
+
}
|
|
2541
|
+
/**
|
|
2542
|
+
* A utility method that returns the time of an offset by degrees below or above the horizon of
|
|
2543
|
+
* {@link getSunrise() sunrise}. Note that the degree offset is from the vertical, so for a calculation of 14°
|
|
2544
|
+
* before sunrise, an offset of 14 + {@link GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2545
|
+
*
|
|
2546
|
+
* @param {number} offsetZenith
|
|
2547
|
+
* the degrees before {@link getSunrise} to use in the calculation. For time after sunrise use
|
|
2548
|
+
* negative numbers. Note that the degree offset is from the vertical, so for a calculation of 14°
|
|
2549
|
+
* before sunrise, an offset of 14 + {@link GEOMETRIC_ZENITH} = 104 would have to be passed as a
|
|
2550
|
+
* parameter.
|
|
2551
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the offset after (or before) {@link getSunrise}. If the calculation
|
|
2552
|
+
* can't be computed such as in the Arctic Circle where there is at least one day a year where the sun does
|
|
2553
|
+
* not rise, and one where it does not set, a null will be returned. See detailed explanation on top of the
|
|
2554
|
+
* page.
|
|
2555
|
+
*/
|
|
2556
|
+
getSunriseOffsetByDegrees(offsetZenith) {
|
|
2557
|
+
const dawn = this.getUTCSunrise0(offsetZenith);
|
|
2558
|
+
if (isNaN(dawn))
|
|
2559
|
+
return null;
|
|
2560
|
+
return this.getDateFromTime(dawn, true);
|
|
2561
|
+
}
|
|
2562
|
+
/**
|
|
2563
|
+
* A utility method that returns the time of an offset by degrees below or above the horizon of {@link getSunset()
|
|
2564
|
+
* sunset}. Note that the degree offset is from the vertical, so for a calculation of 14° after sunset, an
|
|
2565
|
+
* offset of 14 + {@link GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2566
|
+
*
|
|
2567
|
+
* @param {number} offsetZenith
|
|
2568
|
+
* the degrees after {@link getSunset} to use in the calculation. For time before sunset use negative
|
|
2569
|
+
* numbers. Note that the degree offset is from the vertical, so for a calculation of 14° after
|
|
2570
|
+
* sunset, an offset of 14 + {@link GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2571
|
+
* @return {Temporal.ZonedDateTime | null} The `Date`of the offset after (or before) {@link getSunset}. If the calculation can't
|
|
2572
|
+
* be computed such as in the Arctic Circle where there is at least one day a year where the sun does not
|
|
2573
|
+
* rise, and one where it does not set, a null will be returned. See detailed explanation on top of the
|
|
2574
|
+
* page.
|
|
2575
|
+
*/
|
|
2576
|
+
getSunsetOffsetByDegrees(offsetZenith) {
|
|
2577
|
+
const sunset = this.getUTCSunset0(offsetZenith);
|
|
2578
|
+
if (isNaN(sunset))
|
|
2579
|
+
return null;
|
|
2580
|
+
return this.getDateFromTime(sunset, false);
|
|
2581
|
+
}
|
|
2582
|
+
/**
|
|
2583
|
+
* A method that returns the sunrise in UTC time without correction for time zone offset from GMT and without using
|
|
2584
|
+
* daylight savings time.
|
|
2585
|
+
*
|
|
2586
|
+
* @param {number} zenith
|
|
2587
|
+
* the degrees below the horizon. For time after sunrise use negative numbers.
|
|
2588
|
+
* @return {number} The time in the format: 18.75 for 18:45:00 UTC/GMT. If the calculation can't be computed such as in the
|
|
2589
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2590
|
+
* not set, `NaN` will be returned. See detailed explanation on top of the page.
|
|
2591
|
+
*/
|
|
2592
|
+
getUTCSunrise0(zenith) {
|
|
2593
|
+
return this.getUTCSunrise(this.getAdjustedDate(), this.geoLocation, zenith, true);
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* A method that returns the sunrise in UTC time without correction for time zone offset from GMT and without using
|
|
2597
|
+
* daylight savings time. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible
|
|
2598
|
+
* light, something that is not affected by elevation. This method returns UTC sunrise calculated at sea level. This
|
|
2599
|
+
* forms the base for dawn calculations that are calculated as a dip below the horizon before sunrise.
|
|
2600
|
+
*
|
|
2601
|
+
* @param {number} zenith
|
|
2602
|
+
* the degrees below the horizon. For time after sunrise use negative numbers.
|
|
2603
|
+
* @return {number} The time in the format: 18.75 for 18:45:00 UTC/GMT. If the calculation can't be computed such as in the
|
|
2604
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2605
|
+
* not set, `NaN` will be returned. See detailed explanation on top of the page.
|
|
2606
|
+
* @see getUTCSunrise
|
|
2607
|
+
* @see getUTCSeaLevelSunset
|
|
2608
|
+
*/
|
|
2609
|
+
getUTCSeaLevelSunrise(zenith) {
|
|
2610
|
+
return this.getUTCSunrise(this.getAdjustedDate(), this.geoLocation, zenith, false);
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* A method that returns the sunset in UTC time without correction for time zone offset from GMT and without using
|
|
2614
|
+
* daylight savings time.
|
|
2615
|
+
*
|
|
2616
|
+
* @param {number} zenith
|
|
2617
|
+
* the degrees below the horizon. For time after sunset use negative numbers.
|
|
2618
|
+
* @return {number} The time in the format: 18.75 for 18:45:00 UTC/GMT. If the calculation can't be computed such as in the
|
|
2619
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2620
|
+
* not set, `NaN` will be returned. See detailed explanation on top of the page.
|
|
2621
|
+
* @see getUTCSeaLevelSunset
|
|
2622
|
+
*/
|
|
2623
|
+
getUTCSunset0(zenith) {
|
|
2624
|
+
return this.getUTCSunset(this.getAdjustedDate(), this.geoLocation, zenith, true);
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* A method that returns the sunset in UTC time without correction for elevation, time zone offset from GMT and
|
|
2628
|
+
* without using daylight savings time. Non-sunrise and sunset calculations such as dawn and dusk, depend on the
|
|
2629
|
+
* amount of visible light, something that is not affected by elevation. This method returns UTC sunset calculated
|
|
2630
|
+
* at sea level. This forms the base for dusk calculations that are calculated as a dip below the horizon after
|
|
2631
|
+
* sunset.
|
|
2632
|
+
*
|
|
2633
|
+
* @param {number} zenith
|
|
2634
|
+
* the degrees below the horizon. For time before sunset use negative numbers.
|
|
2635
|
+
* @return {number} The time in the format: 18.75 for 18:45:00 UTC/GMT. If the calculation can't be computed such as in the
|
|
2636
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2637
|
+
* not set, `NaN` will be returned. See detailed explanation on top of the page.
|
|
2638
|
+
* @see getUTCSunset
|
|
2639
|
+
* @see getUTCSeaLevelSunrise
|
|
2640
|
+
*/
|
|
2641
|
+
getUTCSeaLevelSunset(zenith) {
|
|
2642
|
+
return this.getUTCSunset(this.getAdjustedDate(), this.geoLocation, zenith, false);
|
|
2643
|
+
}
|
|
2644
|
+
/**
|
|
2645
|
+
* Adjusts the <code>Calendar</code> to deal with edge cases where the location crosses the antimeridian.
|
|
2646
|
+
* @private
|
|
2647
|
+
* @see GeoLocation#getAntimeridianAdjustment()
|
|
2648
|
+
* @return the adjusted Calendar
|
|
2649
|
+
*/
|
|
2650
|
+
getAdjustedDate() {
|
|
2651
|
+
return this.date;
|
|
2652
|
+
}
|
|
2653
|
+
/**
|
|
2654
|
+
* Method to return the adjustment to the zenith required to account for the elevation. Since a person at a higher
|
|
2655
|
+
* elevation can see farther below the horizon, the calculation for sunrise / sunset is calculated below the horizon
|
|
2656
|
+
* used at sea level. This is only used for sunrise and sunset and not times before or after it such as
|
|
2657
|
+
* {@link getBeginNauticalTwilight() nautical twilight} since those
|
|
2658
|
+
* calculations are based on the level of available light at the given dip below the horizon, something that is not
|
|
2659
|
+
* affected by elevation, the adjustment should only made if the zenith == 90° {@link adjustZenith adjusted}
|
|
2660
|
+
* for refraction and solar radius. The algorithm used is
|
|
2661
|
+
*
|
|
2662
|
+
* <pre>
|
|
2663
|
+
* elevationAdjustment = Math.toDegrees(Math.acos(earthRadiusInMeters / (earthRadiusInMeters + elevationMeters)));
|
|
2664
|
+
* </pre>
|
|
2665
|
+
*
|
|
2666
|
+
* The source of this algorithm is <a href="http://www.calendarists.com">Calendrical Calculations</a> by Edward M.
|
|
2667
|
+
* Reingold and Nachum Dershowitz. An alternate algorithm that produces an almost identical (but not accurate)
|
|
2668
|
+
* result found in Ma'aglay Tzedek by Moishe Kosower and other sources is:
|
|
2669
|
+
*
|
|
2670
|
+
* <pre>
|
|
2671
|
+
* elevationAdjustment = 0.0347 * Math.sqrt(elevationMeters);
|
|
2672
|
+
* </pre>
|
|
2673
|
+
*
|
|
2674
|
+
* @param {number} elevation
|
|
2675
|
+
* elevation in Meters.
|
|
2676
|
+
* @return {number} the adjusted zenith
|
|
2677
|
+
*/
|
|
2678
|
+
getElevationAdjustment(elevation) {
|
|
2679
|
+
// double elevationAdjustment = 0.0347 * Math.sqrt(elevation);
|
|
2680
|
+
const elevationAdjustment = radiansToDegrees(Math.acos(earthRadius / (earthRadius + elevation / 1000)));
|
|
2681
|
+
return elevationAdjustment;
|
|
2682
|
+
}
|
|
2683
|
+
/**
|
|
2684
|
+
* Adjusts the zenith of astronomical sunrise and sunset to account for solar refraction, solar radius and
|
|
2685
|
+
* elevation. The value for Sun's zenith and true rise/set Zenith (used in this class and subclasses) is the angle
|
|
2686
|
+
* that the center of the Sun makes to a line perpendicular to the Earth's surface. If the Sun were a point and the
|
|
2687
|
+
* Earth were without an atmosphere, true sunset and sunrise would correspond to a 90° zenith. Because the Sun
|
|
2688
|
+
* is not a point, and because the atmosphere refracts light, this 90° zenith does not, in fact, correspond to
|
|
2689
|
+
* true sunset or sunrise, instead the centre of the Sun's disk must lie just below the horizon for the upper edge
|
|
2690
|
+
* to be obscured. This means that a zenith of just above 90° must be used. The Sun subtends an angle of 16
|
|
2691
|
+
* minutes of arc, and atmospheric refraction
|
|
2692
|
+
* accounts for 34 minutes or so, giving a total
|
|
2693
|
+
* of 50 arcminutes. The total value for ZENITH is 90+(5/6) or 90.8333333° for true sunrise/sunset. Since a
|
|
2694
|
+
* person at an elevation can see blow the horizon of a person at sea level, this will also adjust the zenith to
|
|
2695
|
+
* account for elevation if available. Note that this will only adjust the value if the zenith is exactly 90 degrees.
|
|
2696
|
+
* For values below and above this no correction is done. As an example, astronomical twilight is when the sun is
|
|
2697
|
+
* 18° below the horizon or {@link ASTRONOMICAL_ZENITH 108°
|
|
2698
|
+
* below the zenith}. This is traditionally calculated with none of the above mentioned adjustments. The same goes
|
|
2699
|
+
* for various <em>tzais</em> and <em>alos</em> times such as the
|
|
2700
|
+
* {@link ZmanimCalendar#ZENITH_16_POINT_1 16.1°} dip used in
|
|
2701
|
+
* {@link ComplexZmanimCalendar#getAlos16Point1Degrees}.
|
|
2702
|
+
*
|
|
2703
|
+
* @param {number} zenith
|
|
2704
|
+
* the azimuth below the vertical zenith of 90°. For sunset typically the {@link adjustZenith
|
|
2705
|
+
* zenith} used for the calculation uses geometric zenith of 90° and {@link adjustZenith adjusts}
|
|
2706
|
+
* this slightly to account for solar refraction and the sun's radius. Another example would be
|
|
2707
|
+
* {@link getEndNauticalTwilight} that passes
|
|
2708
|
+
* {@link NAUTICAL_ZENITH} to this method.
|
|
2709
|
+
* @param {number} elevation
|
|
2710
|
+
* elevation in Meters.
|
|
2711
|
+
* @return {number} The zenith adjusted to include the sun's radius, refracton
|
|
2712
|
+
* and {@link getElevationAdjustment elevation} adjustment. This will only be adjusted for
|
|
2713
|
+
* sunrise and sunset (if the zenith == 90°)
|
|
2714
|
+
* @see getElevationAdjustment
|
|
2715
|
+
*/
|
|
2716
|
+
adjustZenith(zenith, elevation) {
|
|
2717
|
+
let adjustedZenith = zenith;
|
|
2718
|
+
if (zenith === NOAACalculator.GEOMETRIC_ZENITH) {
|
|
2719
|
+
// only adjust if it is exactly sunrise or sunset
|
|
2720
|
+
adjustedZenith =
|
|
2721
|
+
zenith +
|
|
2722
|
+
(solarRadius + refraction + this.getElevationAdjustment(elevation));
|
|
2723
|
+
}
|
|
2724
|
+
return adjustedZenith;
|
|
2725
|
+
}
|
|
2726
|
+
/**
|
|
2727
|
+
* A method that calculates UTC sunrise as well as any time based on an angle above or below sunrise.
|
|
2728
|
+
* @param date
|
|
2729
|
+
* Used to calculate day of year.
|
|
2730
|
+
* @param geoLocation
|
|
2731
|
+
* The location information used for astronomical calculating sun times.
|
|
2732
|
+
* @param zenith
|
|
2733
|
+
* the azimuth below the vertical zenith of 90 degrees. for sunrise typically the {@link adjustZenith
|
|
2734
|
+
* zenith} used for the calculation uses geometric zenith of 90° and {@link adjustZenith adjusts}
|
|
2735
|
+
* this slightly to account for solar refraction and the sun's radius. Another example would be
|
|
2736
|
+
* {@link getBeginNauticalTwilight} that passes
|
|
2737
|
+
* {@link NAUTICAL_ZENITH} to this method.
|
|
2738
|
+
* @param adjustForElevation
|
|
2739
|
+
* Should the time be adjusted for elevation
|
|
2740
|
+
* @return The UTC time of sunrise in 24 hour format. 5:45:00 AM will return 5.75.0. If an error was encountered in
|
|
2741
|
+
* the calculation (expected behavior for some locations such as near the poles,
|
|
2742
|
+
* `NaN` will be returned.
|
|
2743
|
+
*/
|
|
2744
|
+
getUTCSunrise(date, geoLocation, zenith, adjustForElevation) {
|
|
2745
|
+
const elevation = adjustForElevation
|
|
2746
|
+
? geoLocation.getElevation()
|
|
2747
|
+
: 0;
|
|
2748
|
+
const adjustedZenith = this.adjustZenith(zenith, elevation);
|
|
2749
|
+
let sunrise = NOAACalculator.getSunriseUTC(NOAACalculator.getJulianDay(date), geoLocation.getLatitude(), -geoLocation.getLongitude(), adjustedZenith);
|
|
2750
|
+
sunrise = sunrise / 60;
|
|
2751
|
+
// ensure that the time is >= 0 and < 24
|
|
2752
|
+
while (sunrise < 0) {
|
|
2753
|
+
sunrise += 24;
|
|
2754
|
+
}
|
|
2755
|
+
while (sunrise >= 24) {
|
|
2756
|
+
sunrise -= 24;
|
|
2757
|
+
}
|
|
2758
|
+
return sunrise;
|
|
2759
|
+
}
|
|
2760
|
+
/**
|
|
2761
|
+
* A method that calculates UTC sunset as well as any time based on an angle above or below sunset.
|
|
2762
|
+
* @param date
|
|
2763
|
+
* Used to calculate day of year.
|
|
2764
|
+
* @param geoLocation
|
|
2765
|
+
* The location information used for astronomical calculating sun times.
|
|
2766
|
+
* @param zenith
|
|
2767
|
+
* the azimuth below the vertical zenith of 90°. For sunset typically the {@link adjustZenith
|
|
2768
|
+
* zenith} used for the calculation uses geometric zenith of 90° and {@link adjustZenith adjusts}
|
|
2769
|
+
* this slightly to account for solar refraction and the sun's radius. Another example would be
|
|
2770
|
+
* {@link getEndNauticalTwilight} that passes
|
|
2771
|
+
* {@link NAUTICAL_ZENITH} to this method.
|
|
2772
|
+
* @param adjustForElevation
|
|
2773
|
+
* Should the time be adjusted for elevation
|
|
2774
|
+
* @return The UTC time of sunset in 24 hour format. 5:45:00 AM will return 5.75.0. If an error was encountered in
|
|
2775
|
+
* the calculation (expected behavior for some locations such as near the poles,
|
|
2776
|
+
* `NaN` will be returned.
|
|
2777
|
+
*/
|
|
2778
|
+
getUTCSunset(date, geoLocation, zenith, adjustForElevation) {
|
|
2779
|
+
const elevation = adjustForElevation
|
|
2780
|
+
? geoLocation.getElevation()
|
|
2781
|
+
: 0;
|
|
2782
|
+
const adjustedZenith = this.adjustZenith(zenith, elevation);
|
|
2783
|
+
let sunset = NOAACalculator.getSunsetUTC(NOAACalculator.getJulianDay(date), geoLocation.getLatitude(), -geoLocation.getLongitude(), adjustedZenith);
|
|
2784
|
+
sunset = sunset / 60;
|
|
2785
|
+
// ensure that the time is >= 0 and < 24
|
|
2786
|
+
while (sunset < 0) {
|
|
2787
|
+
sunset += 24;
|
|
2788
|
+
}
|
|
2789
|
+
while (sunset >= 24) {
|
|
2790
|
+
sunset -= 24;
|
|
2791
|
+
}
|
|
2792
|
+
return sunset;
|
|
2793
|
+
}
|
|
2794
|
+
/**
|
|
2795
|
+
* A utility method that will allow the calculation of a temporal (solar) hour based on the sunrise and sunset
|
|
2796
|
+
* passed as parameters to this method. An example of the use of this method would be the calculation of a
|
|
2797
|
+
* non-elevation adjusted temporal hour by passing in {@link getSeaLevelSunrise() sea level sunrise} and
|
|
2798
|
+
* {@link getSeaLevelSunset() sea level sunset} as parameters.
|
|
2799
|
+
*
|
|
2800
|
+
* @param {Temporal.ZonedDateTime | null} startOfDay
|
|
2801
|
+
* The start of the day.
|
|
2802
|
+
* @param {Temporal.ZonedDateTime | null} endOfDay
|
|
2803
|
+
* The end of the day.
|
|
2804
|
+
*
|
|
2805
|
+
* @return {number} the <code>long</code> millisecond length of the temporal hour. If the calculation can't be computed a
|
|
2806
|
+
* `NaN` will be returned. See detailed explanation on top of the page.
|
|
2807
|
+
*
|
|
2808
|
+
* @see getTemporalHour()
|
|
2809
|
+
*/
|
|
2810
|
+
getTemporalHour(startOfDay = this.getSeaLevelSunrise(), endOfDay = this.getSeaLevelSunset()) {
|
|
2811
|
+
if (startOfDay === null || endOfDay === null) {
|
|
2812
|
+
return NaN;
|
|
2813
|
+
}
|
|
2814
|
+
const delta = endOfDay.epochMilliseconds - startOfDay.epochMilliseconds;
|
|
2815
|
+
return Math.floor(delta / 12);
|
|
2816
|
+
}
|
|
2817
|
+
/**
|
|
2818
|
+
* A method that returns sundial or solar noon. It occurs when the Sun is <a href
|
|
2819
|
+
* ="http://en.wikipedia.org/wiki/Transit_%28astronomy%29">transiting</a> the <a
|
|
2820
|
+
* href="http://en.wikipedia.org/wiki/Meridian_%28astronomy%29">celestial meridian</a>. In this class it is
|
|
2821
|
+
* calculated as halfway between the sunrise and sunset passed to this method. This time can be slightly off the
|
|
2822
|
+
* real transit time due to changes in declination (the lengthening or shortening day).
|
|
2823
|
+
*
|
|
2824
|
+
* @param {Temporal.ZonedDateTime | null} startOfDay
|
|
2825
|
+
* the start of day for calculating the sun's transit. This can be sea level sunrise, visual sunrise (or
|
|
2826
|
+
* any arbitrary start of day) passed to this method.
|
|
2827
|
+
* @param {Temporal.ZonedDateTime | null} endOfDay
|
|
2828
|
+
* the end of day for calculating the sun's transit. This can be sea level sunset, visual sunset (or any
|
|
2829
|
+
* arbitrary end of day) passed to this method.
|
|
2830
|
+
*
|
|
2831
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing Sun's transit. If the calculation can't be computed such as in the
|
|
2832
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2833
|
+
* not set, null will be returned. See detailed explanation on top of the page.
|
|
2834
|
+
*/
|
|
2835
|
+
getSunTransit(startOfDay = this.getSeaLevelSunrise(), endOfDay = this.getSeaLevelSunset()) {
|
|
2836
|
+
const temporalHour = this.getTemporalHour(startOfDay, endOfDay);
|
|
2837
|
+
return NOAACalculator.getTimeOffset(startOfDay, temporalHour * 6);
|
|
2838
|
+
}
|
|
2839
|
+
/**
|
|
2840
|
+
* A method that returns a `Date` from the time passed in as a parameter.
|
|
2841
|
+
* @protected
|
|
2842
|
+
* @param {number} time
|
|
2843
|
+
* The time to be set as the time for the `Date`. The time expected is in the format: 18.75
|
|
2844
|
+
* for 6:45:00 PM.
|
|
2845
|
+
* @param {boolean} isSunrise true if the time is sunrise, and false if it is sunset
|
|
2846
|
+
* @return {Temporal.ZonedDateTime | null} The Date.
|
|
2847
|
+
*/
|
|
2848
|
+
getDateFromTime(time, isSunrise) {
|
|
2849
|
+
if (isNaN(time)) {
|
|
2850
|
+
return null;
|
|
2851
|
+
}
|
|
2852
|
+
let calculatedTime = time;
|
|
2853
|
+
let cal = this.getAdjustedDate();
|
|
2854
|
+
// let cal = new Temporal.PlainDate(adj.year, adj.month, adj.day);
|
|
2855
|
+
const hours = Math.trunc(calculatedTime); // retain only the hours
|
|
2856
|
+
calculatedTime -= hours;
|
|
2857
|
+
const minutes = Math.trunc((calculatedTime *= 60)); // retain only the minutes
|
|
2858
|
+
calculatedTime -= minutes;
|
|
2859
|
+
const seconds = Math.trunc((calculatedTime *= 60)); // retain only the seconds
|
|
2860
|
+
calculatedTime -= seconds; // remaining milliseconds
|
|
2861
|
+
// Check if a date transition has occurred, or is about to occur - this indicates the date of the event is
|
|
2862
|
+
// actually not the target date, but the day prior or after
|
|
2863
|
+
const localTimeHours = Math.trunc(this.geoLocation.getLongitude() / 15);
|
|
2864
|
+
if (isSunrise && localTimeHours + hours > 18) {
|
|
2865
|
+
cal = cal.add({ days: -1 });
|
|
2866
|
+
// cal = cal.minus({days: 1});
|
|
2867
|
+
}
|
|
2868
|
+
else if (!isSunrise && localTimeHours + hours < 6) {
|
|
2869
|
+
cal = cal.add({ days: 1 });
|
|
2870
|
+
}
|
|
2871
|
+
return cal
|
|
2872
|
+
.toZonedDateTime({
|
|
2873
|
+
timeZone: 'UTC',
|
|
2874
|
+
plainTime: new Temporal.PlainTime(hours, minutes, seconds, Math.trunc(calculatedTime * 1000)),
|
|
2875
|
+
})
|
|
2876
|
+
.withTimeZone(this.geoLocation.getTimeZone());
|
|
2877
|
+
}
|
|
2878
|
+
/**
|
|
2879
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> from a Java Calendar
|
|
2880
|
+
* @private
|
|
2881
|
+
* @param {Temporal.ZonedDateTime} date
|
|
2882
|
+
* The Java Calendar
|
|
2883
|
+
* @return the Julian day corresponding to the date Note: Number is returned for start of day. Fractional days
|
|
2884
|
+
* should be added later.
|
|
2885
|
+
*/
|
|
2886
|
+
static getJulianDay(date) {
|
|
2887
|
+
let { year, month } = date;
|
|
2888
|
+
const { day } = date;
|
|
2889
|
+
if (month <= 2) {
|
|
2890
|
+
year -= 1;
|
|
2891
|
+
month += 12;
|
|
2892
|
+
}
|
|
2893
|
+
const a = Math.trunc(year / 100);
|
|
2894
|
+
const b = Math.trunc(2 - a + a / 4);
|
|
2895
|
+
return (Math.floor(365.25 * (year + 4716)) +
|
|
2896
|
+
Math.floor(30.6001 * (month + 1)) +
|
|
2897
|
+
day +
|
|
2898
|
+
b -
|
|
2899
|
+
1524.5);
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Convert <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> to centuries since J2000.0.
|
|
2903
|
+
* @private
|
|
2904
|
+
* @param julianDay
|
|
2905
|
+
* the Julian Day to convert
|
|
2906
|
+
* @return the centuries since 2000 Julian corresponding to the Julian Day
|
|
2907
|
+
*/
|
|
2908
|
+
static getJulianCenturiesFromJulianDay(julianDay) {
|
|
2909
|
+
return ((julianDay - NOAACalculator.JULIAN_DAY_JAN_1_2000) /
|
|
2910
|
+
NOAACalculator.JULIAN_DAYS_PER_CENTURY);
|
|
2911
|
+
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Convert centuries since J2000.0 to <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a>.
|
|
2914
|
+
* @private
|
|
2915
|
+
* @param julianCenturies
|
|
2916
|
+
* the number of Julian centuries since J2000.0
|
|
2917
|
+
* @return the Julian Day corresponding to the Julian centuries passed in
|
|
2918
|
+
*/
|
|
2919
|
+
static getJulianDayFromJulianCenturies(julianCenturies) {
|
|
2920
|
+
return (julianCenturies * NOAACalculator.JULIAN_DAYS_PER_CENTURY +
|
|
2921
|
+
NOAACalculator.JULIAN_DAY_JAN_1_2000);
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_longitude">Mean Longitude</a> of the Sun.
|
|
2925
|
+
* @private
|
|
2926
|
+
* @param julianCenturies
|
|
2927
|
+
* the number of Julian centuries since J2000.0
|
|
2928
|
+
* @return the Geometric Mean Longitude of the Sun in degrees
|
|
2929
|
+
*/
|
|
2930
|
+
static getSunGeometricMeanLongitude(julianCenturies) {
|
|
2931
|
+
let longitude = 280.46646 + julianCenturies * (36000.76983 + 0.0003032 * julianCenturies);
|
|
2932
|
+
while (longitude > 360) {
|
|
2933
|
+
longitude -= 360;
|
|
2934
|
+
}
|
|
2935
|
+
while (longitude < 0) {
|
|
2936
|
+
longitude += 360;
|
|
2937
|
+
}
|
|
2938
|
+
return longitude; // in degrees
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_anomaly">Mean Anomaly</a> of the Sun.
|
|
2942
|
+
* @private
|
|
2943
|
+
* @param julianCenturies
|
|
2944
|
+
* the number of Julian centuries since J2000.0
|
|
2945
|
+
* @return the Geometric Mean Anomaly of the Sun in degrees
|
|
2946
|
+
*/
|
|
2947
|
+
static getSunGeometricMeanAnomaly(julianCenturies) {
|
|
2948
|
+
return (357.52911 + julianCenturies * (35999.05029 - 0.0001537 * julianCenturies)); // in degrees
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Eccentricity_%28orbit%29">eccentricity of earth's orbit</a>.
|
|
2952
|
+
* @private
|
|
2953
|
+
* @param julianCenturies
|
|
2954
|
+
* the number of Julian centuries since J2000.0
|
|
2955
|
+
* @return the unitless eccentricity
|
|
2956
|
+
*/
|
|
2957
|
+
static getEarthOrbitEccentricity(julianCenturies) {
|
|
2958
|
+
return (0.016708634 -
|
|
2959
|
+
julianCenturies * (0.000042037 + 0.0000001267 * julianCenturies)); // unitless
|
|
2960
|
+
}
|
|
2961
|
+
/**
|
|
2962
|
+
* Returns the <a href="http://en.wikipedia.org/wiki/Equation_of_the_center">equation of center</a> for the sun.
|
|
2963
|
+
* @private
|
|
2964
|
+
* @param julianCenturies
|
|
2965
|
+
* the number of Julian centuries since J2000.0
|
|
2966
|
+
* @return the equation of center for the sun in degrees
|
|
2967
|
+
*/
|
|
2968
|
+
static getSunEquationOfCenter(julianCenturies) {
|
|
2969
|
+
const m = NOAACalculator.getSunGeometricMeanAnomaly(julianCenturies);
|
|
2970
|
+
const mrad = degreesToRadians(m);
|
|
2971
|
+
const sinm = Math.sin(mrad);
|
|
2972
|
+
const sin2m = Math.sin(mrad + mrad);
|
|
2973
|
+
const sin3m = Math.sin(mrad + mrad + mrad);
|
|
2974
|
+
return (sinm *
|
|
2975
|
+
(1.914602 - julianCenturies * (0.004817 + 0.000014 * julianCenturies)) +
|
|
2976
|
+
sin2m * (0.019993 - 0.000101 * julianCenturies) +
|
|
2977
|
+
sin3m * 0.000289); // in degrees
|
|
2978
|
+
}
|
|
2979
|
+
/**
|
|
2980
|
+
* Return the true longitude of the sun
|
|
2981
|
+
* @private
|
|
2982
|
+
* @param julianCenturies
|
|
2983
|
+
* the number of Julian centuries since J2000.0
|
|
2984
|
+
* @return the sun's true longitude in degrees
|
|
2985
|
+
*/
|
|
2986
|
+
static getSunTrueLongitude(julianCenturies) {
|
|
2987
|
+
const sunLongitude = NOAACalculator.getSunGeometricMeanLongitude(julianCenturies);
|
|
2988
|
+
const center = NOAACalculator.getSunEquationOfCenter(julianCenturies);
|
|
2989
|
+
return sunLongitude + center; // in degrees
|
|
2990
|
+
}
|
|
2991
|
+
/**
|
|
2992
|
+
* Return the apparent longitude of the sun
|
|
2993
|
+
* @private
|
|
2994
|
+
* @param julianCenturies
|
|
2995
|
+
* the number of Julian centuries since J2000.0
|
|
2996
|
+
* @return sun's apparent longitude in degrees
|
|
2997
|
+
*/
|
|
2998
|
+
static getSunApparentLongitude(julianCenturies) {
|
|
2999
|
+
const sunTrueLongitude = NOAACalculator.getSunTrueLongitude(julianCenturies);
|
|
3000
|
+
const omega = 125.04 - 1934.136 * julianCenturies;
|
|
3001
|
+
const lambda = sunTrueLongitude - 0.00569 - 0.00478 * Math.sin(degreesToRadians(omega));
|
|
3002
|
+
return lambda; // in degrees
|
|
3003
|
+
}
|
|
3004
|
+
/**
|
|
3005
|
+
* Returns the mean <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial tilt).
|
|
3006
|
+
* @private
|
|
3007
|
+
* @param julianCenturies
|
|
3008
|
+
* the number of Julian centuries since J2000.0
|
|
3009
|
+
* @return the mean obliquity in degrees
|
|
3010
|
+
*/
|
|
3011
|
+
static getMeanObliquityOfEcliptic(julianCenturies) {
|
|
3012
|
+
const seconds = 21.448 -
|
|
3013
|
+
julianCenturies *
|
|
3014
|
+
(46.815 + julianCenturies * (0.00059 - julianCenturies * 0.001813));
|
|
3015
|
+
return 23 + (26 + seconds / 60) / 60; // in degrees
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Returns the corrected <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial
|
|
3019
|
+
* tilt).
|
|
3020
|
+
* @private
|
|
3021
|
+
* @param julianCenturies
|
|
3022
|
+
* the number of Julian centuries since J2000.0
|
|
3023
|
+
* @return the corrected obliquity in degrees
|
|
3024
|
+
*/
|
|
3025
|
+
static getObliquityCorrection(julianCenturies) {
|
|
3026
|
+
const obliquityOfEcliptic = NOAACalculator.getMeanObliquityOfEcliptic(julianCenturies);
|
|
3027
|
+
const omega = 125.04 - 1934.136 * julianCenturies;
|
|
3028
|
+
return obliquityOfEcliptic + 0.00256 * Math.cos(degreesToRadians(omega)); // in degrees
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Declination">declination</a> of the sun.
|
|
3032
|
+
* @private
|
|
3033
|
+
* @param julianCenturies
|
|
3034
|
+
* the number of Julian centuries since J2000.0
|
|
3035
|
+
* @return
|
|
3036
|
+
* the sun's declination in degrees
|
|
3037
|
+
*/
|
|
3038
|
+
static getSunDeclination(julianCenturies) {
|
|
3039
|
+
const obliquityCorrection = NOAACalculator.getObliquityCorrection(julianCenturies);
|
|
3040
|
+
const lambda = NOAACalculator.getSunApparentLongitude(julianCenturies);
|
|
3041
|
+
const sint = Math.sin(degreesToRadians(obliquityCorrection)) *
|
|
3042
|
+
Math.sin(degreesToRadians(lambda));
|
|
3043
|
+
const theta = radiansToDegrees(Math.asin(sint));
|
|
3044
|
+
return theta; // in degrees
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Equation_of_time">Equation of Time</a> - the difference between
|
|
3048
|
+
* true solar time and mean solar time
|
|
3049
|
+
* @private
|
|
3050
|
+
* @param julianCenturies
|
|
3051
|
+
* the number of Julian centuries since J2000.0
|
|
3052
|
+
* @return equation of time in minutes of time
|
|
3053
|
+
*/
|
|
3054
|
+
static getEquationOfTime(julianCenturies) {
|
|
3055
|
+
const epsilon = NOAACalculator.getObliquityCorrection(julianCenturies);
|
|
3056
|
+
const geomMeanLongSun = NOAACalculator.getSunGeometricMeanLongitude(julianCenturies);
|
|
3057
|
+
const eccentricityEarthOrbit = NOAACalculator.getEarthOrbitEccentricity(julianCenturies);
|
|
3058
|
+
const geomMeanAnomalySun = NOAACalculator.getSunGeometricMeanAnomaly(julianCenturies);
|
|
3059
|
+
let y = Math.tan(degreesToRadians(epsilon) / 2);
|
|
3060
|
+
y *= y;
|
|
3061
|
+
const sin2l0 = Math.sin(2 * degreesToRadians(geomMeanLongSun));
|
|
3062
|
+
const sinm = Math.sin(degreesToRadians(geomMeanAnomalySun));
|
|
3063
|
+
const cos2l0 = Math.cos(2 * degreesToRadians(geomMeanLongSun));
|
|
3064
|
+
const sin4l0 = Math.sin(4 * degreesToRadians(geomMeanLongSun));
|
|
3065
|
+
const sin2m = Math.sin(2 * degreesToRadians(geomMeanAnomalySun));
|
|
3066
|
+
const equationOfTime = y * sin2l0 -
|
|
3067
|
+
2 * eccentricityEarthOrbit * sinm +
|
|
3068
|
+
4 * eccentricityEarthOrbit * y * sinm * cos2l0 -
|
|
3069
|
+
0.5 * y * y * sin4l0 -
|
|
3070
|
+
1.25 * eccentricityEarthOrbit * eccentricityEarthOrbit * sin2m;
|
|
3071
|
+
return radiansToDegrees(equationOfTime) * 4; // in minutes of time
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunrise for the
|
|
3075
|
+
* latitude.
|
|
3076
|
+
* @private
|
|
3077
|
+
* @param {number} lat
|
|
3078
|
+
* , the latitude of observer in degrees
|
|
3079
|
+
* @param solarDec
|
|
3080
|
+
* the declination angle of sun in degrees
|
|
3081
|
+
* @param {number} zenith
|
|
3082
|
+
* the zenith
|
|
3083
|
+
* @return hour angle of sunrise in radians
|
|
3084
|
+
*/
|
|
3085
|
+
static getSunHourAngleAtSunrise(lat, solarDec, zenith) {
|
|
3086
|
+
const latRad = degreesToRadians(lat);
|
|
3087
|
+
const sdRad = degreesToRadians(solarDec);
|
|
3088
|
+
return Math.acos(Math.cos(degreesToRadians(zenith)) /
|
|
3089
|
+
(Math.cos(latRad) * Math.cos(sdRad)) -
|
|
3090
|
+
Math.tan(latRad) * Math.tan(sdRad)); // in radians
|
|
3091
|
+
}
|
|
3092
|
+
/**
|
|
3093
|
+
* Returns the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunset for the
|
|
3094
|
+
* latitude.
|
|
3095
|
+
* @private
|
|
3096
|
+
* @param {number} lat
|
|
3097
|
+
* the latitude of observer in degrees
|
|
3098
|
+
* @param solarDec
|
|
3099
|
+
* the declination angle of sun in degrees
|
|
3100
|
+
* @param {number} zenith
|
|
3101
|
+
* the zenith
|
|
3102
|
+
* @return the hour angle of sunset in radians
|
|
3103
|
+
*/
|
|
3104
|
+
static getSunHourAngleAtSunset(lat, solarDec, zenith) {
|
|
3105
|
+
const latRad = degreesToRadians(lat);
|
|
3106
|
+
const sdRad = degreesToRadians(solarDec);
|
|
3107
|
+
const hourAngle = Math.acos(Math.cos(degreesToRadians(zenith)) /
|
|
3108
|
+
(Math.cos(latRad) * Math.cos(sdRad)) -
|
|
3109
|
+
Math.tan(latRad) * Math.tan(sdRad));
|
|
3110
|
+
return -hourAngle; // in radians
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Elevation</a> for the
|
|
3114
|
+
* horizontal coordinate system at the given location at the given time. Can be negative if the sun is below the
|
|
3115
|
+
* horizon. Not corrected for altitude.
|
|
3116
|
+
*
|
|
3117
|
+
* @param {Temporal.ZonedDateTime} date
|
|
3118
|
+
* time of calculation
|
|
3119
|
+
* @param {number} lat
|
|
3120
|
+
* latitude of location for calculation
|
|
3121
|
+
* @param {number} lon
|
|
3122
|
+
* longitude of location for calculation
|
|
3123
|
+
* @return {number} solar elevation in degrees - horizon is 0 degrees, civil twilight is -6 degrees
|
|
3124
|
+
*/
|
|
3125
|
+
static getSolarElevation(date, lat, lon) {
|
|
3126
|
+
const julianDay = NOAACalculator.getJulianDay(date.toPlainDate());
|
|
3127
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3128
|
+
const equationOfTime = NOAACalculator.getEquationOfTime(julianCenturies);
|
|
3129
|
+
let longitude = date.hour + 12 + (date.minute + equationOfTime + date.second / 60) / 60;
|
|
3130
|
+
longitude = -((longitude * 360) / 24) % 360;
|
|
3131
|
+
const hourAngleRad = degreesToRadians(lon - longitude);
|
|
3132
|
+
const declination = NOAACalculator.getSunDeclination(julianCenturies);
|
|
3133
|
+
const decRad = degreesToRadians(declination);
|
|
3134
|
+
const latRad = degreesToRadians(lat);
|
|
3135
|
+
return radiansToDegrees(Math.asin(Math.sin(latRad) * Math.sin(decRad) +
|
|
3136
|
+
Math.cos(latRad) * Math.cos(decRad) * Math.cos(hourAngleRad)));
|
|
3137
|
+
}
|
|
3138
|
+
/**
|
|
3139
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Azimuth</a> for the
|
|
3140
|
+
* horizontal coordinate system at the given location at the given time. Not corrected for altitude. True south is 0
|
|
3141
|
+
* degrees.
|
|
3142
|
+
*
|
|
3143
|
+
* @param {Temporal.ZonedDateTime} date
|
|
3144
|
+
* time of calculation
|
|
3145
|
+
* @param {number} latitude
|
|
3146
|
+
* latitude of location for calculation
|
|
3147
|
+
* @param {number} lon
|
|
3148
|
+
* longitude of location for calculation
|
|
3149
|
+
* @return {number}
|
|
3150
|
+
*/
|
|
3151
|
+
static getSolarAzimuth(date, latitude, lon) {
|
|
3152
|
+
const julianDay = NOAACalculator.getJulianDay(date.toPlainDate());
|
|
3153
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3154
|
+
const equationOfTime = NOAACalculator.getEquationOfTime(julianCenturies);
|
|
3155
|
+
let longitude = date.hour + 12 + (date.minute + equationOfTime + date.second / 60) / 60;
|
|
3156
|
+
longitude = -((longitude * 360) / 24) % 360;
|
|
3157
|
+
const hourAngleRad = degreesToRadians(lon - longitude);
|
|
3158
|
+
const declination = NOAACalculator.getSunDeclination(julianCenturies);
|
|
3159
|
+
const decRad = degreesToRadians(declination);
|
|
3160
|
+
const latRad = degreesToRadians(latitude);
|
|
3161
|
+
return (radiansToDegrees(Math.atan(Math.sin(hourAngleRad) /
|
|
3162
|
+
(Math.cos(hourAngleRad) * Math.sin(latRad) -
|
|
3163
|
+
Math.tan(decRad) * Math.cos(latRad)))) + 180);
|
|
3164
|
+
}
|
|
3165
|
+
/**
|
|
3166
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3167
|
+
* of sunrise for the given day at the given location on earth
|
|
3168
|
+
* @private
|
|
3169
|
+
* @param julianDay
|
|
3170
|
+
* the Julian day
|
|
3171
|
+
* @param {number} latitude
|
|
3172
|
+
* the latitude of observer in degrees
|
|
3173
|
+
* @param {number} longitude
|
|
3174
|
+
* the longitude of observer in degrees
|
|
3175
|
+
* @param {number} zenith
|
|
3176
|
+
* the zenith
|
|
3177
|
+
* @return the time in minutes from zero UTC
|
|
3178
|
+
*/
|
|
3179
|
+
static getSunriseUTC(julianDay, latitude, longitude, zenith) {
|
|
3180
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3181
|
+
// Find the time of solar noon at the location, and use that declination. This is better than start of the
|
|
3182
|
+
// Julian day
|
|
3183
|
+
const noonmin = NOAACalculator.getSolarNoonUTC(julianCenturies, longitude);
|
|
3184
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay + noonmin / 1440);
|
|
3185
|
+
// First pass to approximate sunrise (using solar noon)
|
|
3186
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3187
|
+
let solarDec = NOAACalculator.getSunDeclination(tnoon);
|
|
3188
|
+
let hourAngle = NOAACalculator.getSunHourAngleAtSunrise(latitude, solarDec, zenith);
|
|
3189
|
+
let delta = longitude - radiansToDegrees(hourAngle);
|
|
3190
|
+
let timeDiff = 4 * delta; // in minutes of time
|
|
3191
|
+
let timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3192
|
+
// Second pass includes fractional Julian Day in gamma calc
|
|
3193
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3194
|
+
timeUTC / 1440);
|
|
3195
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3196
|
+
solarDec = NOAACalculator.getSunDeclination(newt);
|
|
3197
|
+
hourAngle = NOAACalculator.getSunHourAngleAtSunrise(latitude, solarDec, zenith);
|
|
3198
|
+
delta = longitude - radiansToDegrees(hourAngle);
|
|
3199
|
+
timeDiff = 4 * delta;
|
|
3200
|
+
timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3201
|
+
return timeUTC;
|
|
3202
|
+
}
|
|
3203
|
+
/**
|
|
3204
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3205
|
+
* of <a href="http://en.wikipedia.org/wiki/Noon#Solar_noon">solar noon</a> for the given day at the given location
|
|
3206
|
+
* on earth.
|
|
3207
|
+
* @private
|
|
3208
|
+
* @param julianCenturies
|
|
3209
|
+
* the number of Julian centuries since J2000.0
|
|
3210
|
+
* @param {number} longitude
|
|
3211
|
+
* the longitude of observer in degrees
|
|
3212
|
+
* @return the time in minutes from zero UTC
|
|
3213
|
+
*/
|
|
3214
|
+
static getSolarNoonUTC(julianCenturies, longitude) {
|
|
3215
|
+
// First pass uses approximate solar noon to calculate eqtime
|
|
3216
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3217
|
+
longitude / 360);
|
|
3218
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3219
|
+
const solNoonUTC = 720 + longitude * 4 - eqTime; // min
|
|
3220
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) -
|
|
3221
|
+
0.5 +
|
|
3222
|
+
solNoonUTC / 1440);
|
|
3223
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3224
|
+
return 720 + longitude * 4 - eqTime; // min
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3228
|
+
* of sunset for the given day at the given location on earth
|
|
3229
|
+
* @private
|
|
3230
|
+
* @param julianDay
|
|
3231
|
+
* the Julian day
|
|
3232
|
+
* @param {number} latitude
|
|
3233
|
+
* the latitude of observer in degrees
|
|
3234
|
+
* @param {number} longitude
|
|
3235
|
+
* : longitude of observer in degrees
|
|
3236
|
+
* @param {number} zenith
|
|
3237
|
+
* the zenith
|
|
3238
|
+
* @return the time in minutes from zero Universal Coordinated Time (UTC)
|
|
3239
|
+
*/
|
|
3240
|
+
static getSunsetUTC(julianDay, latitude, longitude, zenith) {
|
|
3241
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3242
|
+
// Find the time of solar noon at the location, and use that declination. This is better than start of the
|
|
3243
|
+
// Julian day
|
|
3244
|
+
const noonmin = NOAACalculator.getSolarNoonUTC(julianCenturies, longitude);
|
|
3245
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay + noonmin / 1440);
|
|
3246
|
+
// First calculates sunrise and approx length of day
|
|
3247
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3248
|
+
let solarDec = NOAACalculator.getSunDeclination(tnoon);
|
|
3249
|
+
let hourAngle = NOAACalculator.getSunHourAngleAtSunset(latitude, solarDec, zenith);
|
|
3250
|
+
let delta = longitude - radiansToDegrees(hourAngle);
|
|
3251
|
+
let timeDiff = 4 * delta;
|
|
3252
|
+
let timeUTC = 720 + timeDiff - eqTime;
|
|
3253
|
+
// Second pass includes fractional Julian Day in gamma calc
|
|
3254
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3255
|
+
timeUTC / 1440);
|
|
3256
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3257
|
+
solarDec = NOAACalculator.getSunDeclination(newt);
|
|
3258
|
+
hourAngle = NOAACalculator.getSunHourAngleAtSunset(latitude, solarDec, zenith);
|
|
3259
|
+
delta = longitude - radiansToDegrees(hourAngle);
|
|
3260
|
+
timeDiff = 4 * delta;
|
|
3261
|
+
timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3262
|
+
return timeUTC;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
/**
|
|
3266
|
+
* The zenith of astronomical sunrise and sunset. The sun is 90° from the vertical 0°
|
|
3267
|
+
* @private
|
|
3268
|
+
*/
|
|
3269
|
+
NOAACalculator.GEOMETRIC_ZENITH = 90;
|
|
3270
|
+
/**
|
|
3271
|
+
* Default value for Sun's zenith and true rise/set Zenith (used in this class and subclasses) is the angle that the
|
|
3272
|
+
* center of the Sun makes to a line perpendicular to the Earth's surface. If the Sun were a point and the Earth
|
|
3273
|
+
* were without an atmosphere, true sunset and sunrise would correspond to a 90° zenith. Because the Sun is not
|
|
3274
|
+
* a point, and because the atmosphere refracts light, this 90° zenith does not, in fact, correspond to true
|
|
3275
|
+
* sunset or sunrise, instead the center of the Sun's disk must lie just below the horizon for the upper edge to be
|
|
3276
|
+
* obscured. This means that a zenith of just above 90° must be used. The Sun subtends an angle of 16 minutes of
|
|
3277
|
+
* arc, and atmospheric refraction accounts for
|
|
3278
|
+
* 34 minutes or so, giving a total of 50
|
|
3279
|
+
* arcminutes. The total value for ZENITH is 90+(5/6) or 90.8333333° for true sunrise/sunset.
|
|
3280
|
+
*/
|
|
3281
|
+
// const ZENITH: number = GEOMETRIC_ZENITH + 5.0 / 6.0;
|
|
3282
|
+
/** Sun's zenith at civil twilight (96°). */
|
|
3283
|
+
NOAACalculator.CIVIL_ZENITH = 96;
|
|
3284
|
+
/** Sun's zenith at nautical twilight (102°). */
|
|
3285
|
+
NOAACalculator.NAUTICAL_ZENITH = 102;
|
|
3286
|
+
/** Sun's zenith at astronomical twilight (108°). */
|
|
3287
|
+
NOAACalculator.ASTRONOMICAL_ZENITH = 108;
|
|
3288
|
+
/**
|
|
3289
|
+
* The <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> of January 1, 2000
|
|
3290
|
+
* @private
|
|
3291
|
+
*/
|
|
3292
|
+
NOAACalculator.JULIAN_DAY_JAN_1_2000 = 2451545;
|
|
3293
|
+
/**
|
|
3294
|
+
* Julian days per century
|
|
3295
|
+
* @private
|
|
3296
|
+
*/
|
|
3297
|
+
NOAACalculator.JULIAN_DAYS_PER_CENTURY = 36525;
|
|
3298
|
+
|
|
337
3299
|
/*
|
|
338
3300
|
Hebcal - A Jewish Calendar Generator
|
|
339
3301
|
Copyright (c) 1994-2020 Danny Sadinoff
|
|
@@ -466,7 +3428,7 @@ function getFormatter(tzid) {
|
|
|
466
3428
|
return f;
|
|
467
3429
|
}
|
|
468
3430
|
/** Class representing Location */
|
|
469
|
-
class Location extends
|
|
3431
|
+
class Location extends GeoLocation {
|
|
470
3432
|
/**
|
|
471
3433
|
* Initialize a Location instance
|
|
472
3434
|
* @param latitude - Latitude as a decimal, valid range -90 thru +90 (e.g. 41.85003)
|
|
@@ -650,9 +3612,9 @@ function zdtToDate(zdt) {
|
|
|
650
3612
|
return res;
|
|
651
3613
|
}
|
|
652
3614
|
function getDate(date) {
|
|
653
|
-
if (
|
|
3615
|
+
if (isDate(date))
|
|
654
3616
|
return date;
|
|
655
|
-
if (
|
|
3617
|
+
if (HDate.isHDate(date))
|
|
656
3618
|
return date.greg();
|
|
657
3619
|
throw new TypeError(`invalid date: ${date}`);
|
|
658
3620
|
}
|
|
@@ -703,7 +3665,7 @@ class Zmanim {
|
|
|
703
3665
|
month: dt.getMonth() + 1,
|
|
704
3666
|
day: dt.getDate(),
|
|
705
3667
|
});
|
|
706
|
-
this.noaa = new
|
|
3668
|
+
this.noaa = new NOAACalculator(gloc, plainDate);
|
|
707
3669
|
this.useElevation = Boolean(useElevation);
|
|
708
3670
|
}
|
|
709
3671
|
/**
|
|
@@ -858,7 +3820,7 @@ class Zmanim {
|
|
|
858
3820
|
: this.noaa.getSeaLevelSunset();
|
|
859
3821
|
const temporalHour = this.noaa.getTemporalHour(startOfDay, endOfDay);
|
|
860
3822
|
const offset = Math.round(temporalHour * hours);
|
|
861
|
-
const zdt =
|
|
3823
|
+
const zdt = NOAACalculator.getTimeOffset(startOfDay, offset);
|
|
862
3824
|
return zdtToDate(zdt);
|
|
863
3825
|
}
|
|
864
3826
|
/**
|
|
@@ -1106,11 +4068,11 @@ class Zmanim {
|
|
|
1106
4068
|
* @param date
|
|
1107
4069
|
*/
|
|
1108
4070
|
static timeZoneOffset(tzid, date) {
|
|
1109
|
-
const offset =
|
|
4071
|
+
const offset = getTimezoneOffset(tzid, date);
|
|
1110
4072
|
const offsetAbs = Math.abs(offset);
|
|
1111
4073
|
const hours = Math.floor(offsetAbs / 60);
|
|
1112
4074
|
const minutes = offsetAbs % 60;
|
|
1113
|
-
return (offset < 0 ? '+' : '-') +
|
|
4075
|
+
return (offset < 0 ? '+' : '-') + pad2(hours) + ':' + pad2(minutes);
|
|
1114
4076
|
}
|
|
1115
4077
|
/**
|
|
1116
4078
|
* Returns a string like "2022-04-01T13:06:00-11:00"
|
|
@@ -1121,7 +4083,7 @@ class Zmanim {
|
|
|
1121
4083
|
if (isNaN(date.getTime())) {
|
|
1122
4084
|
return '0000-00-00T00:00:00Z';
|
|
1123
4085
|
}
|
|
1124
|
-
return (
|
|
4086
|
+
return (getPseudoISO(tzid, date).substring(0, 19) +
|
|
1125
4087
|
Zmanim.timeZoneOffset(tzid, date));
|
|
1126
4088
|
}
|
|
1127
4089
|
/**
|
|
@@ -1192,7 +4154,7 @@ class Zmanim {
|
|
|
1192
4154
|
static makeSunsetAwareHDate(gloc, date, useElevation) {
|
|
1193
4155
|
const zmanim = new Zmanim(gloc, date, useElevation);
|
|
1194
4156
|
const sunset = zmanim.sunset();
|
|
1195
|
-
let hd = new
|
|
4157
|
+
let hd = new HDate(date);
|
|
1196
4158
|
const sunsetMillis = sunset.getTime();
|
|
1197
4159
|
if (isNaN(sunsetMillis)) {
|
|
1198
4160
|
return hd;
|
|
@@ -1274,14 +4236,14 @@ class TimedEvent extends Event {
|
|
|
1274
4236
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
1275
4237
|
*/
|
|
1276
4238
|
render(locale) {
|
|
1277
|
-
return
|
|
4239
|
+
return Locale.gettext(this.getDesc(), locale) + ': ' + this.fmtTime;
|
|
1278
4240
|
}
|
|
1279
4241
|
/**
|
|
1280
4242
|
* Returns translation of "Candle lighting" without the time.
|
|
1281
4243
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
1282
4244
|
*/
|
|
1283
4245
|
renderBrief(locale) {
|
|
1284
|
-
return
|
|
4246
|
+
return Locale.gettext(this.getDesc(), locale);
|
|
1285
4247
|
}
|
|
1286
4248
|
getCategories() {
|
|
1287
4249
|
const desc = this.getDesc();
|
|
@@ -1329,9 +4291,9 @@ class HavdalahEvent extends TimedEvent {
|
|
|
1329
4291
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
1330
4292
|
*/
|
|
1331
4293
|
renderBrief(locale) {
|
|
1332
|
-
let str =
|
|
4294
|
+
let str = Locale.gettext(this.getDesc(), locale);
|
|
1333
4295
|
if (this.havdalahMins) {
|
|
1334
|
-
const min =
|
|
4296
|
+
const min = Locale.gettext('min', locale);
|
|
1335
4297
|
str += ` (${this.havdalahMins} ${min})`;
|
|
1336
4298
|
}
|
|
1337
4299
|
return str;
|
|
@@ -1341,17 +4303,17 @@ class HavdalahEvent extends TimedEvent {
|
|
|
1341
4303
|
}
|
|
1342
4304
|
}
|
|
1343
4305
|
|
|
1344
|
-
const Nisan =
|
|
1345
|
-
const Iyyar =
|
|
1346
|
-
const Sivan =
|
|
1347
|
-
const Tamuz =
|
|
1348
|
-
const Av =
|
|
1349
|
-
const Elul =
|
|
1350
|
-
const Tishrei =
|
|
1351
|
-
const Cheshvan =
|
|
1352
|
-
const Kislev =
|
|
1353
|
-
const Shvat =
|
|
1354
|
-
const Adar2 =
|
|
4306
|
+
const Nisan = months.NISAN;
|
|
4307
|
+
const Iyyar = months.IYYAR;
|
|
4308
|
+
const Sivan = months.SIVAN;
|
|
4309
|
+
const Tamuz = months.TAMUZ;
|
|
4310
|
+
const Av = months.AV;
|
|
4311
|
+
const Elul = months.ELUL;
|
|
4312
|
+
const Tishrei = months.TISHREI;
|
|
4313
|
+
const Cheshvan = months.CHESHVAN;
|
|
4314
|
+
const Kislev = months.KISLEV;
|
|
4315
|
+
const Shvat = months.SHVAT;
|
|
4316
|
+
const Adar2 = months.ADAR_II;
|
|
1355
4317
|
const CHAG$1 = flags.CHAG;
|
|
1356
4318
|
const LIGHT_CANDLES$2 = flags.LIGHT_CANDLES;
|
|
1357
4319
|
const YOM_TOV_ENDS$1 = flags.YOM_TOV_ENDS;
|
|
@@ -1955,7 +4917,7 @@ const staticModernHolidays = [
|
|
|
1955
4917
|
// https://www.gov.il/he/departments/policies/2012_des5234
|
|
1956
4918
|
{
|
|
1957
4919
|
firstYear: 5773,
|
|
1958
|
-
mm:
|
|
4920
|
+
mm: months.TEVET,
|
|
1959
4921
|
dd: 21,
|
|
1960
4922
|
desc: HEBREW_LANGUAGE_DAY,
|
|
1961
4923
|
friSatMovetoThu: true,
|
|
@@ -2060,7 +5022,7 @@ class HolidayEvent extends Event {
|
|
|
2060
5022
|
*/
|
|
2061
5023
|
class AsaraBTevetEvent extends HolidayEvent {
|
|
2062
5024
|
urlDateSuffix() {
|
|
2063
|
-
const isoDate =
|
|
5025
|
+
const isoDate = isoDateString(this.getDate().greg());
|
|
2064
5026
|
return isoDate.replace(/-/g, '');
|
|
2065
5027
|
}
|
|
2066
5028
|
}
|
|
@@ -2095,7 +5057,7 @@ class RoshHashanaEvent extends HolidayEvent {
|
|
|
2095
5057
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
2096
5058
|
*/
|
|
2097
5059
|
render(locale) {
|
|
2098
|
-
return
|
|
5060
|
+
return Locale.gettext('Rosh Hashana', locale) + ' ' + this.hyear;
|
|
2099
5061
|
}
|
|
2100
5062
|
getEmoji() {
|
|
2101
5063
|
return '🍏🍯';
|
|
@@ -2118,9 +5080,9 @@ class RoshChodeshEvent extends HolidayEvent {
|
|
|
2118
5080
|
*/
|
|
2119
5081
|
render(locale) {
|
|
2120
5082
|
const monthName = this.getDesc().substring(roshChodeshStr.length + 1);
|
|
2121
|
-
const monthName0 =
|
|
5083
|
+
const monthName0 = Locale.gettext(monthName, locale);
|
|
2122
5084
|
const monthName1 = monthName0.replace(/'/g, '’');
|
|
2123
|
-
return
|
|
5085
|
+
return Locale.gettext(roshChodeshStr, locale) + ' ' + monthName1;
|
|
2124
5086
|
}
|
|
2125
5087
|
basename() {
|
|
2126
5088
|
return this.getDesc();
|
|
@@ -2241,7 +5203,7 @@ function makeFastStartEnd(ev, options) {
|
|
|
2241
5203
|
startEvent = makeTimedEvent(ev, dawn, FAST_BEGINS, options);
|
|
2242
5204
|
}
|
|
2243
5205
|
if (dt.getDay() !== 5 &&
|
|
2244
|
-
!(hd.getDate() === 14 && hd.getMonth() ===
|
|
5206
|
+
!(hd.getDate() === 14 && hd.getMonth() === months.NISAN)) {
|
|
2245
5207
|
const tzeit = zmanim.tzeit(fastEndDeg);
|
|
2246
5208
|
if (!isNaN(tzeit.getTime())) {
|
|
2247
5209
|
endEvent = makeTimedEvent(ev, tzeit, FAST_ENDS, options);
|
|
@@ -2324,7 +5286,7 @@ class Molad {
|
|
|
2324
5286
|
* @param month
|
|
2325
5287
|
*/
|
|
2326
5288
|
constructor(year, month) {
|
|
2327
|
-
this.m =
|
|
5289
|
+
this.m = molad(year, month);
|
|
2328
5290
|
}
|
|
2329
5291
|
/**
|
|
2330
5292
|
*/
|
|
@@ -2339,7 +5301,7 @@ class Molad {
|
|
|
2339
5301
|
/**
|
|
2340
5302
|
*/
|
|
2341
5303
|
getMonthName() {
|
|
2342
|
-
return
|
|
5304
|
+
return HDate.getMonthName(this.m.month, this.m.year);
|
|
2343
5305
|
}
|
|
2344
5306
|
/**
|
|
2345
5307
|
* @returns Day of Week (0=Sunday, 6=Saturday)
|
|
@@ -2371,23 +5333,23 @@ class Molad {
|
|
|
2371
5333
|
*/
|
|
2372
5334
|
render(locale, options) {
|
|
2373
5335
|
var _a;
|
|
2374
|
-
locale = locale !== null && locale !== void 0 ? locale :
|
|
5336
|
+
locale = locale !== null && locale !== void 0 ? locale : Locale.getLocaleName();
|
|
2375
5337
|
if (typeof locale === 'string') {
|
|
2376
5338
|
locale = locale.toLowerCase();
|
|
2377
5339
|
}
|
|
2378
5340
|
const isHebrewLocale = locale === 'he' || locale === 'he-x-nonikud' || locale === 'h';
|
|
2379
5341
|
const isFrenchLocale = locale === 'fr';
|
|
2380
|
-
const monthName =
|
|
5342
|
+
const monthName = Locale.gettext(this.getMonthName(), locale);
|
|
2381
5343
|
const dayNames = isHebrewLocale ? heDayNames : (isFrenchLocale ? frDayNames : shortDayNames);
|
|
2382
5344
|
const dow = dayNames[this.getDow()];
|
|
2383
5345
|
const minutes = this.getMinutes();
|
|
2384
5346
|
const hour = this.getHour();
|
|
2385
5347
|
const chalakim = this.getChalakim();
|
|
2386
|
-
const moladStr =
|
|
2387
|
-
const minutesStr = (_a =
|
|
2388
|
-
const chalakimStr =
|
|
2389
|
-
const and =
|
|
2390
|
-
const after =
|
|
5348
|
+
const moladStr = Locale.gettext('Molad', locale);
|
|
5349
|
+
const minutesStr = (_a = Locale.lookupTranslation('min', locale)) !== null && _a !== void 0 ? _a : 'minutes';
|
|
5350
|
+
const chalakimStr = Locale.gettext('chalakim', locale);
|
|
5351
|
+
const and = Locale.gettext('and', locale);
|
|
5352
|
+
const after = Locale.gettext('after', locale);
|
|
2391
5353
|
if (isHebrewLocale) {
|
|
2392
5354
|
const ampm = getHebrewTimeOfDay(hour);
|
|
2393
5355
|
const result = `${moladStr} ${monthName} יִהְיֶה בַּיּוֹם ${dow} בשָׁבוּעַ, ` +
|
|
@@ -2395,7 +5357,7 @@ class Molad {
|
|
|
2395
5357
|
`ו-${minutes} ${minutesStr} ` +
|
|
2396
5358
|
`ו-${chalakim} ${chalakimStr}`;
|
|
2397
5359
|
if (locale === 'he-x-nonikud') {
|
|
2398
|
-
return
|
|
5360
|
+
return Locale.hebrewStripNikkud(result);
|
|
2399
5361
|
}
|
|
2400
5362
|
return result;
|
|
2401
5363
|
}
|
|
@@ -2651,23 +5613,23 @@ class OmerEvent extends Event {
|
|
|
2651
5613
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
2652
5614
|
*/
|
|
2653
5615
|
render(locale) {
|
|
2654
|
-
locale = locale !== null && locale !== void 0 ? locale :
|
|
5616
|
+
locale = locale !== null && locale !== void 0 ? locale : Locale.getLocaleName();
|
|
2655
5617
|
if (typeof locale === 'string') {
|
|
2656
5618
|
locale = locale.toLowerCase();
|
|
2657
5619
|
}
|
|
2658
5620
|
const isHebrewLocale = locale === 'he' || locale === 'he-x-nonikud' || locale === 'h';
|
|
2659
5621
|
const omer = this.omer;
|
|
2660
|
-
const nth = isHebrewLocale ?
|
|
2661
|
-
return nth + ' ' +
|
|
5622
|
+
const nth = isHebrewLocale ? gematriya(omer) : Locale.ordinal(omer, locale);
|
|
5623
|
+
return nth + ' ' + Locale.gettext('day of the Omer', locale);
|
|
2662
5624
|
}
|
|
2663
5625
|
/**
|
|
2664
5626
|
* Returns translation of "Omer day 22" without ordinal numbers.
|
|
2665
5627
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
2666
5628
|
*/
|
|
2667
5629
|
renderBrief(locale) {
|
|
2668
|
-
return (
|
|
5630
|
+
return (Locale.gettext('Omer', locale) +
|
|
2669
5631
|
' ' +
|
|
2670
|
-
|
|
5632
|
+
Locale.gettext('day', locale) +
|
|
2671
5633
|
' ' +
|
|
2672
5634
|
this.omer);
|
|
2673
5635
|
}
|
|
@@ -2708,14 +5670,14 @@ class OmerEvent extends Event {
|
|
|
2708
5670
|
* or `הַיוֹם עֲשָׂרָה יָמִים, שְׁהֵם שָׁבוּעַ אֶחָד וְשְׁלוֹשָׁה יָמִים לָעוֹמֶר`
|
|
2709
5671
|
*/
|
|
2710
5672
|
getTodayIs(locale) {
|
|
2711
|
-
locale = locale !== null && locale !== void 0 ? locale :
|
|
5673
|
+
locale = locale !== null && locale !== void 0 ? locale : Locale.getLocaleName();
|
|
2712
5674
|
if (typeof locale === 'string') {
|
|
2713
5675
|
locale = locale.toLowerCase();
|
|
2714
5676
|
}
|
|
2715
5677
|
const isHebrew = locale === 'he' || locale === 'he-x-nonikud';
|
|
2716
5678
|
const str = isHebrew ? omerTodayIsHe(this.omer) : omerTodayIsEn(this.omer);
|
|
2717
5679
|
if (locale === 'he-x-nonikud') {
|
|
2718
|
-
return
|
|
5680
|
+
return Locale.hebrewStripNikkud(str);
|
|
2719
5681
|
}
|
|
2720
5682
|
return str;
|
|
2721
5683
|
}
|
|
@@ -2726,14 +5688,14 @@ class OmerEvent extends Event {
|
|
|
2726
5688
|
|
|
2727
5689
|
/** @private */
|
|
2728
5690
|
function renderParshaName(parsha, locale) {
|
|
2729
|
-
const locale0 = locale !== null && locale !== void 0 ? locale :
|
|
2730
|
-
let name =
|
|
5691
|
+
const locale0 = locale !== null && locale !== void 0 ? locale : Locale.getLocaleName();
|
|
5692
|
+
let name = Locale.gettext(parsha[0], locale0);
|
|
2731
5693
|
if (parsha.length === 2) {
|
|
2732
5694
|
const hyphen = locale0 === 'he' ? '־' : '-';
|
|
2733
|
-
name += hyphen +
|
|
5695
|
+
name += hyphen + Locale.gettext(parsha[1], locale0);
|
|
2734
5696
|
}
|
|
2735
5697
|
name = name.replace(/'/g, '’');
|
|
2736
|
-
const str =
|
|
5698
|
+
const str = Locale.gettext('Parashat', locale) + ' ' + name;
|
|
2737
5699
|
return str.normalize();
|
|
2738
5700
|
}
|
|
2739
5701
|
|
|
@@ -3056,8 +6018,8 @@ const INCOMPLETE = 0;
|
|
|
3056
6018
|
const REGULAR = 1;
|
|
3057
6019
|
const COMPLETE = 2;
|
|
3058
6020
|
function yearType(hyear) {
|
|
3059
|
-
const longC =
|
|
3060
|
-
const shortK =
|
|
6021
|
+
const longC = HDate.longCheshvan(hyear);
|
|
6022
|
+
const shortK = HDate.shortKislev(hyear);
|
|
3061
6023
|
if (longC && !shortK) {
|
|
3062
6024
|
return COMPLETE;
|
|
3063
6025
|
}
|
|
@@ -3080,21 +6042,23 @@ class Sedra {
|
|
|
3080
6042
|
constructor(hyear, il) {
|
|
3081
6043
|
hyear = +hyear;
|
|
3082
6044
|
this.year = hyear;
|
|
3083
|
-
const rh0 = new
|
|
6045
|
+
const rh0 = new HDate(1, months.TISHREI, hyear);
|
|
3084
6046
|
const rh = rh0.abs();
|
|
3085
6047
|
const rhDay = rh0.getDay() + 1;
|
|
3086
6048
|
// find the first Saturday on or after Rosh Hashana
|
|
3087
|
-
this.firstSaturday =
|
|
3088
|
-
const leap = +
|
|
6049
|
+
this.firstSaturday = HDate.dayOnOrBefore(6, rh + 6);
|
|
6050
|
+
const leap = +HDate.isLeapYear(hyear);
|
|
3089
6051
|
this.il = Boolean(il);
|
|
3090
6052
|
const type = yearType(hyear);
|
|
3091
6053
|
let key = `${leap}${rhDay}${type}`;
|
|
3092
6054
|
if (types[key]) {
|
|
3093
6055
|
this.theSedraArray = types[key];
|
|
6056
|
+
this.yearKey = key;
|
|
3094
6057
|
}
|
|
3095
6058
|
else {
|
|
3096
6059
|
key = key + +this.il; // cast to num, then concat
|
|
3097
6060
|
this.theSedraArray = types[key];
|
|
6061
|
+
this.yearKey = key;
|
|
3098
6062
|
}
|
|
3099
6063
|
if (!this.theSedraArray) {
|
|
3100
6064
|
throw new Error(`improper sedra year type ${key} calculated for ${hyear}`);
|
|
@@ -3186,7 +6150,7 @@ class Sedra {
|
|
|
3186
6150
|
if (idx === -1) {
|
|
3187
6151
|
return null; // doesn't occur this year
|
|
3188
6152
|
}
|
|
3189
|
-
return new
|
|
6153
|
+
return new HDate(this.firstSaturday + idx * 7);
|
|
3190
6154
|
}
|
|
3191
6155
|
/**
|
|
3192
6156
|
* Returns the date that a parsha (or its doubled or undoubled counterpart)
|
|
@@ -3253,32 +6217,32 @@ class Sedra {
|
|
|
3253
6217
|
* @param hd Hebrew date or R.D. days
|
|
3254
6218
|
*/
|
|
3255
6219
|
lookup(hd) {
|
|
3256
|
-
const abs = typeof hd === 'number' ? hd :
|
|
6220
|
+
const abs = typeof hd === 'number' ? hd : HDate.isHDate(hd) ? hd.abs() : NaN;
|
|
3257
6221
|
if (isNaN(abs)) {
|
|
3258
6222
|
throw new TypeError(`Bad date argument: ${hd}`);
|
|
3259
6223
|
}
|
|
3260
6224
|
// find the first saturday on or after today's date
|
|
3261
|
-
const saturday =
|
|
6225
|
+
const saturday = HDate.dayOnOrBefore(6, abs + 6);
|
|
3262
6226
|
const weekNum = (saturday - this.firstSaturday) / 7;
|
|
3263
6227
|
const index = this.theSedraArray[weekNum];
|
|
3264
6228
|
if (typeof index === 'undefined') {
|
|
3265
6229
|
const sedra = getSedra(this.year + 1, this.il);
|
|
3266
6230
|
return sedra.lookup(saturday); // must be next year
|
|
3267
6231
|
}
|
|
3268
|
-
const hdate
|
|
6232
|
+
const hdate = new HDate(saturday);
|
|
3269
6233
|
if (typeof index === 'string') {
|
|
3270
6234
|
// Shabbat has a chag. Return a description
|
|
3271
|
-
return { parsha: [index], chag: true, hdate
|
|
6235
|
+
return { parsha: [index], chag: true, hdate };
|
|
3272
6236
|
}
|
|
3273
6237
|
if (index >= 0) {
|
|
3274
|
-
return { parsha: [parshiot[index]], chag: false, num: index + 1, hdate
|
|
6238
|
+
return { parsha: [parshiot[index]], chag: false, num: index + 1, hdate };
|
|
3275
6239
|
}
|
|
3276
6240
|
const p1 = D(index); // undouble the parsha
|
|
3277
6241
|
return {
|
|
3278
6242
|
parsha: [parshiot[p1], parshiot[p1 + 1]],
|
|
3279
6243
|
chag: false,
|
|
3280
6244
|
num: [p1 + 1, p1 + 2],
|
|
3281
|
-
hdate
|
|
6245
|
+
hdate,
|
|
3282
6246
|
};
|
|
3283
6247
|
}
|
|
3284
6248
|
}
|
|
@@ -3412,11 +6376,11 @@ const types = {
|
|
|
3412
6376
|
/* Hebrew year that starts on Monday, is `incomplete' (Heshvan and
|
|
3413
6377
|
* Kislev each have 29 days), and has Passover start on Tuesday. */
|
|
3414
6378
|
// e.g. 5753
|
|
3415
|
-
'020': yearStartVayeilech.concat(r020, D(21), 23, 24,
|
|
6379
|
+
'020': yearStartVayeilech.concat(r020, D(21), 23, 24, CHMPESACH, 25, D(26), D(28), 30, D(31), r3340, D(41), r4349, D(50)),
|
|
3416
6380
|
/* Hebrew year that starts on Monday, is `complete' (Heshvan and
|
|
3417
6381
|
* Kislev each have 30 days), and has Passover start on Thursday. */
|
|
3418
6382
|
// e.g. 5756
|
|
3419
|
-
'0220': yearStartVayeilech.concat(r020, D(21), 23, 24,
|
|
6383
|
+
'0220': yearStartVayeilech.concat(r020, D(21), 23, 24, CHMPESACH, 25, D(26), D(28), 30, D(31), 33, SHAVUOT, range$1(34, 37), D(38), 40, D(41), r4349, D(50)),
|
|
3420
6384
|
/* Hebrew year that starts on Thursday, is `regular' (Heshvan has 29
|
|
3421
6385
|
* days and Kislev has 30 days), and has Passover start on Saturday. */
|
|
3422
6386
|
// e.g. 5701
|
|
@@ -3547,7 +6511,7 @@ class ParshaEvent extends Event {
|
|
|
3547
6511
|
return this.il ? url + '?i=on' : url;
|
|
3548
6512
|
}
|
|
3549
6513
|
urlDateSuffix() {
|
|
3550
|
-
const isoDate =
|
|
6514
|
+
const isoDate = isoDateString(this.getDate().greg());
|
|
3551
6515
|
return isoDate.replace(/-/g, '');
|
|
3552
6516
|
}
|
|
3553
6517
|
}
|
|
@@ -3562,7 +6526,7 @@ class ParshaEvent extends Event {
|
|
|
3562
6526
|
function parshaYear(year, il) {
|
|
3563
6527
|
const sedra = getSedra(year, il);
|
|
3564
6528
|
const startAbs = sedra.getFirstSaturday();
|
|
3565
|
-
const endAbs =
|
|
6529
|
+
const endAbs = HDate.hebrew2abs(year, months.ELUL, 29);
|
|
3566
6530
|
const events = [];
|
|
3567
6531
|
for (let absDt = startAbs; absDt <= endAbs; absDt += 7) {
|
|
3568
6532
|
const parsha = sedra.lookup(absDt);
|
|
@@ -3578,8 +6542,8 @@ const SUN$1 = 0;
|
|
|
3578
6542
|
const TUE$1 = 2;
|
|
3579
6543
|
const FRI$2 = 5;
|
|
3580
6544
|
const SAT$2 = 6;
|
|
3581
|
-
const NISAN$2 =
|
|
3582
|
-
const IYYAR =
|
|
6545
|
+
const NISAN$2 = months.NISAN;
|
|
6546
|
+
const IYYAR = months.IYYAR;
|
|
3583
6547
|
/**
|
|
3584
6548
|
* Yom HaShoah first observed in 1951.
|
|
3585
6549
|
* When the actual date of Yom Hashoah falls on a Friday, the
|
|
@@ -3594,12 +6558,12 @@ function dateYomHaShoah(year) {
|
|
|
3594
6558
|
if (year < 5711) {
|
|
3595
6559
|
return null;
|
|
3596
6560
|
}
|
|
3597
|
-
let nisan27dt = new
|
|
6561
|
+
let nisan27dt = new HDate(27, NISAN$2, year);
|
|
3598
6562
|
if (nisan27dt.getDay() === FRI$2) {
|
|
3599
|
-
nisan27dt = new
|
|
6563
|
+
nisan27dt = new HDate(26, NISAN$2, year);
|
|
3600
6564
|
}
|
|
3601
6565
|
else if (nisan27dt.getDay() === SUN$1) {
|
|
3602
|
-
nisan27dt = new
|
|
6566
|
+
nisan27dt = new HDate(28, NISAN$2, year);
|
|
3603
6567
|
}
|
|
3604
6568
|
return nisan27dt;
|
|
3605
6569
|
}
|
|
@@ -3613,7 +6577,7 @@ function dateYomHaZikaron(year) {
|
|
|
3613
6577
|
return null;
|
|
3614
6578
|
}
|
|
3615
6579
|
let day;
|
|
3616
|
-
const pesach = new
|
|
6580
|
+
const pesach = new HDate(15, NISAN$2, year);
|
|
3617
6581
|
const pdow = pesach.getDay();
|
|
3618
6582
|
if (pdow === SUN$1) {
|
|
3619
6583
|
day = 2;
|
|
@@ -3630,7 +6594,7 @@ function dateYomHaZikaron(year) {
|
|
|
3630
6594
|
else {
|
|
3631
6595
|
day = 4;
|
|
3632
6596
|
}
|
|
3633
|
-
return new
|
|
6597
|
+
return new HDate(day, IYYAR, year);
|
|
3634
6598
|
}
|
|
3635
6599
|
|
|
3636
6600
|
const ykk = 'Yom Kippur Katan';
|
|
@@ -3653,15 +6617,15 @@ class YomKippurKatanEvent extends HolidayEvent {
|
|
|
3653
6617
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
3654
6618
|
*/
|
|
3655
6619
|
render(locale) {
|
|
3656
|
-
const monthName0 =
|
|
6620
|
+
const monthName0 = Locale.gettext(this.nextMonthName, locale);
|
|
3657
6621
|
const monthName = monthName0.replace(/'/g, '’');
|
|
3658
|
-
return
|
|
6622
|
+
return Locale.gettext(ykk, locale) + ' ' + monthName;
|
|
3659
6623
|
}
|
|
3660
6624
|
/**
|
|
3661
6625
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
3662
6626
|
*/
|
|
3663
6627
|
renderBrief(locale) {
|
|
3664
|
-
return
|
|
6628
|
+
return Locale.gettext(ykk, locale);
|
|
3665
6629
|
}
|
|
3666
6630
|
url() {
|
|
3667
6631
|
return undefined;
|
|
@@ -3706,7 +6670,7 @@ function holidayFilter(il) {
|
|
|
3706
6670
|
* @param [il] use the Israeli schedule for holidays
|
|
3707
6671
|
*/
|
|
3708
6672
|
function getHolidaysOnDate(date, il) {
|
|
3709
|
-
const hd =
|
|
6673
|
+
const hd = HDate.isHDate(date) ? date : new HDate(date);
|
|
3710
6674
|
const hdStr = hd.toString();
|
|
3711
6675
|
const yearMap = getHolidaysForYear_(hd.getFullYear());
|
|
3712
6676
|
const events = yearMap.get(hdStr);
|
|
@@ -3732,14 +6696,14 @@ const TUE = 2;
|
|
|
3732
6696
|
const THU = 4;
|
|
3733
6697
|
const FRI$1 = 5;
|
|
3734
6698
|
const SAT$1 = 6;
|
|
3735
|
-
const NISAN$1 =
|
|
3736
|
-
const TAMUZ =
|
|
3737
|
-
const AV =
|
|
3738
|
-
const TISHREI$1 =
|
|
3739
|
-
const KISLEV =
|
|
3740
|
-
const TEVET =
|
|
3741
|
-
const ADAR_I =
|
|
3742
|
-
const ADAR_II =
|
|
6699
|
+
const NISAN$1 = months.NISAN;
|
|
6700
|
+
const TAMUZ = months.TAMUZ;
|
|
6701
|
+
const AV = months.AV;
|
|
6702
|
+
const TISHREI$1 = months.TISHREI;
|
|
6703
|
+
const KISLEV = months.KISLEV;
|
|
6704
|
+
const TEVET = months.TEVET;
|
|
6705
|
+
const ADAR_I = months.ADAR_I;
|
|
6706
|
+
const ADAR_II = months.ADAR_II;
|
|
3743
6707
|
const emojiIsraelFlag = { emoji: '🇮🇱' };
|
|
3744
6708
|
const chanukahEmoji = '🕎';
|
|
3745
6709
|
const yearCache = new QuickLRU({ maxSize: 400 });
|
|
@@ -3772,8 +6736,8 @@ function getHolidaysForYear_(year) {
|
|
|
3772
6736
|
if (cached) {
|
|
3773
6737
|
return cached;
|
|
3774
6738
|
}
|
|
3775
|
-
const RH = new
|
|
3776
|
-
const pesach = new
|
|
6739
|
+
const RH = new HDate(1, TISHREI$1, year);
|
|
6740
|
+
const pesach = new HDate(15, NISAN$1, year);
|
|
3777
6741
|
const map = new Map();
|
|
3778
6742
|
function add(...events) {
|
|
3779
6743
|
for (const ev of events) {
|
|
@@ -3793,7 +6757,7 @@ function getHolidaysForYear_(year) {
|
|
|
3793
6757
|
}
|
|
3794
6758
|
}
|
|
3795
6759
|
for (const h of staticHolidays) {
|
|
3796
|
-
const hd = new
|
|
6760
|
+
const hd = new HDate(h.dd, h.mm, year);
|
|
3797
6761
|
const ev = new HolidayEvent(hd, h.desc, h.flags);
|
|
3798
6762
|
if (h.emoji)
|
|
3799
6763
|
ev.emoji = h.emoji;
|
|
@@ -3805,39 +6769,39 @@ function getHolidaysForYear_(year) {
|
|
|
3805
6769
|
add(new RoshHashanaEvent(RH, year, CHAG | LIGHT_CANDLES_TZEIS$1));
|
|
3806
6770
|
// Variable date holidays
|
|
3807
6771
|
const tzomGedaliahDay = RH.getDay() === THU ? 4 : 3;
|
|
3808
|
-
add(new HolidayEvent(new
|
|
6772
|
+
add(new HolidayEvent(new HDate(tzomGedaliahDay, TISHREI$1, year), holidayDesc.TZOM_GEDALIAH, MINOR_FAST$1));
|
|
3809
6773
|
// first SAT after RH
|
|
3810
|
-
add(new HolidayEvent(new
|
|
3811
|
-
const rchTevet =
|
|
3812
|
-
? new
|
|
3813
|
-
: new
|
|
6774
|
+
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, 7 + RH.abs())), holidayDesc.SHABBAT_SHUVA, SPECIAL_SHABBAT$1));
|
|
6775
|
+
const rchTevet = HDate.shortKislev(year)
|
|
6776
|
+
? new HDate(1, TEVET, year)
|
|
6777
|
+
: new HDate(30, KISLEV, year);
|
|
3814
6778
|
add(new HolidayEvent(rchTevet, holidayDesc.CHAG_HABANOT, MINOR_HOLIDAY$1));
|
|
3815
6779
|
// yes, we know Kislev 30-32 are wrong
|
|
3816
6780
|
// HDate() corrects the month automatically
|
|
3817
6781
|
for (let candles = 2; candles <= 8; candles++) {
|
|
3818
|
-
const hd = new
|
|
6782
|
+
const hd = new HDate(23 + candles, KISLEV, year);
|
|
3819
6783
|
add(new ChanukahEvent(hd, `Chanukah: ${candles} Candles`, MINOR_HOLIDAY$1 | CHANUKAH_CANDLES$1, {
|
|
3820
6784
|
chanukahDay: candles - 1,
|
|
3821
6785
|
emoji: chanukahEmoji + KEYCAP_DIGITS[candles],
|
|
3822
6786
|
}));
|
|
3823
6787
|
}
|
|
3824
|
-
add(new ChanukahEvent(new
|
|
3825
|
-
add(new AsaraBTevetEvent(new
|
|
6788
|
+
add(new ChanukahEvent(new HDate(32, KISLEV, year), holidayDesc.CHANUKAH_8TH_DAY, MINOR_HOLIDAY$1, { chanukahDay: 8, emoji: chanukahEmoji }));
|
|
6789
|
+
add(new AsaraBTevetEvent(new HDate(10, TEVET, year), holidayDesc.ASARA_BTEVET, MINOR_FAST$1));
|
|
3826
6790
|
const pesachAbs = pesach.abs();
|
|
3827
|
-
add(new HolidayEvent(new
|
|
3828
|
-
const haChodeshAbs =
|
|
3829
|
-
add(new HolidayEvent(new
|
|
6791
|
+
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 43)), holidayDesc.SHABBAT_SHEKALIM, SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 30)), holidayDesc.SHABBAT_ZACHOR, SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(pesachAbs - (pesach.getDay() === TUE ? 33 : 31)), holidayDesc.TAANIT_ESTHER, MINOR_FAST$1));
|
|
6792
|
+
const haChodeshAbs = HDate.dayOnOrBefore(SAT$1, pesachAbs - 14);
|
|
6793
|
+
add(new HolidayEvent(new HDate(haChodeshAbs - 7), holidayDesc.SHABBAT_PARAH, SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(haChodeshAbs), holidayDesc.SHABBAT_HACHODESH, SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 1)), holidayDesc.SHABBAT_HAGADOL, SPECIAL_SHABBAT$1), new HolidayEvent(
|
|
3830
6794
|
// if the fast falls on Shabbat, move to Thursday
|
|
3831
6795
|
pesach.prev().getDay() === SAT$1
|
|
3832
6796
|
? pesach.onOrBefore(THU)
|
|
3833
|
-
: new
|
|
3834
|
-
add(new HolidayEvent(new
|
|
6797
|
+
: new HDate(14, NISAN$1, year), holidayDesc.TAANIT_BECHOROT, MINOR_FAST$1));
|
|
6798
|
+
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, new HDate(1, TISHREI$1, year + 1).abs() - 4)), holidayDesc.LEIL_SELICHOT, MINOR_HOLIDAY$1, { emoji: '🕍' }));
|
|
3835
6799
|
if (pesach.getDay() === SUN) {
|
|
3836
|
-
add(new HolidayEvent(new
|
|
6800
|
+
add(new HolidayEvent(new HDate(16, ADAR_II, year), holidayDesc.PURIM_MESHULASH, MINOR_HOLIDAY$1));
|
|
3837
6801
|
}
|
|
3838
|
-
if (
|
|
3839
|
-
add(new HolidayEvent(new
|
|
3840
|
-
add(new HolidayEvent(new
|
|
6802
|
+
if (HDate.isLeapYear(year)) {
|
|
6803
|
+
add(new HolidayEvent(new HDate(14, ADAR_I, year), holidayDesc.PURIM_KATAN, MINOR_HOLIDAY$1, { emoji: '🎭️' }));
|
|
6804
|
+
add(new HolidayEvent(new HDate(15, ADAR_I, year), holidayDesc.SHUSHAN_PURIM_KATAN, MINOR_HOLIDAY$1, { emoji: '🎭️' }));
|
|
3841
6805
|
}
|
|
3842
6806
|
const nisan27dt = dateYomHaShoah(year);
|
|
3843
6807
|
if (nisan27dt) {
|
|
@@ -3849,13 +6813,13 @@ function getHolidaysForYear_(year) {
|
|
|
3849
6813
|
}
|
|
3850
6814
|
for (const h of staticModernHolidays) {
|
|
3851
6815
|
if (year >= h.firstYear) {
|
|
3852
|
-
let hd = new
|
|
6816
|
+
let hd = new HDate(h.dd, h.mm, year);
|
|
3853
6817
|
const dow = hd.getDay();
|
|
3854
6818
|
if (h.friSatMovetoThu && (dow === FRI$1 || dow === SAT$1)) {
|
|
3855
6819
|
hd = hd.onOrBefore(THU);
|
|
3856
6820
|
}
|
|
3857
6821
|
else if (h.friPostponeToSun && dow === FRI$1) {
|
|
3858
|
-
hd = new
|
|
6822
|
+
hd = new HDate(hd.abs() + 2);
|
|
3859
6823
|
}
|
|
3860
6824
|
else if (h.satPostponeToSun && dow === SAT$1) {
|
|
3861
6825
|
hd = hd.next();
|
|
@@ -3868,14 +6832,14 @@ function getHolidaysForYear_(year) {
|
|
|
3868
6832
|
add(ev);
|
|
3869
6833
|
}
|
|
3870
6834
|
}
|
|
3871
|
-
let tamuz17 = new
|
|
6835
|
+
let tamuz17 = new HDate(17, TAMUZ, year);
|
|
3872
6836
|
let tamuz17attrs;
|
|
3873
6837
|
if (tamuz17.getDay() === SAT$1) {
|
|
3874
|
-
tamuz17 = new
|
|
6838
|
+
tamuz17 = new HDate(18, TAMUZ, year);
|
|
3875
6839
|
tamuz17attrs = { observed: true };
|
|
3876
6840
|
}
|
|
3877
6841
|
add(new HolidayEvent(tamuz17, holidayDesc.TZOM_TAMMUZ, MINOR_FAST$1, tamuz17attrs));
|
|
3878
|
-
let av9dt = new
|
|
6842
|
+
let av9dt = new HDate(9, AV, year);
|
|
3879
6843
|
let av9title = holidayDesc.TISHA_BAV;
|
|
3880
6844
|
let av9attrs;
|
|
3881
6845
|
if (av9dt.getDay() === SAT$1) {
|
|
@@ -3884,38 +6848,38 @@ function getHolidaysForYear_(year) {
|
|
|
3884
6848
|
av9title += ' (observed)';
|
|
3885
6849
|
}
|
|
3886
6850
|
const av9abs = av9dt.abs();
|
|
3887
|
-
add(new HolidayEvent(new
|
|
3888
|
-
const monthsInYear =
|
|
6851
|
+
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, av9abs)), holidayDesc.SHABBAT_CHAZON, SPECIAL_SHABBAT$1), new HolidayEvent(av9dt.prev(), holidayDesc.EREV_TISHA_BAV, EREV$1 | MAJOR_FAST$1, av9attrs), new HolidayEvent(av9dt, av9title, MAJOR_FAST$1, av9attrs), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, av9abs + 7)), holidayDesc.SHABBAT_NACHAMU, SPECIAL_SHABBAT$1));
|
|
6852
|
+
const monthsInYear = HDate.monthsInYear(year);
|
|
3889
6853
|
for (let month = 1; month <= monthsInYear; month++) {
|
|
3890
|
-
const monthName =
|
|
6854
|
+
const monthName = HDate.getMonthName(month, year);
|
|
3891
6855
|
if ((month === NISAN$1
|
|
3892
|
-
?
|
|
3893
|
-
:
|
|
3894
|
-
add(new RoshChodeshEvent(new
|
|
3895
|
-
add(new RoshChodeshEvent(new
|
|
6856
|
+
? HDate.daysInMonth(HDate.monthsInYear(year - 1), year - 1)
|
|
6857
|
+
: HDate.daysInMonth(month - 1, year)) === 30) {
|
|
6858
|
+
add(new RoshChodeshEvent(new HDate(1, month, year), monthName));
|
|
6859
|
+
add(new RoshChodeshEvent(new HDate(30, month - 1, year), monthName));
|
|
3896
6860
|
}
|
|
3897
6861
|
else if (month !== TISHREI$1) {
|
|
3898
|
-
add(new RoshChodeshEvent(new
|
|
6862
|
+
add(new RoshChodeshEvent(new HDate(1, month, year), monthName));
|
|
3899
6863
|
}
|
|
3900
6864
|
}
|
|
3901
6865
|
// Begin: Yom Kippur Katan
|
|
3902
6866
|
// start at Iyyar because one may not fast during Nisan
|
|
3903
|
-
for (let month =
|
|
6867
|
+
for (let month = months.IYYAR; month <= monthsInYear; month++) {
|
|
3904
6868
|
const nextMonth = month + 1;
|
|
3905
6869
|
// Yom Kippur Katan is not observed on the day before Rosh Hashanah.
|
|
3906
6870
|
// Not observed prior to Rosh Chodesh Cheshvan because Yom Kippur has just passed.
|
|
3907
6871
|
// Not observed before Rosh Chodesh Tevet, because that day is Hanukkah.
|
|
3908
6872
|
if (nextMonth === TISHREI$1 ||
|
|
3909
|
-
nextMonth ===
|
|
6873
|
+
nextMonth === months.CHESHVAN ||
|
|
3910
6874
|
nextMonth === TEVET) {
|
|
3911
6875
|
continue;
|
|
3912
6876
|
}
|
|
3913
|
-
let ykk = new
|
|
6877
|
+
let ykk = new HDate(29, month, year);
|
|
3914
6878
|
const dow = ykk.getDay();
|
|
3915
6879
|
if (dow === FRI$1 || dow === SAT$1) {
|
|
3916
6880
|
ykk = ykk.onOrBefore(THU);
|
|
3917
6881
|
}
|
|
3918
|
-
const nextMonthName =
|
|
6882
|
+
const nextMonthName = HDate.getMonthName(nextMonth, year);
|
|
3919
6883
|
const ev = new YomKippurKatanEvent(ykk, nextMonthName);
|
|
3920
6884
|
add(ev);
|
|
3921
6885
|
}
|
|
@@ -3925,7 +6889,7 @@ function getHolidaysForYear_(year) {
|
|
|
3925
6889
|
// Birkat Hachamah appears only once every 28 years
|
|
3926
6890
|
const birkatHaChama = getBirkatHaChama(year);
|
|
3927
6891
|
if (birkatHaChama) {
|
|
3928
|
-
const hd = new
|
|
6892
|
+
const hd = new HDate(birkatHaChama);
|
|
3929
6893
|
add(new HolidayEvent(hd, holidayDesc.BIRKAT_HACHAMAH, MINOR_HOLIDAY$1, { emoji: '☀️' }));
|
|
3930
6894
|
}
|
|
3931
6895
|
yearCache.set(year, map);
|
|
@@ -3942,10 +6906,10 @@ function getHolidaysForYear_(year) {
|
|
|
3942
6906
|
* @private
|
|
3943
6907
|
*/
|
|
3944
6908
|
function getBirkatHaChama(year) {
|
|
3945
|
-
const leap =
|
|
6909
|
+
const leap = HDate.isLeapYear(year);
|
|
3946
6910
|
const startMonth = leap ? ADAR_II : NISAN$1;
|
|
3947
6911
|
const startDay = leap ? 20 : 1;
|
|
3948
|
-
const baseRd =
|
|
6912
|
+
const baseRd = HDate.hebrew2abs(year, startMonth, startDay);
|
|
3949
6913
|
for (let day = 0; day <= 40; day++) {
|
|
3950
6914
|
const abs = baseRd + day;
|
|
3951
6915
|
const elapsed = abs + 1373429;
|
|
@@ -3962,12 +6926,12 @@ function getBirkatHaChama(year) {
|
|
|
3962
6926
|
*/
|
|
3963
6927
|
function getHolidaysForYearArray(year, il) {
|
|
3964
6928
|
const yearMap = getHolidaysForYear_(year);
|
|
3965
|
-
const startAbs =
|
|
3966
|
-
const endAbs =
|
|
6929
|
+
const startAbs = HDate.hebrew2abs(year, TISHREI$1, 1);
|
|
6930
|
+
const endAbs = HDate.hebrew2abs(year + 1, TISHREI$1, 1) - 1;
|
|
3967
6931
|
let events = [];
|
|
3968
6932
|
const myFilter = il ? observedInIsrael : observedInDiaspora;
|
|
3969
6933
|
for (let absDt = startAbs; absDt <= endAbs; absDt++) {
|
|
3970
|
-
const hd = new
|
|
6934
|
+
const hd = new HDate(absDt);
|
|
3971
6935
|
const holidays = yearMap.get(hd.toString());
|
|
3972
6936
|
if (holidays) {
|
|
3973
6937
|
const filtered = holidays.filter(myFilter);
|
|
@@ -3989,14 +6953,14 @@ class MevarchimChodeshEvent extends Event {
|
|
|
3989
6953
|
*/
|
|
3990
6954
|
constructor(date, monthName, memo, locale) {
|
|
3991
6955
|
super(date, `${mevarchimChodeshStr} ${monthName}`, flags.SHABBAT_MEVARCHIM);
|
|
3992
|
-
this.monthName =
|
|
6956
|
+
this.monthName = Locale.gettext(monthName, locale);
|
|
3993
6957
|
if (memo) {
|
|
3994
6958
|
this.memo = memo;
|
|
3995
6959
|
}
|
|
3996
6960
|
else {
|
|
3997
6961
|
const hyear = date.getFullYear();
|
|
3998
6962
|
const hmonth = date.getMonth();
|
|
3999
|
-
const monNext = hmonth ===
|
|
6963
|
+
const monNext = hmonth === HDate.monthsInYear(hyear) ? months.NISAN : hmonth + 1;
|
|
4000
6964
|
const molad = new Molad(hyear, monNext);
|
|
4001
6965
|
this.memo = molad.render('en', { hour12: false });
|
|
4002
6966
|
}
|
|
@@ -4009,9 +6973,9 @@ class MevarchimChodeshEvent extends Event {
|
|
|
4009
6973
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
4010
6974
|
*/
|
|
4011
6975
|
render(locale) {
|
|
4012
|
-
const monthName0 =
|
|
6976
|
+
const monthName0 = Locale.gettext(this.monthName, locale);
|
|
4013
6977
|
const monthName = monthName0.replace(/'/g, '’');
|
|
4014
|
-
return
|
|
6978
|
+
return Locale.gettext(mevarchimChodeshStr, locale) + ' ' + monthName;
|
|
4015
6979
|
}
|
|
4016
6980
|
/**
|
|
4017
6981
|
* Returns (translated) description of this event
|
|
@@ -4086,7 +7050,7 @@ const WHOLE = 2;
|
|
|
4086
7050
|
/**
|
|
4087
7051
|
* @private
|
|
4088
7052
|
*/
|
|
4089
|
-
function hallel_(events, hdate
|
|
7053
|
+
function hallel_(events, hdate) {
|
|
4090
7054
|
const whole = events
|
|
4091
7055
|
.filter(ev => {
|
|
4092
7056
|
const desc = ev.getDesc();
|
|
@@ -4096,7 +7060,7 @@ function hallel_(events, hdate$1) {
|
|
|
4096
7060
|
return (desc.startsWith('Chanukah') ||
|
|
4097
7061
|
desc.startsWith('Shavuot') ||
|
|
4098
7062
|
desc.startsWith('Sukkot') ||
|
|
4099
|
-
(month ===
|
|
7063
|
+
(month === months.NISAN &&
|
|
4100
7064
|
(mday === 15 || mday === 16) &&
|
|
4101
7065
|
ev.getFlags() & flags.CHAG) || // Pesach
|
|
4102
7066
|
desc === "Yom HaAtzma'ut" ||
|
|
@@ -4105,7 +7069,7 @@ function hallel_(events, hdate$1) {
|
|
|
4105
7069
|
.map(ev => {
|
|
4106
7070
|
return ev.getDate().abs();
|
|
4107
7071
|
});
|
|
4108
|
-
const abs = hdate
|
|
7072
|
+
const abs = hdate.abs();
|
|
4109
7073
|
if (whole.includes(abs)) {
|
|
4110
7074
|
return WHOLE;
|
|
4111
7075
|
}
|
|
@@ -4157,14 +7121,14 @@ const NONE = {
|
|
|
4157
7121
|
function tachanun(hdate, il) {
|
|
4158
7122
|
return tachanun0(hdate, il, true);
|
|
4159
7123
|
}
|
|
4160
|
-
function tachanun0(hdate
|
|
4161
|
-
const year = hdate
|
|
7124
|
+
function tachanun0(hdate, il, checkNext) {
|
|
7125
|
+
const year = hdate.yy;
|
|
4162
7126
|
const dates = tachanunYear(year, il);
|
|
4163
|
-
const abs = hdate
|
|
7127
|
+
const abs = hdate.abs();
|
|
4164
7128
|
if (dates.none.indexOf(abs) > -1) {
|
|
4165
7129
|
return NONE;
|
|
4166
7130
|
}
|
|
4167
|
-
const dow = hdate
|
|
7131
|
+
const dow = hdate.getDay();
|
|
4168
7132
|
const ret = {
|
|
4169
7133
|
shacharit: false,
|
|
4170
7134
|
mincha: false,
|
|
@@ -4178,7 +7142,7 @@ function tachanun0(hdate$1, il, checkNext) {
|
|
|
4178
7142
|
}
|
|
4179
7143
|
const tomorrow = abs + 1;
|
|
4180
7144
|
if (checkNext && dates.yesPrev.indexOf(tomorrow) === -1) {
|
|
4181
|
-
const tmp = tachanun0(new
|
|
7145
|
+
const tmp = tachanun0(new HDate(tomorrow), il, false);
|
|
4182
7146
|
ret.mincha = tmp.shacharit;
|
|
4183
7147
|
}
|
|
4184
7148
|
else {
|
|
@@ -4190,53 +7154,53 @@ function tachanun0(hdate$1, il, checkNext) {
|
|
|
4190
7154
|
return ret;
|
|
4191
7155
|
}
|
|
4192
7156
|
function tachanunYear(year, il) {
|
|
4193
|
-
const leap =
|
|
4194
|
-
const monthsInYear =
|
|
4195
|
-
let av9dt = new
|
|
7157
|
+
const leap = HDate.isLeapYear(year);
|
|
7158
|
+
const monthsInYear = HDate.monthsInYear(year);
|
|
7159
|
+
let av9dt = new HDate(9, months.AV, year);
|
|
4196
7160
|
if (av9dt.getDay() === 6) {
|
|
4197
7161
|
av9dt = av9dt.next();
|
|
4198
7162
|
}
|
|
4199
|
-
let shushPurim = new
|
|
7163
|
+
let shushPurim = new HDate(15, months.ADAR_II, year);
|
|
4200
7164
|
if (shushPurim.getDay() === 6) {
|
|
4201
7165
|
shushPurim = shushPurim.next();
|
|
4202
7166
|
}
|
|
4203
7167
|
const none = [
|
|
4204
|
-
new
|
|
7168
|
+
new HDate(2, months.TISHREI, year), // Rosh Hashana II
|
|
4205
7169
|
].concat(
|
|
4206
7170
|
// Rosh Chodesh - 1st of every month. Also includes RH day 1 (1 Tishrei)
|
|
4207
|
-
range(1, monthsInYear).map(month => new
|
|
7171
|
+
range(1, monthsInYear).map(month => new HDate(1, month, year)),
|
|
4208
7172
|
// Rosh Chodesh - 30th of months that have one
|
|
4209
7173
|
range(1, monthsInYear)
|
|
4210
|
-
.filter(month =>
|
|
4211
|
-
.map(month => new
|
|
7174
|
+
.filter(month => HDate.daysInMonth(month, year) === 30)
|
|
7175
|
+
.map(month => new HDate(30, month, year)),
|
|
4212
7176
|
// entire month of Nisan
|
|
4213
|
-
range(1,
|
|
7177
|
+
range(1, HDate.daysInMonth(months.NISAN, year)).map(mday => new HDate(mday, months.NISAN, year)), new HDate(18, months.IYYAR, year), // Lag BaOmer
|
|
4214
7178
|
// Rosh Chodesh Sivan thru Isru Chag
|
|
4215
|
-
range(1, 8 - (il ? 1 : 0)).map(mday => new
|
|
4216
|
-
new
|
|
4217
|
-
new
|
|
7179
|
+
range(1, 8 - (il ? 1 : 0)).map(mday => new HDate(mday, months.SIVAN, year)), av9dt, // Tisha B'Av
|
|
7180
|
+
new HDate(15, months.AV, year), // Tu B'Av
|
|
7181
|
+
new HDate(29, months.ELUL, year), // Erev Rosh Hashanah
|
|
4218
7182
|
// Erev Yom Kippur thru Isru Chag
|
|
4219
|
-
range(9, 24 - (il ? 1 : 0)).map(mday => new
|
|
7183
|
+
range(9, 24 - (il ? 1 : 0)).map(mday => new HDate(mday, months.TISHREI, year)),
|
|
4220
7184
|
// Chanukah
|
|
4221
|
-
range(25, 33).map(mday => new
|
|
4222
|
-
new
|
|
4223
|
-
shushPurim, leap ? new
|
|
7185
|
+
range(25, 33).map(mday => new HDate(mday, months.KISLEV, year)), new HDate(15, months.SHVAT, year), // Tu BiShvat
|
|
7186
|
+
new HDate(14, months.ADAR_II, year), // Purim
|
|
7187
|
+
shushPurim, leap ? new HDate(14, months.ADAR_I, year) : [] // Purim Katan
|
|
4224
7188
|
);
|
|
4225
7189
|
const some = [
|
|
4226
|
-
new
|
|
7190
|
+
new HDate(14, months.IYYAR, year), // Pesach Sheini
|
|
4227
7191
|
].concat(
|
|
4228
7192
|
// Until 14 Sivan
|
|
4229
|
-
range(1, 13).map(mday => new
|
|
7193
|
+
range(1, 13).map(mday => new HDate(mday, months.SIVAN, year)),
|
|
4230
7194
|
// Until after Rosh Chodesh Cheshvan
|
|
4231
|
-
range(20, 31).map(mday => new
|
|
7195
|
+
range(20, 31).map(mday => new HDate(mday, months.TISHREI, year)),
|
|
4232
7196
|
// Yom HaAtzma'ut, which changes based on day of week
|
|
4233
7197
|
year >= 5708 ? dateYomHaZikaron(year).next() : [],
|
|
4234
7198
|
// Yom Yerushalayim
|
|
4235
|
-
year >= 5727 ? new
|
|
7199
|
+
year >= 5727 ? new HDate(28, months.IYYAR, year) : []);
|
|
4236
7200
|
const yesPrev = [
|
|
4237
|
-
new
|
|
4238
|
-
new
|
|
4239
|
-
new
|
|
7201
|
+
new HDate(29, months.ELUL, year - 1), // Erev Rosh Hashanah
|
|
7202
|
+
new HDate(9, months.TISHREI, year), // Erev Yom Kippur
|
|
7203
|
+
new HDate(14, months.IYYAR, year), // Pesach Sheini
|
|
4240
7204
|
];
|
|
4241
7205
|
return {
|
|
4242
7206
|
none: none.map(hd => hd.abs()).sort((a, b) => a - b),
|
|
@@ -4245,7 +7209,7 @@ function tachanunYear(year, il) {
|
|
|
4245
7209
|
};
|
|
4246
7210
|
}
|
|
4247
7211
|
|
|
4248
|
-
const TISHREI =
|
|
7212
|
+
const TISHREI = months.TISHREI;
|
|
4249
7213
|
/**
|
|
4250
7214
|
* Gets the R.D. days for a number, Date, or HDate
|
|
4251
7215
|
* @private
|
|
@@ -4253,9 +7217,9 @@ const TISHREI = hdate.months.TISHREI;
|
|
|
4253
7217
|
function getAbs(d) {
|
|
4254
7218
|
if (typeof d === 'number')
|
|
4255
7219
|
return d;
|
|
4256
|
-
if (
|
|
4257
|
-
return
|
|
4258
|
-
if (
|
|
7220
|
+
if (isDate(d))
|
|
7221
|
+
return greg2abs(d);
|
|
7222
|
+
if (HDate.isHDate(d))
|
|
4259
7223
|
return d.abs();
|
|
4260
7224
|
throw new TypeError(`Invalid date type: ${d}`);
|
|
4261
7225
|
}
|
|
@@ -4264,7 +7228,7 @@ function getYear(options) {
|
|
|
4264
7228
|
return Number(options.year);
|
|
4265
7229
|
}
|
|
4266
7230
|
return options.isHebrewYear
|
|
4267
|
-
? new
|
|
7231
|
+
? new HDate().getFullYear()
|
|
4268
7232
|
: new Date().getFullYear();
|
|
4269
7233
|
}
|
|
4270
7234
|
/**
|
|
@@ -4298,7 +7262,7 @@ function getStartAndEnd(options) {
|
|
|
4298
7262
|
function getMonth(options) {
|
|
4299
7263
|
if (options.month) {
|
|
4300
7264
|
if (options.isHebrewYear) {
|
|
4301
|
-
return
|
|
7265
|
+
return HDate.monthNum(options.month);
|
|
4302
7266
|
}
|
|
4303
7267
|
else if (typeof options.month === 'number') {
|
|
4304
7268
|
return options.month;
|
|
@@ -4312,10 +7276,10 @@ function startEndGregorian(theMonth, theYear, numYears) {
|
|
|
4312
7276
|
if (theYear < 100) {
|
|
4313
7277
|
startGreg.setFullYear(theYear);
|
|
4314
7278
|
}
|
|
4315
|
-
const startAbs =
|
|
7279
|
+
const startAbs = greg2abs(startGreg);
|
|
4316
7280
|
let endAbs;
|
|
4317
7281
|
if (theMonth) {
|
|
4318
|
-
endAbs = startAbs +
|
|
7282
|
+
endAbs = startAbs + daysInGregMonth(theMonth, theYear) - 1;
|
|
4319
7283
|
}
|
|
4320
7284
|
else {
|
|
4321
7285
|
const endYear = theYear + numYears;
|
|
@@ -4323,16 +7287,16 @@ function startEndGregorian(theMonth, theYear, numYears) {
|
|
|
4323
7287
|
if (endYear < 100) {
|
|
4324
7288
|
endGreg.setFullYear(endYear);
|
|
4325
7289
|
}
|
|
4326
|
-
endAbs =
|
|
7290
|
+
endAbs = greg2abs(endGreg) - 1;
|
|
4327
7291
|
}
|
|
4328
7292
|
return [startAbs, endAbs];
|
|
4329
7293
|
}
|
|
4330
7294
|
function startEndHebrew(theMonth, theYear, numYears) {
|
|
4331
|
-
const startDate = new
|
|
7295
|
+
const startDate = new HDate(1, theMonth || TISHREI, theYear);
|
|
4332
7296
|
let startAbs = startDate.abs();
|
|
4333
7297
|
const endAbs = theMonth
|
|
4334
7298
|
? startAbs + startDate.daysInMonth()
|
|
4335
|
-
: new
|
|
7299
|
+
: new HDate(1, TISHREI, theYear + numYears).abs() - 1;
|
|
4336
7300
|
// for full Hebrew year, start on Erev Rosh Hashana which
|
|
4337
7301
|
// is technically in the previous Hebrew year
|
|
4338
7302
|
// (but conveniently lets us get candle-lighting time for Erev)
|
|
@@ -4462,13 +7426,13 @@ function calendar(options = {}) {
|
|
|
4462
7426
|
throw new TypeError(`Invalid options.locale: ${options.locale}`);
|
|
4463
7427
|
}
|
|
4464
7428
|
const locale = options.ashkenazi ? 'ashkenazi' : options.locale;
|
|
4465
|
-
const translationObj =
|
|
7429
|
+
const translationObj = Locale.useLocale(locale);
|
|
4466
7430
|
if (!translationObj) {
|
|
4467
7431
|
throw new TypeError(`Locale '${locale}' not found; did you forget to import @hebcal/locales?`);
|
|
4468
7432
|
}
|
|
4469
7433
|
}
|
|
4470
7434
|
else {
|
|
4471
|
-
|
|
7435
|
+
Locale.useLocale('en');
|
|
4472
7436
|
}
|
|
4473
7437
|
const evts = [];
|
|
4474
7438
|
let sedra;
|
|
@@ -4480,12 +7444,12 @@ function calendar(options = {}) {
|
|
|
4480
7444
|
warnUnrecognizedOptions(options);
|
|
4481
7445
|
const startAbs = startAndEnd[0];
|
|
4482
7446
|
const endAbs = startAndEnd[1];
|
|
4483
|
-
const startGreg =
|
|
7447
|
+
const startGreg = abs2greg(startAbs);
|
|
4484
7448
|
if (startGreg.getFullYear() < 100) {
|
|
4485
7449
|
options.candlelighting = false;
|
|
4486
7450
|
}
|
|
4487
7451
|
for (let abs = startAbs; abs <= endAbs; abs++) {
|
|
4488
|
-
const hd = new
|
|
7452
|
+
const hd = new HDate(abs);
|
|
4489
7453
|
const hyear = hd.getFullYear();
|
|
4490
7454
|
if (hyear !== currentYear) {
|
|
4491
7455
|
currentYear = hyear;
|
|
@@ -4494,8 +7458,8 @@ function calendar(options = {}) {
|
|
|
4494
7458
|
sedra = getSedra(currentYear, il);
|
|
4495
7459
|
}
|
|
4496
7460
|
if (options.omer) {
|
|
4497
|
-
beginOmer =
|
|
4498
|
-
endOmer =
|
|
7461
|
+
beginOmer = HDate.hebrew2abs(currentYear, NISAN, 16);
|
|
7462
|
+
endOmer = HDate.hebrew2abs(currentYear, SIVAN, 5);
|
|
4499
7463
|
}
|
|
4500
7464
|
}
|
|
4501
7465
|
const prevEventsLength = evts.length;
|
|
@@ -4516,7 +7480,7 @@ function calendar(options = {}) {
|
|
|
4516
7480
|
if (options.yizkor) {
|
|
4517
7481
|
const mm = hd.getMonth();
|
|
4518
7482
|
const dd = hd.getDate();
|
|
4519
|
-
if ((mm ===
|
|
7483
|
+
if ((mm === months.TISHREI && (dd === 10 || dd === 22)) ||
|
|
4520
7484
|
(mm === NISAN && dd === (il ? 21 : 22)) ||
|
|
4521
7485
|
(mm === SIVAN && dd === (il ? 6 : 7))) {
|
|
4522
7486
|
const linkedEvent = holidays.filter(ev => ev.observedIn(il))[0];
|
|
@@ -4577,9 +7541,9 @@ function calendar(options = {}) {
|
|
|
4577
7541
|
}
|
|
4578
7542
|
const FRI = 5;
|
|
4579
7543
|
const SAT = 6;
|
|
4580
|
-
const NISAN =
|
|
4581
|
-
const SIVAN =
|
|
4582
|
-
const ELUL =
|
|
7544
|
+
const NISAN = months.NISAN;
|
|
7545
|
+
const SIVAN = months.SIVAN;
|
|
7546
|
+
const ELUL = months.ELUL;
|
|
4583
7547
|
const LIGHT_CANDLES = flags.LIGHT_CANDLES;
|
|
4584
7548
|
const YOM_TOV_ENDS = flags.YOM_TOV_ENDS;
|
|
4585
7549
|
const CHUL_ONLY = flags.CHUL_ONLY;
|
|
@@ -4928,15 +7892,15 @@ function appendHolidayAndRelated(candlesEv, events, ev, options, isFriday, isSat
|
|
|
4928
7892
|
function makeMoladAndMevarchimChodesh(hd, options) {
|
|
4929
7893
|
const evts = [];
|
|
4930
7894
|
const hmonth = hd.getMonth();
|
|
4931
|
-
const hdate
|
|
4932
|
-
if (hmonth !== ELUL && hdate
|
|
7895
|
+
const hdate = hd.getDate();
|
|
7896
|
+
if (hmonth !== ELUL && hdate >= 23 && hdate <= 29) {
|
|
4933
7897
|
const hyear = hd.getFullYear();
|
|
4934
|
-
const monNext = hmonth ===
|
|
7898
|
+
const monNext = hmonth === HDate.monthsInYear(hyear) ? NISAN : hmonth + 1;
|
|
4935
7899
|
if (options.molad) {
|
|
4936
7900
|
evts.push(new MoladEvent(hd, hyear, monNext, options));
|
|
4937
7901
|
}
|
|
4938
7902
|
if (options.shabbatMevarchim) {
|
|
4939
|
-
const nextMonthName =
|
|
7903
|
+
const nextMonthName = HDate.getMonthName(monNext, hyear);
|
|
4940
7904
|
const molad = new Molad(hyear, monNext);
|
|
4941
7905
|
const memo = molad.render(options.locale || 'en', options);
|
|
4942
7906
|
evts.push(new MevarchimChodeshEvent(hd, nextMonthName, memo, options.locale));
|
|
@@ -5142,11 +8106,11 @@ class HebrewCalendar {
|
|
|
5142
8106
|
* @returns anniversary occurring in `hyear`
|
|
5143
8107
|
*/
|
|
5144
8108
|
static getBirthdayOrAnniversary(hyear, gdate) {
|
|
5145
|
-
const dt =
|
|
8109
|
+
const dt = getBirthdayHD(hyear, gdate);
|
|
5146
8110
|
if (typeof dt === 'undefined') {
|
|
5147
8111
|
return dt;
|
|
5148
8112
|
}
|
|
5149
|
-
return new
|
|
8113
|
+
return new HDate(dt);
|
|
5150
8114
|
}
|
|
5151
8115
|
/**
|
|
5152
8116
|
* Calculates yahrzeit.
|
|
@@ -5183,11 +8147,11 @@ class HebrewCalendar {
|
|
|
5183
8147
|
* @returns anniversary occurring in hyear
|
|
5184
8148
|
*/
|
|
5185
8149
|
static getYahrzeit(hyear, gdate) {
|
|
5186
|
-
const dt =
|
|
8150
|
+
const dt = getYahrzeitHD(hyear, gdate);
|
|
5187
8151
|
if (typeof dt === 'undefined') {
|
|
5188
8152
|
return dt;
|
|
5189
8153
|
}
|
|
5190
|
-
return new
|
|
8154
|
+
return new HDate(dt);
|
|
5191
8155
|
}
|
|
5192
8156
|
/**
|
|
5193
8157
|
* Lower-level holidays interface, which returns a `Map` of `Event`s indexed by
|
|
@@ -5221,7 +8185,7 @@ class HebrewCalendar {
|
|
|
5221
8185
|
if (date.getDay() < 3 || date.getDay() > 4) {
|
|
5222
8186
|
return false;
|
|
5223
8187
|
}
|
|
5224
|
-
const today = new
|
|
8188
|
+
const today = new HDate(date);
|
|
5225
8189
|
const friday = today.after(5);
|
|
5226
8190
|
const tomorrow = today.next();
|
|
5227
8191
|
if (!isChag(friday, il) || isChag(today, il) || !isChag(tomorrow, il)) {
|
|
@@ -5299,52 +8263,24 @@ function isChag(date, il) {
|
|
|
5299
8263
|
return chag.length !== 0;
|
|
5300
8264
|
}
|
|
5301
8265
|
|
|
5302
|
-
Object.defineProperty(exports, "HDate", {
|
|
5303
|
-
enumerable: true,
|
|
5304
|
-
get: function () { return hdate.HDate; }
|
|
5305
|
-
});
|
|
5306
|
-
Object.defineProperty(exports, "Locale", {
|
|
5307
|
-
enumerable: true,
|
|
5308
|
-
get: function () { return hdate.Locale; }
|
|
5309
|
-
});
|
|
5310
|
-
Object.defineProperty(exports, "gematriya", {
|
|
5311
|
-
enumerable: true,
|
|
5312
|
-
get: function () { return hdate.gematriya; }
|
|
5313
|
-
});
|
|
5314
|
-
Object.defineProperty(exports, "gematriyaStrToNum", {
|
|
5315
|
-
enumerable: true,
|
|
5316
|
-
get: function () { return hdate.gematriyaStrToNum; }
|
|
5317
|
-
});
|
|
5318
|
-
Object.defineProperty(exports, "greg", {
|
|
5319
|
-
enumerable: true,
|
|
5320
|
-
get: function () { return hdate.greg; }
|
|
5321
|
-
});
|
|
5322
|
-
Object.defineProperty(exports, "months", {
|
|
5323
|
-
enumerable: true,
|
|
5324
|
-
get: function () { return hdate.months; }
|
|
5325
|
-
});
|
|
5326
|
-
Object.defineProperty(exports, "GeoLocation", {
|
|
5327
|
-
enumerable: true,
|
|
5328
|
-
get: function () { return noaa.GeoLocation; }
|
|
5329
|
-
});
|
|
5330
|
-
Object.defineProperty(exports, "NOAACalculator", {
|
|
5331
|
-
enumerable: true,
|
|
5332
|
-
get: function () { return noaa.NOAACalculator; }
|
|
5333
|
-
});
|
|
5334
8266
|
exports.AsaraBTevetEvent = AsaraBTevetEvent;
|
|
5335
8267
|
exports.CandleLightingEvent = CandleLightingEvent;
|
|
5336
8268
|
exports.ChanukahEvent = ChanukahEvent;
|
|
5337
8269
|
exports.DailyLearning = DailyLearning;
|
|
5338
8270
|
exports.Event = Event;
|
|
5339
8271
|
exports.FastDayEvent = FastDayEvent;
|
|
8272
|
+
exports.GeoLocation = GeoLocation;
|
|
8273
|
+
exports.HDate = HDate;
|
|
5340
8274
|
exports.HavdalahEvent = HavdalahEvent;
|
|
5341
8275
|
exports.HebrewCalendar = HebrewCalendar;
|
|
5342
8276
|
exports.HebrewDateEvent = HebrewDateEvent;
|
|
5343
8277
|
exports.HolidayEvent = HolidayEvent;
|
|
8278
|
+
exports.Locale = Locale;
|
|
5344
8279
|
exports.Location = Location;
|
|
5345
8280
|
exports.MevarchimChodeshEvent = MevarchimChodeshEvent;
|
|
5346
8281
|
exports.Molad = Molad;
|
|
5347
8282
|
exports.MoladEvent = MoladEvent;
|
|
8283
|
+
exports.NOAACalculator = NOAACalculator;
|
|
5348
8284
|
exports.OmerEvent = OmerEvent;
|
|
5349
8285
|
exports.ParshaEvent = ParshaEvent;
|
|
5350
8286
|
exports.RoshChodeshEvent = RoshChodeshEvent;
|
|
@@ -5355,9 +8291,12 @@ exports.TimedEvent = TimedEvent;
|
|
|
5355
8291
|
exports.YomKippurKatanEvent = YomKippurKatanEvent;
|
|
5356
8292
|
exports.Zmanim = Zmanim;
|
|
5357
8293
|
exports.flags = flags;
|
|
8294
|
+
exports.gematriya = gematriya;
|
|
8295
|
+
exports.gematriyaStrToNum = gematriyaStrToNum;
|
|
5358
8296
|
exports.getHolidaysOnDate = getHolidaysOnDate;
|
|
5359
8297
|
exports.getSedra = getSedra;
|
|
5360
8298
|
exports.holidayDesc = holidayDesc;
|
|
8299
|
+
exports.months = months;
|
|
5361
8300
|
exports.parshaYear = parshaYear;
|
|
5362
8301
|
exports.parshiot = parshiot;
|
|
5363
8302
|
exports.version = version;
|