@hebcal/core 5.9.6 → 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/index.cjs +3176 -239
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,32 +1,1894 @@
|
|
|
1
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
7
|
const version = '5.9.6';
|
|
10
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
|
+
}
|
|
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,12 +6042,12 @@ 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}`;
|
|
@@ -3188,7 +6150,7 @@ class Sedra {
|
|
|
3188
6150
|
if (idx === -1) {
|
|
3189
6151
|
return null; // doesn't occur this year
|
|
3190
6152
|
}
|
|
3191
|
-
return new
|
|
6153
|
+
return new HDate(this.firstSaturday + idx * 7);
|
|
3192
6154
|
}
|
|
3193
6155
|
/**
|
|
3194
6156
|
* Returns the date that a parsha (or its doubled or undoubled counterpart)
|
|
@@ -3255,32 +6217,32 @@ class Sedra {
|
|
|
3255
6217
|
* @param hd Hebrew date or R.D. days
|
|
3256
6218
|
*/
|
|
3257
6219
|
lookup(hd) {
|
|
3258
|
-
const abs = typeof hd === 'number' ? hd :
|
|
6220
|
+
const abs = typeof hd === 'number' ? hd : HDate.isHDate(hd) ? hd.abs() : NaN;
|
|
3259
6221
|
if (isNaN(abs)) {
|
|
3260
6222
|
throw new TypeError(`Bad date argument: ${hd}`);
|
|
3261
6223
|
}
|
|
3262
6224
|
// find the first saturday on or after today's date
|
|
3263
|
-
const saturday =
|
|
6225
|
+
const saturday = HDate.dayOnOrBefore(6, abs + 6);
|
|
3264
6226
|
const weekNum = (saturday - this.firstSaturday) / 7;
|
|
3265
6227
|
const index = this.theSedraArray[weekNum];
|
|
3266
6228
|
if (typeof index === 'undefined') {
|
|
3267
6229
|
const sedra = getSedra(this.year + 1, this.il);
|
|
3268
6230
|
return sedra.lookup(saturday); // must be next year
|
|
3269
6231
|
}
|
|
3270
|
-
const hdate
|
|
6232
|
+
const hdate = new HDate(saturday);
|
|
3271
6233
|
if (typeof index === 'string') {
|
|
3272
6234
|
// Shabbat has a chag. Return a description
|
|
3273
|
-
return { parsha: [index], chag: true, hdate
|
|
6235
|
+
return { parsha: [index], chag: true, hdate };
|
|
3274
6236
|
}
|
|
3275
6237
|
if (index >= 0) {
|
|
3276
|
-
return { parsha: [parshiot[index]], chag: false, num: index + 1, hdate
|
|
6238
|
+
return { parsha: [parshiot[index]], chag: false, num: index + 1, hdate };
|
|
3277
6239
|
}
|
|
3278
6240
|
const p1 = D(index); // undouble the parsha
|
|
3279
6241
|
return {
|
|
3280
6242
|
parsha: [parshiot[p1], parshiot[p1 + 1]],
|
|
3281
6243
|
chag: false,
|
|
3282
6244
|
num: [p1 + 1, p1 + 2],
|
|
3283
|
-
hdate
|
|
6245
|
+
hdate,
|
|
3284
6246
|
};
|
|
3285
6247
|
}
|
|
3286
6248
|
}
|
|
@@ -3549,7 +6511,7 @@ class ParshaEvent extends Event {
|
|
|
3549
6511
|
return this.il ? url + '?i=on' : url;
|
|
3550
6512
|
}
|
|
3551
6513
|
urlDateSuffix() {
|
|
3552
|
-
const isoDate =
|
|
6514
|
+
const isoDate = isoDateString(this.getDate().greg());
|
|
3553
6515
|
return isoDate.replace(/-/g, '');
|
|
3554
6516
|
}
|
|
3555
6517
|
}
|
|
@@ -3564,7 +6526,7 @@ class ParshaEvent extends Event {
|
|
|
3564
6526
|
function parshaYear(year, il) {
|
|
3565
6527
|
const sedra = getSedra(year, il);
|
|
3566
6528
|
const startAbs = sedra.getFirstSaturday();
|
|
3567
|
-
const endAbs =
|
|
6529
|
+
const endAbs = HDate.hebrew2abs(year, months.ELUL, 29);
|
|
3568
6530
|
const events = [];
|
|
3569
6531
|
for (let absDt = startAbs; absDt <= endAbs; absDt += 7) {
|
|
3570
6532
|
const parsha = sedra.lookup(absDt);
|
|
@@ -3580,8 +6542,8 @@ const SUN$1 = 0;
|
|
|
3580
6542
|
const TUE$1 = 2;
|
|
3581
6543
|
const FRI$2 = 5;
|
|
3582
6544
|
const SAT$2 = 6;
|
|
3583
|
-
const NISAN$2 =
|
|
3584
|
-
const IYYAR =
|
|
6545
|
+
const NISAN$2 = months.NISAN;
|
|
6546
|
+
const IYYAR = months.IYYAR;
|
|
3585
6547
|
/**
|
|
3586
6548
|
* Yom HaShoah first observed in 1951.
|
|
3587
6549
|
* When the actual date of Yom Hashoah falls on a Friday, the
|
|
@@ -3596,12 +6558,12 @@ function dateYomHaShoah(year) {
|
|
|
3596
6558
|
if (year < 5711) {
|
|
3597
6559
|
return null;
|
|
3598
6560
|
}
|
|
3599
|
-
let nisan27dt = new
|
|
6561
|
+
let nisan27dt = new HDate(27, NISAN$2, year);
|
|
3600
6562
|
if (nisan27dt.getDay() === FRI$2) {
|
|
3601
|
-
nisan27dt = new
|
|
6563
|
+
nisan27dt = new HDate(26, NISAN$2, year);
|
|
3602
6564
|
}
|
|
3603
6565
|
else if (nisan27dt.getDay() === SUN$1) {
|
|
3604
|
-
nisan27dt = new
|
|
6566
|
+
nisan27dt = new HDate(28, NISAN$2, year);
|
|
3605
6567
|
}
|
|
3606
6568
|
return nisan27dt;
|
|
3607
6569
|
}
|
|
@@ -3615,7 +6577,7 @@ function dateYomHaZikaron(year) {
|
|
|
3615
6577
|
return null;
|
|
3616
6578
|
}
|
|
3617
6579
|
let day;
|
|
3618
|
-
const pesach = new
|
|
6580
|
+
const pesach = new HDate(15, NISAN$2, year);
|
|
3619
6581
|
const pdow = pesach.getDay();
|
|
3620
6582
|
if (pdow === SUN$1) {
|
|
3621
6583
|
day = 2;
|
|
@@ -3632,7 +6594,7 @@ function dateYomHaZikaron(year) {
|
|
|
3632
6594
|
else {
|
|
3633
6595
|
day = 4;
|
|
3634
6596
|
}
|
|
3635
|
-
return new
|
|
6597
|
+
return new HDate(day, IYYAR, year);
|
|
3636
6598
|
}
|
|
3637
6599
|
|
|
3638
6600
|
const ykk = 'Yom Kippur Katan';
|
|
@@ -3655,15 +6617,15 @@ class YomKippurKatanEvent extends HolidayEvent {
|
|
|
3655
6617
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
3656
6618
|
*/
|
|
3657
6619
|
render(locale) {
|
|
3658
|
-
const monthName0 =
|
|
6620
|
+
const monthName0 = Locale.gettext(this.nextMonthName, locale);
|
|
3659
6621
|
const monthName = monthName0.replace(/'/g, '’');
|
|
3660
|
-
return
|
|
6622
|
+
return Locale.gettext(ykk, locale) + ' ' + monthName;
|
|
3661
6623
|
}
|
|
3662
6624
|
/**
|
|
3663
6625
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
3664
6626
|
*/
|
|
3665
6627
|
renderBrief(locale) {
|
|
3666
|
-
return
|
|
6628
|
+
return Locale.gettext(ykk, locale);
|
|
3667
6629
|
}
|
|
3668
6630
|
url() {
|
|
3669
6631
|
return undefined;
|
|
@@ -3708,7 +6670,7 @@ function holidayFilter(il) {
|
|
|
3708
6670
|
* @param [il] use the Israeli schedule for holidays
|
|
3709
6671
|
*/
|
|
3710
6672
|
function getHolidaysOnDate(date, il) {
|
|
3711
|
-
const hd =
|
|
6673
|
+
const hd = HDate.isHDate(date) ? date : new HDate(date);
|
|
3712
6674
|
const hdStr = hd.toString();
|
|
3713
6675
|
const yearMap = getHolidaysForYear_(hd.getFullYear());
|
|
3714
6676
|
const events = yearMap.get(hdStr);
|
|
@@ -3734,14 +6696,14 @@ const TUE = 2;
|
|
|
3734
6696
|
const THU = 4;
|
|
3735
6697
|
const FRI$1 = 5;
|
|
3736
6698
|
const SAT$1 = 6;
|
|
3737
|
-
const NISAN$1 =
|
|
3738
|
-
const TAMUZ =
|
|
3739
|
-
const AV =
|
|
3740
|
-
const TISHREI$1 =
|
|
3741
|
-
const KISLEV =
|
|
3742
|
-
const TEVET =
|
|
3743
|
-
const ADAR_I =
|
|
3744
|
-
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;
|
|
3745
6707
|
const emojiIsraelFlag = { emoji: '🇮🇱' };
|
|
3746
6708
|
const chanukahEmoji = '🕎';
|
|
3747
6709
|
const yearCache = new QuickLRU({ maxSize: 400 });
|
|
@@ -3774,8 +6736,8 @@ function getHolidaysForYear_(year) {
|
|
|
3774
6736
|
if (cached) {
|
|
3775
6737
|
return cached;
|
|
3776
6738
|
}
|
|
3777
|
-
const RH = new
|
|
3778
|
-
const pesach = new
|
|
6739
|
+
const RH = new HDate(1, TISHREI$1, year);
|
|
6740
|
+
const pesach = new HDate(15, NISAN$1, year);
|
|
3779
6741
|
const map = new Map();
|
|
3780
6742
|
function add(...events) {
|
|
3781
6743
|
for (const ev of events) {
|
|
@@ -3795,7 +6757,7 @@ function getHolidaysForYear_(year) {
|
|
|
3795
6757
|
}
|
|
3796
6758
|
}
|
|
3797
6759
|
for (const h of staticHolidays) {
|
|
3798
|
-
const hd = new
|
|
6760
|
+
const hd = new HDate(h.dd, h.mm, year);
|
|
3799
6761
|
const ev = new HolidayEvent(hd, h.desc, h.flags);
|
|
3800
6762
|
if (h.emoji)
|
|
3801
6763
|
ev.emoji = h.emoji;
|
|
@@ -3807,39 +6769,39 @@ function getHolidaysForYear_(year) {
|
|
|
3807
6769
|
add(new RoshHashanaEvent(RH, year, CHAG | LIGHT_CANDLES_TZEIS$1));
|
|
3808
6770
|
// Variable date holidays
|
|
3809
6771
|
const tzomGedaliahDay = RH.getDay() === THU ? 4 : 3;
|
|
3810
|
-
add(new HolidayEvent(new
|
|
6772
|
+
add(new HolidayEvent(new HDate(tzomGedaliahDay, TISHREI$1, year), holidayDesc.TZOM_GEDALIAH, MINOR_FAST$1));
|
|
3811
6773
|
// first SAT after RH
|
|
3812
|
-
add(new HolidayEvent(new
|
|
3813
|
-
const rchTevet =
|
|
3814
|
-
? new
|
|
3815
|
-
: 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);
|
|
3816
6778
|
add(new HolidayEvent(rchTevet, holidayDesc.CHAG_HABANOT, MINOR_HOLIDAY$1));
|
|
3817
6779
|
// yes, we know Kislev 30-32 are wrong
|
|
3818
6780
|
// HDate() corrects the month automatically
|
|
3819
6781
|
for (let candles = 2; candles <= 8; candles++) {
|
|
3820
|
-
const hd = new
|
|
6782
|
+
const hd = new HDate(23 + candles, KISLEV, year);
|
|
3821
6783
|
add(new ChanukahEvent(hd, `Chanukah: ${candles} Candles`, MINOR_HOLIDAY$1 | CHANUKAH_CANDLES$1, {
|
|
3822
6784
|
chanukahDay: candles - 1,
|
|
3823
6785
|
emoji: chanukahEmoji + KEYCAP_DIGITS[candles],
|
|
3824
6786
|
}));
|
|
3825
6787
|
}
|
|
3826
|
-
add(new ChanukahEvent(new
|
|
3827
|
-
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));
|
|
3828
6790
|
const pesachAbs = pesach.abs();
|
|
3829
|
-
add(new HolidayEvent(new
|
|
3830
|
-
const haChodeshAbs =
|
|
3831
|
-
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(
|
|
3832
6794
|
// if the fast falls on Shabbat, move to Thursday
|
|
3833
6795
|
pesach.prev().getDay() === SAT$1
|
|
3834
6796
|
? pesach.onOrBefore(THU)
|
|
3835
|
-
: new
|
|
3836
|
-
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: '🕍' }));
|
|
3837
6799
|
if (pesach.getDay() === SUN) {
|
|
3838
|
-
add(new HolidayEvent(new
|
|
6800
|
+
add(new HolidayEvent(new HDate(16, ADAR_II, year), holidayDesc.PURIM_MESHULASH, MINOR_HOLIDAY$1));
|
|
3839
6801
|
}
|
|
3840
|
-
if (
|
|
3841
|
-
add(new HolidayEvent(new
|
|
3842
|
-
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: '🎭️' }));
|
|
3843
6805
|
}
|
|
3844
6806
|
const nisan27dt = dateYomHaShoah(year);
|
|
3845
6807
|
if (nisan27dt) {
|
|
@@ -3851,13 +6813,13 @@ function getHolidaysForYear_(year) {
|
|
|
3851
6813
|
}
|
|
3852
6814
|
for (const h of staticModernHolidays) {
|
|
3853
6815
|
if (year >= h.firstYear) {
|
|
3854
|
-
let hd = new
|
|
6816
|
+
let hd = new HDate(h.dd, h.mm, year);
|
|
3855
6817
|
const dow = hd.getDay();
|
|
3856
6818
|
if (h.friSatMovetoThu && (dow === FRI$1 || dow === SAT$1)) {
|
|
3857
6819
|
hd = hd.onOrBefore(THU);
|
|
3858
6820
|
}
|
|
3859
6821
|
else if (h.friPostponeToSun && dow === FRI$1) {
|
|
3860
|
-
hd = new
|
|
6822
|
+
hd = new HDate(hd.abs() + 2);
|
|
3861
6823
|
}
|
|
3862
6824
|
else if (h.satPostponeToSun && dow === SAT$1) {
|
|
3863
6825
|
hd = hd.next();
|
|
@@ -3870,14 +6832,14 @@ function getHolidaysForYear_(year) {
|
|
|
3870
6832
|
add(ev);
|
|
3871
6833
|
}
|
|
3872
6834
|
}
|
|
3873
|
-
let tamuz17 = new
|
|
6835
|
+
let tamuz17 = new HDate(17, TAMUZ, year);
|
|
3874
6836
|
let tamuz17attrs;
|
|
3875
6837
|
if (tamuz17.getDay() === SAT$1) {
|
|
3876
|
-
tamuz17 = new
|
|
6838
|
+
tamuz17 = new HDate(18, TAMUZ, year);
|
|
3877
6839
|
tamuz17attrs = { observed: true };
|
|
3878
6840
|
}
|
|
3879
6841
|
add(new HolidayEvent(tamuz17, holidayDesc.TZOM_TAMMUZ, MINOR_FAST$1, tamuz17attrs));
|
|
3880
|
-
let av9dt = new
|
|
6842
|
+
let av9dt = new HDate(9, AV, year);
|
|
3881
6843
|
let av9title = holidayDesc.TISHA_BAV;
|
|
3882
6844
|
let av9attrs;
|
|
3883
6845
|
if (av9dt.getDay() === SAT$1) {
|
|
@@ -3886,38 +6848,38 @@ function getHolidaysForYear_(year) {
|
|
|
3886
6848
|
av9title += ' (observed)';
|
|
3887
6849
|
}
|
|
3888
6850
|
const av9abs = av9dt.abs();
|
|
3889
|
-
add(new HolidayEvent(new
|
|
3890
|
-
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);
|
|
3891
6853
|
for (let month = 1; month <= monthsInYear; month++) {
|
|
3892
|
-
const monthName =
|
|
6854
|
+
const monthName = HDate.getMonthName(month, year);
|
|
3893
6855
|
if ((month === NISAN$1
|
|
3894
|
-
?
|
|
3895
|
-
:
|
|
3896
|
-
add(new RoshChodeshEvent(new
|
|
3897
|
-
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));
|
|
3898
6860
|
}
|
|
3899
6861
|
else if (month !== TISHREI$1) {
|
|
3900
|
-
add(new RoshChodeshEvent(new
|
|
6862
|
+
add(new RoshChodeshEvent(new HDate(1, month, year), monthName));
|
|
3901
6863
|
}
|
|
3902
6864
|
}
|
|
3903
6865
|
// Begin: Yom Kippur Katan
|
|
3904
6866
|
// start at Iyyar because one may not fast during Nisan
|
|
3905
|
-
for (let month =
|
|
6867
|
+
for (let month = months.IYYAR; month <= monthsInYear; month++) {
|
|
3906
6868
|
const nextMonth = month + 1;
|
|
3907
6869
|
// Yom Kippur Katan is not observed on the day before Rosh Hashanah.
|
|
3908
6870
|
// Not observed prior to Rosh Chodesh Cheshvan because Yom Kippur has just passed.
|
|
3909
6871
|
// Not observed before Rosh Chodesh Tevet, because that day is Hanukkah.
|
|
3910
6872
|
if (nextMonth === TISHREI$1 ||
|
|
3911
|
-
nextMonth ===
|
|
6873
|
+
nextMonth === months.CHESHVAN ||
|
|
3912
6874
|
nextMonth === TEVET) {
|
|
3913
6875
|
continue;
|
|
3914
6876
|
}
|
|
3915
|
-
let ykk = new
|
|
6877
|
+
let ykk = new HDate(29, month, year);
|
|
3916
6878
|
const dow = ykk.getDay();
|
|
3917
6879
|
if (dow === FRI$1 || dow === SAT$1) {
|
|
3918
6880
|
ykk = ykk.onOrBefore(THU);
|
|
3919
6881
|
}
|
|
3920
|
-
const nextMonthName =
|
|
6882
|
+
const nextMonthName = HDate.getMonthName(nextMonth, year);
|
|
3921
6883
|
const ev = new YomKippurKatanEvent(ykk, nextMonthName);
|
|
3922
6884
|
add(ev);
|
|
3923
6885
|
}
|
|
@@ -3927,7 +6889,7 @@ function getHolidaysForYear_(year) {
|
|
|
3927
6889
|
// Birkat Hachamah appears only once every 28 years
|
|
3928
6890
|
const birkatHaChama = getBirkatHaChama(year);
|
|
3929
6891
|
if (birkatHaChama) {
|
|
3930
|
-
const hd = new
|
|
6892
|
+
const hd = new HDate(birkatHaChama);
|
|
3931
6893
|
add(new HolidayEvent(hd, holidayDesc.BIRKAT_HACHAMAH, MINOR_HOLIDAY$1, { emoji: '☀️' }));
|
|
3932
6894
|
}
|
|
3933
6895
|
yearCache.set(year, map);
|
|
@@ -3944,10 +6906,10 @@ function getHolidaysForYear_(year) {
|
|
|
3944
6906
|
* @private
|
|
3945
6907
|
*/
|
|
3946
6908
|
function getBirkatHaChama(year) {
|
|
3947
|
-
const leap =
|
|
6909
|
+
const leap = HDate.isLeapYear(year);
|
|
3948
6910
|
const startMonth = leap ? ADAR_II : NISAN$1;
|
|
3949
6911
|
const startDay = leap ? 20 : 1;
|
|
3950
|
-
const baseRd =
|
|
6912
|
+
const baseRd = HDate.hebrew2abs(year, startMonth, startDay);
|
|
3951
6913
|
for (let day = 0; day <= 40; day++) {
|
|
3952
6914
|
const abs = baseRd + day;
|
|
3953
6915
|
const elapsed = abs + 1373429;
|
|
@@ -3964,12 +6926,12 @@ function getBirkatHaChama(year) {
|
|
|
3964
6926
|
*/
|
|
3965
6927
|
function getHolidaysForYearArray(year, il) {
|
|
3966
6928
|
const yearMap = getHolidaysForYear_(year);
|
|
3967
|
-
const startAbs =
|
|
3968
|
-
const endAbs =
|
|
6929
|
+
const startAbs = HDate.hebrew2abs(year, TISHREI$1, 1);
|
|
6930
|
+
const endAbs = HDate.hebrew2abs(year + 1, TISHREI$1, 1) - 1;
|
|
3969
6931
|
let events = [];
|
|
3970
6932
|
const myFilter = il ? observedInIsrael : observedInDiaspora;
|
|
3971
6933
|
for (let absDt = startAbs; absDt <= endAbs; absDt++) {
|
|
3972
|
-
const hd = new
|
|
6934
|
+
const hd = new HDate(absDt);
|
|
3973
6935
|
const holidays = yearMap.get(hd.toString());
|
|
3974
6936
|
if (holidays) {
|
|
3975
6937
|
const filtered = holidays.filter(myFilter);
|
|
@@ -3991,14 +6953,14 @@ class MevarchimChodeshEvent extends Event {
|
|
|
3991
6953
|
*/
|
|
3992
6954
|
constructor(date, monthName, memo, locale) {
|
|
3993
6955
|
super(date, `${mevarchimChodeshStr} ${monthName}`, flags.SHABBAT_MEVARCHIM);
|
|
3994
|
-
this.monthName =
|
|
6956
|
+
this.monthName = Locale.gettext(monthName, locale);
|
|
3995
6957
|
if (memo) {
|
|
3996
6958
|
this.memo = memo;
|
|
3997
6959
|
}
|
|
3998
6960
|
else {
|
|
3999
6961
|
const hyear = date.getFullYear();
|
|
4000
6962
|
const hmonth = date.getMonth();
|
|
4001
|
-
const monNext = hmonth ===
|
|
6963
|
+
const monNext = hmonth === HDate.monthsInYear(hyear) ? months.NISAN : hmonth + 1;
|
|
4002
6964
|
const molad = new Molad(hyear, monNext);
|
|
4003
6965
|
this.memo = molad.render('en', { hour12: false });
|
|
4004
6966
|
}
|
|
@@ -4011,9 +6973,9 @@ class MevarchimChodeshEvent extends Event {
|
|
|
4011
6973
|
* @param [locale] Optional locale name (defaults to active locale).
|
|
4012
6974
|
*/
|
|
4013
6975
|
render(locale) {
|
|
4014
|
-
const monthName0 =
|
|
6976
|
+
const monthName0 = Locale.gettext(this.monthName, locale);
|
|
4015
6977
|
const monthName = monthName0.replace(/'/g, '’');
|
|
4016
|
-
return
|
|
6978
|
+
return Locale.gettext(mevarchimChodeshStr, locale) + ' ' + monthName;
|
|
4017
6979
|
}
|
|
4018
6980
|
/**
|
|
4019
6981
|
* Returns (translated) description of this event
|
|
@@ -4088,7 +7050,7 @@ const WHOLE = 2;
|
|
|
4088
7050
|
/**
|
|
4089
7051
|
* @private
|
|
4090
7052
|
*/
|
|
4091
|
-
function hallel_(events, hdate
|
|
7053
|
+
function hallel_(events, hdate) {
|
|
4092
7054
|
const whole = events
|
|
4093
7055
|
.filter(ev => {
|
|
4094
7056
|
const desc = ev.getDesc();
|
|
@@ -4098,7 +7060,7 @@ function hallel_(events, hdate$1) {
|
|
|
4098
7060
|
return (desc.startsWith('Chanukah') ||
|
|
4099
7061
|
desc.startsWith('Shavuot') ||
|
|
4100
7062
|
desc.startsWith('Sukkot') ||
|
|
4101
|
-
(month ===
|
|
7063
|
+
(month === months.NISAN &&
|
|
4102
7064
|
(mday === 15 || mday === 16) &&
|
|
4103
7065
|
ev.getFlags() & flags.CHAG) || // Pesach
|
|
4104
7066
|
desc === "Yom HaAtzma'ut" ||
|
|
@@ -4107,7 +7069,7 @@ function hallel_(events, hdate$1) {
|
|
|
4107
7069
|
.map(ev => {
|
|
4108
7070
|
return ev.getDate().abs();
|
|
4109
7071
|
});
|
|
4110
|
-
const abs = hdate
|
|
7072
|
+
const abs = hdate.abs();
|
|
4111
7073
|
if (whole.includes(abs)) {
|
|
4112
7074
|
return WHOLE;
|
|
4113
7075
|
}
|
|
@@ -4159,14 +7121,14 @@ const NONE = {
|
|
|
4159
7121
|
function tachanun(hdate, il) {
|
|
4160
7122
|
return tachanun0(hdate, il, true);
|
|
4161
7123
|
}
|
|
4162
|
-
function tachanun0(hdate
|
|
4163
|
-
const year = hdate
|
|
7124
|
+
function tachanun0(hdate, il, checkNext) {
|
|
7125
|
+
const year = hdate.yy;
|
|
4164
7126
|
const dates = tachanunYear(year, il);
|
|
4165
|
-
const abs = hdate
|
|
7127
|
+
const abs = hdate.abs();
|
|
4166
7128
|
if (dates.none.indexOf(abs) > -1) {
|
|
4167
7129
|
return NONE;
|
|
4168
7130
|
}
|
|
4169
|
-
const dow = hdate
|
|
7131
|
+
const dow = hdate.getDay();
|
|
4170
7132
|
const ret = {
|
|
4171
7133
|
shacharit: false,
|
|
4172
7134
|
mincha: false,
|
|
@@ -4180,7 +7142,7 @@ function tachanun0(hdate$1, il, checkNext) {
|
|
|
4180
7142
|
}
|
|
4181
7143
|
const tomorrow = abs + 1;
|
|
4182
7144
|
if (checkNext && dates.yesPrev.indexOf(tomorrow) === -1) {
|
|
4183
|
-
const tmp = tachanun0(new
|
|
7145
|
+
const tmp = tachanun0(new HDate(tomorrow), il, false);
|
|
4184
7146
|
ret.mincha = tmp.shacharit;
|
|
4185
7147
|
}
|
|
4186
7148
|
else {
|
|
@@ -4192,53 +7154,53 @@ function tachanun0(hdate$1, il, checkNext) {
|
|
|
4192
7154
|
return ret;
|
|
4193
7155
|
}
|
|
4194
7156
|
function tachanunYear(year, il) {
|
|
4195
|
-
const leap =
|
|
4196
|
-
const monthsInYear =
|
|
4197
|
-
let av9dt = new
|
|
7157
|
+
const leap = HDate.isLeapYear(year);
|
|
7158
|
+
const monthsInYear = HDate.monthsInYear(year);
|
|
7159
|
+
let av9dt = new HDate(9, months.AV, year);
|
|
4198
7160
|
if (av9dt.getDay() === 6) {
|
|
4199
7161
|
av9dt = av9dt.next();
|
|
4200
7162
|
}
|
|
4201
|
-
let shushPurim = new
|
|
7163
|
+
let shushPurim = new HDate(15, months.ADAR_II, year);
|
|
4202
7164
|
if (shushPurim.getDay() === 6) {
|
|
4203
7165
|
shushPurim = shushPurim.next();
|
|
4204
7166
|
}
|
|
4205
7167
|
const none = [
|
|
4206
|
-
new
|
|
7168
|
+
new HDate(2, months.TISHREI, year), // Rosh Hashana II
|
|
4207
7169
|
].concat(
|
|
4208
7170
|
// Rosh Chodesh - 1st of every month. Also includes RH day 1 (1 Tishrei)
|
|
4209
|
-
range(1, monthsInYear).map(month => new
|
|
7171
|
+
range(1, monthsInYear).map(month => new HDate(1, month, year)),
|
|
4210
7172
|
// Rosh Chodesh - 30th of months that have one
|
|
4211
7173
|
range(1, monthsInYear)
|
|
4212
|
-
.filter(month =>
|
|
4213
|
-
.map(month => new
|
|
7174
|
+
.filter(month => HDate.daysInMonth(month, year) === 30)
|
|
7175
|
+
.map(month => new HDate(30, month, year)),
|
|
4214
7176
|
// entire month of Nisan
|
|
4215
|
-
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
|
|
4216
7178
|
// Rosh Chodesh Sivan thru Isru Chag
|
|
4217
|
-
range(1, 8 - (il ? 1 : 0)).map(mday => new
|
|
4218
|
-
new
|
|
4219
|
-
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
|
|
4220
7182
|
// Erev Yom Kippur thru Isru Chag
|
|
4221
|
-
range(9, 24 - (il ? 1 : 0)).map(mday => new
|
|
7183
|
+
range(9, 24 - (il ? 1 : 0)).map(mday => new HDate(mday, months.TISHREI, year)),
|
|
4222
7184
|
// Chanukah
|
|
4223
|
-
range(25, 33).map(mday => new
|
|
4224
|
-
new
|
|
4225
|
-
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
|
|
4226
7188
|
);
|
|
4227
7189
|
const some = [
|
|
4228
|
-
new
|
|
7190
|
+
new HDate(14, months.IYYAR, year), // Pesach Sheini
|
|
4229
7191
|
].concat(
|
|
4230
7192
|
// Until 14 Sivan
|
|
4231
|
-
range(1, 13).map(mday => new
|
|
7193
|
+
range(1, 13).map(mday => new HDate(mday, months.SIVAN, year)),
|
|
4232
7194
|
// Until after Rosh Chodesh Cheshvan
|
|
4233
|
-
range(20, 31).map(mday => new
|
|
7195
|
+
range(20, 31).map(mday => new HDate(mday, months.TISHREI, year)),
|
|
4234
7196
|
// Yom HaAtzma'ut, which changes based on day of week
|
|
4235
7197
|
year >= 5708 ? dateYomHaZikaron(year).next() : [],
|
|
4236
7198
|
// Yom Yerushalayim
|
|
4237
|
-
year >= 5727 ? new
|
|
7199
|
+
year >= 5727 ? new HDate(28, months.IYYAR, year) : []);
|
|
4238
7200
|
const yesPrev = [
|
|
4239
|
-
new
|
|
4240
|
-
new
|
|
4241
|
-
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
|
|
4242
7204
|
];
|
|
4243
7205
|
return {
|
|
4244
7206
|
none: none.map(hd => hd.abs()).sort((a, b) => a - b),
|
|
@@ -4247,7 +7209,7 @@ function tachanunYear(year, il) {
|
|
|
4247
7209
|
};
|
|
4248
7210
|
}
|
|
4249
7211
|
|
|
4250
|
-
const TISHREI =
|
|
7212
|
+
const TISHREI = months.TISHREI;
|
|
4251
7213
|
/**
|
|
4252
7214
|
* Gets the R.D. days for a number, Date, or HDate
|
|
4253
7215
|
* @private
|
|
@@ -4255,9 +7217,9 @@ const TISHREI = hdate.months.TISHREI;
|
|
|
4255
7217
|
function getAbs(d) {
|
|
4256
7218
|
if (typeof d === 'number')
|
|
4257
7219
|
return d;
|
|
4258
|
-
if (
|
|
4259
|
-
return
|
|
4260
|
-
if (
|
|
7220
|
+
if (isDate(d))
|
|
7221
|
+
return greg2abs(d);
|
|
7222
|
+
if (HDate.isHDate(d))
|
|
4261
7223
|
return d.abs();
|
|
4262
7224
|
throw new TypeError(`Invalid date type: ${d}`);
|
|
4263
7225
|
}
|
|
@@ -4266,7 +7228,7 @@ function getYear(options) {
|
|
|
4266
7228
|
return Number(options.year);
|
|
4267
7229
|
}
|
|
4268
7230
|
return options.isHebrewYear
|
|
4269
|
-
? new
|
|
7231
|
+
? new HDate().getFullYear()
|
|
4270
7232
|
: new Date().getFullYear();
|
|
4271
7233
|
}
|
|
4272
7234
|
/**
|
|
@@ -4300,7 +7262,7 @@ function getStartAndEnd(options) {
|
|
|
4300
7262
|
function getMonth(options) {
|
|
4301
7263
|
if (options.month) {
|
|
4302
7264
|
if (options.isHebrewYear) {
|
|
4303
|
-
return
|
|
7265
|
+
return HDate.monthNum(options.month);
|
|
4304
7266
|
}
|
|
4305
7267
|
else if (typeof options.month === 'number') {
|
|
4306
7268
|
return options.month;
|
|
@@ -4314,10 +7276,10 @@ function startEndGregorian(theMonth, theYear, numYears) {
|
|
|
4314
7276
|
if (theYear < 100) {
|
|
4315
7277
|
startGreg.setFullYear(theYear);
|
|
4316
7278
|
}
|
|
4317
|
-
const startAbs =
|
|
7279
|
+
const startAbs = greg2abs(startGreg);
|
|
4318
7280
|
let endAbs;
|
|
4319
7281
|
if (theMonth) {
|
|
4320
|
-
endAbs = startAbs +
|
|
7282
|
+
endAbs = startAbs + daysInGregMonth(theMonth, theYear) - 1;
|
|
4321
7283
|
}
|
|
4322
7284
|
else {
|
|
4323
7285
|
const endYear = theYear + numYears;
|
|
@@ -4325,16 +7287,16 @@ function startEndGregorian(theMonth, theYear, numYears) {
|
|
|
4325
7287
|
if (endYear < 100) {
|
|
4326
7288
|
endGreg.setFullYear(endYear);
|
|
4327
7289
|
}
|
|
4328
|
-
endAbs =
|
|
7290
|
+
endAbs = greg2abs(endGreg) - 1;
|
|
4329
7291
|
}
|
|
4330
7292
|
return [startAbs, endAbs];
|
|
4331
7293
|
}
|
|
4332
7294
|
function startEndHebrew(theMonth, theYear, numYears) {
|
|
4333
|
-
const startDate = new
|
|
7295
|
+
const startDate = new HDate(1, theMonth || TISHREI, theYear);
|
|
4334
7296
|
let startAbs = startDate.abs();
|
|
4335
7297
|
const endAbs = theMonth
|
|
4336
7298
|
? startAbs + startDate.daysInMonth()
|
|
4337
|
-
: new
|
|
7299
|
+
: new HDate(1, TISHREI, theYear + numYears).abs() - 1;
|
|
4338
7300
|
// for full Hebrew year, start on Erev Rosh Hashana which
|
|
4339
7301
|
// is technically in the previous Hebrew year
|
|
4340
7302
|
// (but conveniently lets us get candle-lighting time for Erev)
|
|
@@ -4464,13 +7426,13 @@ function calendar(options = {}) {
|
|
|
4464
7426
|
throw new TypeError(`Invalid options.locale: ${options.locale}`);
|
|
4465
7427
|
}
|
|
4466
7428
|
const locale = options.ashkenazi ? 'ashkenazi' : options.locale;
|
|
4467
|
-
const translationObj =
|
|
7429
|
+
const translationObj = Locale.useLocale(locale);
|
|
4468
7430
|
if (!translationObj) {
|
|
4469
7431
|
throw new TypeError(`Locale '${locale}' not found; did you forget to import @hebcal/locales?`);
|
|
4470
7432
|
}
|
|
4471
7433
|
}
|
|
4472
7434
|
else {
|
|
4473
|
-
|
|
7435
|
+
Locale.useLocale('en');
|
|
4474
7436
|
}
|
|
4475
7437
|
const evts = [];
|
|
4476
7438
|
let sedra;
|
|
@@ -4482,12 +7444,12 @@ function calendar(options = {}) {
|
|
|
4482
7444
|
warnUnrecognizedOptions(options);
|
|
4483
7445
|
const startAbs = startAndEnd[0];
|
|
4484
7446
|
const endAbs = startAndEnd[1];
|
|
4485
|
-
const startGreg =
|
|
7447
|
+
const startGreg = abs2greg(startAbs);
|
|
4486
7448
|
if (startGreg.getFullYear() < 100) {
|
|
4487
7449
|
options.candlelighting = false;
|
|
4488
7450
|
}
|
|
4489
7451
|
for (let abs = startAbs; abs <= endAbs; abs++) {
|
|
4490
|
-
const hd = new
|
|
7452
|
+
const hd = new HDate(abs);
|
|
4491
7453
|
const hyear = hd.getFullYear();
|
|
4492
7454
|
if (hyear !== currentYear) {
|
|
4493
7455
|
currentYear = hyear;
|
|
@@ -4496,8 +7458,8 @@ function calendar(options = {}) {
|
|
|
4496
7458
|
sedra = getSedra(currentYear, il);
|
|
4497
7459
|
}
|
|
4498
7460
|
if (options.omer) {
|
|
4499
|
-
beginOmer =
|
|
4500
|
-
endOmer =
|
|
7461
|
+
beginOmer = HDate.hebrew2abs(currentYear, NISAN, 16);
|
|
7462
|
+
endOmer = HDate.hebrew2abs(currentYear, SIVAN, 5);
|
|
4501
7463
|
}
|
|
4502
7464
|
}
|
|
4503
7465
|
const prevEventsLength = evts.length;
|
|
@@ -4518,7 +7480,7 @@ function calendar(options = {}) {
|
|
|
4518
7480
|
if (options.yizkor) {
|
|
4519
7481
|
const mm = hd.getMonth();
|
|
4520
7482
|
const dd = hd.getDate();
|
|
4521
|
-
if ((mm ===
|
|
7483
|
+
if ((mm === months.TISHREI && (dd === 10 || dd === 22)) ||
|
|
4522
7484
|
(mm === NISAN && dd === (il ? 21 : 22)) ||
|
|
4523
7485
|
(mm === SIVAN && dd === (il ? 6 : 7))) {
|
|
4524
7486
|
const linkedEvent = holidays.filter(ev => ev.observedIn(il))[0];
|
|
@@ -4579,9 +7541,9 @@ function calendar(options = {}) {
|
|
|
4579
7541
|
}
|
|
4580
7542
|
const FRI = 5;
|
|
4581
7543
|
const SAT = 6;
|
|
4582
|
-
const NISAN =
|
|
4583
|
-
const SIVAN =
|
|
4584
|
-
const ELUL =
|
|
7544
|
+
const NISAN = months.NISAN;
|
|
7545
|
+
const SIVAN = months.SIVAN;
|
|
7546
|
+
const ELUL = months.ELUL;
|
|
4585
7547
|
const LIGHT_CANDLES = flags.LIGHT_CANDLES;
|
|
4586
7548
|
const YOM_TOV_ENDS = flags.YOM_TOV_ENDS;
|
|
4587
7549
|
const CHUL_ONLY = flags.CHUL_ONLY;
|
|
@@ -4930,15 +7892,15 @@ function appendHolidayAndRelated(candlesEv, events, ev, options, isFriday, isSat
|
|
|
4930
7892
|
function makeMoladAndMevarchimChodesh(hd, options) {
|
|
4931
7893
|
const evts = [];
|
|
4932
7894
|
const hmonth = hd.getMonth();
|
|
4933
|
-
const hdate
|
|
4934
|
-
if (hmonth !== ELUL && hdate
|
|
7895
|
+
const hdate = hd.getDate();
|
|
7896
|
+
if (hmonth !== ELUL && hdate >= 23 && hdate <= 29) {
|
|
4935
7897
|
const hyear = hd.getFullYear();
|
|
4936
|
-
const monNext = hmonth ===
|
|
7898
|
+
const monNext = hmonth === HDate.monthsInYear(hyear) ? NISAN : hmonth + 1;
|
|
4937
7899
|
if (options.molad) {
|
|
4938
7900
|
evts.push(new MoladEvent(hd, hyear, monNext, options));
|
|
4939
7901
|
}
|
|
4940
7902
|
if (options.shabbatMevarchim) {
|
|
4941
|
-
const nextMonthName =
|
|
7903
|
+
const nextMonthName = HDate.getMonthName(monNext, hyear);
|
|
4942
7904
|
const molad = new Molad(hyear, monNext);
|
|
4943
7905
|
const memo = molad.render(options.locale || 'en', options);
|
|
4944
7906
|
evts.push(new MevarchimChodeshEvent(hd, nextMonthName, memo, options.locale));
|
|
@@ -5144,11 +8106,11 @@ class HebrewCalendar {
|
|
|
5144
8106
|
* @returns anniversary occurring in `hyear`
|
|
5145
8107
|
*/
|
|
5146
8108
|
static getBirthdayOrAnniversary(hyear, gdate) {
|
|
5147
|
-
const dt =
|
|
8109
|
+
const dt = getBirthdayHD(hyear, gdate);
|
|
5148
8110
|
if (typeof dt === 'undefined') {
|
|
5149
8111
|
return dt;
|
|
5150
8112
|
}
|
|
5151
|
-
return new
|
|
8113
|
+
return new HDate(dt);
|
|
5152
8114
|
}
|
|
5153
8115
|
/**
|
|
5154
8116
|
* Calculates yahrzeit.
|
|
@@ -5185,11 +8147,11 @@ class HebrewCalendar {
|
|
|
5185
8147
|
* @returns anniversary occurring in hyear
|
|
5186
8148
|
*/
|
|
5187
8149
|
static getYahrzeit(hyear, gdate) {
|
|
5188
|
-
const dt =
|
|
8150
|
+
const dt = getYahrzeitHD(hyear, gdate);
|
|
5189
8151
|
if (typeof dt === 'undefined') {
|
|
5190
8152
|
return dt;
|
|
5191
8153
|
}
|
|
5192
|
-
return new
|
|
8154
|
+
return new HDate(dt);
|
|
5193
8155
|
}
|
|
5194
8156
|
/**
|
|
5195
8157
|
* Lower-level holidays interface, which returns a `Map` of `Event`s indexed by
|
|
@@ -5223,7 +8185,7 @@ class HebrewCalendar {
|
|
|
5223
8185
|
if (date.getDay() < 3 || date.getDay() > 4) {
|
|
5224
8186
|
return false;
|
|
5225
8187
|
}
|
|
5226
|
-
const today = new
|
|
8188
|
+
const today = new HDate(date);
|
|
5227
8189
|
const friday = today.after(5);
|
|
5228
8190
|
const tomorrow = today.next();
|
|
5229
8191
|
if (!isChag(friday, il) || isChag(today, il) || !isChag(tomorrow, il)) {
|
|
@@ -5301,52 +8263,24 @@ function isChag(date, il) {
|
|
|
5301
8263
|
return chag.length !== 0;
|
|
5302
8264
|
}
|
|
5303
8265
|
|
|
5304
|
-
Object.defineProperty(exports, "HDate", {
|
|
5305
|
-
enumerable: true,
|
|
5306
|
-
get: function () { return hdate.HDate; }
|
|
5307
|
-
});
|
|
5308
|
-
Object.defineProperty(exports, "Locale", {
|
|
5309
|
-
enumerable: true,
|
|
5310
|
-
get: function () { return hdate.Locale; }
|
|
5311
|
-
});
|
|
5312
|
-
Object.defineProperty(exports, "gematriya", {
|
|
5313
|
-
enumerable: true,
|
|
5314
|
-
get: function () { return hdate.gematriya; }
|
|
5315
|
-
});
|
|
5316
|
-
Object.defineProperty(exports, "gematriyaStrToNum", {
|
|
5317
|
-
enumerable: true,
|
|
5318
|
-
get: function () { return hdate.gematriyaStrToNum; }
|
|
5319
|
-
});
|
|
5320
|
-
Object.defineProperty(exports, "greg", {
|
|
5321
|
-
enumerable: true,
|
|
5322
|
-
get: function () { return hdate.greg; }
|
|
5323
|
-
});
|
|
5324
|
-
Object.defineProperty(exports, "months", {
|
|
5325
|
-
enumerable: true,
|
|
5326
|
-
get: function () { return hdate.months; }
|
|
5327
|
-
});
|
|
5328
|
-
Object.defineProperty(exports, "GeoLocation", {
|
|
5329
|
-
enumerable: true,
|
|
5330
|
-
get: function () { return noaa.GeoLocation; }
|
|
5331
|
-
});
|
|
5332
|
-
Object.defineProperty(exports, "NOAACalculator", {
|
|
5333
|
-
enumerable: true,
|
|
5334
|
-
get: function () { return noaa.NOAACalculator; }
|
|
5335
|
-
});
|
|
5336
8266
|
exports.AsaraBTevetEvent = AsaraBTevetEvent;
|
|
5337
8267
|
exports.CandleLightingEvent = CandleLightingEvent;
|
|
5338
8268
|
exports.ChanukahEvent = ChanukahEvent;
|
|
5339
8269
|
exports.DailyLearning = DailyLearning;
|
|
5340
8270
|
exports.Event = Event;
|
|
5341
8271
|
exports.FastDayEvent = FastDayEvent;
|
|
8272
|
+
exports.GeoLocation = GeoLocation;
|
|
8273
|
+
exports.HDate = HDate;
|
|
5342
8274
|
exports.HavdalahEvent = HavdalahEvent;
|
|
5343
8275
|
exports.HebrewCalendar = HebrewCalendar;
|
|
5344
8276
|
exports.HebrewDateEvent = HebrewDateEvent;
|
|
5345
8277
|
exports.HolidayEvent = HolidayEvent;
|
|
8278
|
+
exports.Locale = Locale;
|
|
5346
8279
|
exports.Location = Location;
|
|
5347
8280
|
exports.MevarchimChodeshEvent = MevarchimChodeshEvent;
|
|
5348
8281
|
exports.Molad = Molad;
|
|
5349
8282
|
exports.MoladEvent = MoladEvent;
|
|
8283
|
+
exports.NOAACalculator = NOAACalculator;
|
|
5350
8284
|
exports.OmerEvent = OmerEvent;
|
|
5351
8285
|
exports.ParshaEvent = ParshaEvent;
|
|
5352
8286
|
exports.RoshChodeshEvent = RoshChodeshEvent;
|
|
@@ -5357,9 +8291,12 @@ exports.TimedEvent = TimedEvent;
|
|
|
5357
8291
|
exports.YomKippurKatanEvent = YomKippurKatanEvent;
|
|
5358
8292
|
exports.Zmanim = Zmanim;
|
|
5359
8293
|
exports.flags = flags;
|
|
8294
|
+
exports.gematriya = gematriya;
|
|
8295
|
+
exports.gematriyaStrToNum = gematriyaStrToNum;
|
|
5360
8296
|
exports.getHolidaysOnDate = getHolidaysOnDate;
|
|
5361
8297
|
exports.getSedra = getSedra;
|
|
5362
8298
|
exports.holidayDesc = holidayDesc;
|
|
8299
|
+
exports.months = months;
|
|
5363
8300
|
exports.parshaYear = parshaYear;
|
|
5364
8301
|
exports.parshiot = parshiot;
|
|
5365
8302
|
exports.version = version;
|