@hebcal/core 4.5.1 → 5.0.0-rc1
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/README.md +1109 -457
- package/dist/bundle.js +5124 -1331
- package/dist/bundle.min.js +2 -2
- package/dist/index.js +2216 -1525
- package/dist/index.mjs +2215 -1524
- package/hebcal.d.ts +7 -121
- package/package.json +10 -8
- package/dist/greg0.mjs +0 -159
- package/dist/hdate-bundle.js +0 -1864
- package/dist/hdate-bundle.min.js +0 -2
- package/dist/hdate.js +0 -1853
- package/dist/hdate.mjs +0 -1909
- package/dist/hdate0-bundle.js +0 -444
- package/dist/hdate0-bundle.min.js +0 -2
- package/dist/hdate0.mjs +0 -465
package/dist/index.js
CHANGED
|
@@ -1,249 +1,6 @@
|
|
|
1
|
-
/*! @hebcal/core
|
|
1
|
+
/*! @hebcal/core v5.0.0-rc1 */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
/*
|
|
5
|
-
* More minimal greg routines
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/** @private */
|
|
9
|
-
const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
10
|
-
/** @private */
|
|
11
|
-
const monthLengths = [lengths, lengths.slice()];
|
|
12
|
-
monthLengths[1][2] = 29;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @private
|
|
16
|
-
* @param {number} x
|
|
17
|
-
* @param {number} y
|
|
18
|
-
* @return {number}
|
|
19
|
-
*/
|
|
20
|
-
function mod(x, y) {
|
|
21
|
-
return x - y * Math.floor(x / y);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @private
|
|
26
|
-
* @param {number} x
|
|
27
|
-
* @param {number} y
|
|
28
|
-
* @return {number}
|
|
29
|
-
*/
|
|
30
|
-
function quotient(x, y) {
|
|
31
|
-
return Math.floor(x / y);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Returns true if the Gregorian year is a leap year
|
|
36
|
-
* @private
|
|
37
|
-
* @param {number} year Gregorian year
|
|
38
|
-
* @return {boolean}
|
|
39
|
-
*/
|
|
40
|
-
function isLeapYear$1(year) {
|
|
41
|
-
return !(year % 4) && (!!(year % 100) || !(year % 400));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Number of days in the Gregorian month for given year
|
|
46
|
-
* @private
|
|
47
|
-
* @param {number} month Gregorian month (1=January, 12=December)
|
|
48
|
-
* @param {number} year Gregorian year
|
|
49
|
-
* @return {number}
|
|
50
|
-
*/
|
|
51
|
-
function daysInMonth$1(month, year) {
|
|
52
|
-
// 1 based months
|
|
53
|
-
return monthLengths[+isLeapYear$1(year)][month];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Returns true if the object is a Javascript Date
|
|
58
|
-
* @private
|
|
59
|
-
* @param {Object} obj
|
|
60
|
-
* @return {boolean}
|
|
61
|
-
*/
|
|
62
|
-
function isDate(obj) {
|
|
63
|
-
return typeof obj === 'object' && Date.prototype === obj.__proto__;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/*
|
|
67
|
-
const ABS_14SEP1752 = 639797;
|
|
68
|
-
const ABS_2SEP1752 = 639785;
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
73
|
-
* @private
|
|
74
|
-
* @param {Date} date Gregorian date
|
|
75
|
-
* @return {number}
|
|
76
|
-
*/
|
|
77
|
-
function greg2abs(date) {
|
|
78
|
-
if (!isDate(date)) {
|
|
79
|
-
throw new TypeError(`Argument not a Date: ${date}`);
|
|
80
|
-
}
|
|
81
|
-
const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
82
|
-
/*
|
|
83
|
-
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
84
|
-
throw new RangeError(`Invalid Date: ${date}`);
|
|
85
|
-
}
|
|
86
|
-
*/
|
|
87
|
-
return abs;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @private
|
|
92
|
-
* @param {number} abs - R.D. number of days
|
|
93
|
-
* @return {number}
|
|
94
|
-
*/
|
|
95
|
-
function yearFromFixed(abs) {
|
|
96
|
-
const l0 = abs - 1;
|
|
97
|
-
const n400 = quotient(l0, 146097);
|
|
98
|
-
const d1 = mod(l0, 146097);
|
|
99
|
-
const n100 = quotient(d1, 36524);
|
|
100
|
-
const d2 = mod(d1, 36524);
|
|
101
|
-
const n4 = quotient(d2, 1461);
|
|
102
|
-
const d3 = mod(d2, 1461);
|
|
103
|
-
const n1 = quotient(d3, 365);
|
|
104
|
-
const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
105
|
-
return n100 != 4 && n1 != 4 ? year + 1 : year;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @private
|
|
110
|
-
* @param {number} year
|
|
111
|
-
* @param {number} month (1-12)
|
|
112
|
-
* @param {number} day (1-31)
|
|
113
|
-
* @return {number}
|
|
114
|
-
*/
|
|
115
|
-
function toFixed(year, month, day) {
|
|
116
|
-
const py = year - 1;
|
|
117
|
-
return 365 * py + quotient(py, 4) - quotient(py, 100) + quotient(py, 400) + quotient(367 * month - 362, 12) + (month <= 2 ? 0 : isLeapYear$1(year) ? -1 : -2) + day;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Converts from Rata Die (R.D. number) to Gregorian date.
|
|
122
|
-
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
|
|
123
|
-
* Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
|
|
124
|
-
* Clamen, Software--Practice and Experience, Volume 23, Number 4
|
|
125
|
-
* (April, 1993), pages 383-404 for an explanation.
|
|
126
|
-
* @private
|
|
127
|
-
* @param {number} abs - R.D. number of days
|
|
128
|
-
* @return {Date}
|
|
129
|
-
*/
|
|
130
|
-
function abs2greg(abs) {
|
|
131
|
-
if (typeof abs !== 'number') {
|
|
132
|
-
throw new TypeError(`Argument not a Number: ${abs}`);
|
|
133
|
-
}
|
|
134
|
-
abs = Math.trunc(abs);
|
|
135
|
-
/*
|
|
136
|
-
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
137
|
-
throw new RangeError(`Invalid Date: ${abs}`);
|
|
138
|
-
}
|
|
139
|
-
*/
|
|
140
|
-
const year = yearFromFixed(abs);
|
|
141
|
-
const priorDays = abs - toFixed(year, 1, 1);
|
|
142
|
-
const correction = abs < toFixed(year, 3, 1) ? 0 : isLeapYear$1(year) ? 1 : 2;
|
|
143
|
-
const month = quotient(12 * (priorDays + correction) + 373, 367);
|
|
144
|
-
const day = abs - toFixed(year, month, 1) + 1;
|
|
145
|
-
const dt = new Date(year, month - 1, day);
|
|
146
|
-
if (year < 100 && year >= 0) {
|
|
147
|
-
dt.setFullYear(year);
|
|
148
|
-
}
|
|
149
|
-
return dt;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/*
|
|
153
|
-
Hebcal - A Jewish Calendar Generator
|
|
154
|
-
Copyright (c) 1994-2020 Danny Sadinoff
|
|
155
|
-
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
156
|
-
|
|
157
|
-
https://github.com/hebcal/hebcal-es6
|
|
158
|
-
|
|
159
|
-
This program is free software; you can redistribute it and/or
|
|
160
|
-
modify it under the terms of the GNU General Public License
|
|
161
|
-
as published by the Free Software Foundation; either version 2
|
|
162
|
-
of the License, or (at your option) any later version.
|
|
163
|
-
|
|
164
|
-
This program is distributed in the hope that it will be useful,
|
|
165
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
166
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
167
|
-
GNU General Public License for more details.
|
|
168
|
-
|
|
169
|
-
You should have received a copy of the GNU General Public License
|
|
170
|
-
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
171
|
-
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Gregorian date helper functions.
|
|
176
|
-
*/
|
|
177
|
-
const greg = {
|
|
178
|
-
/**
|
|
179
|
-
* Long names of the Gregorian months (1='January', 12='December')
|
|
180
|
-
* @readonly
|
|
181
|
-
* @type {string[]}
|
|
182
|
-
*/
|
|
183
|
-
monthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
184
|
-
/**
|
|
185
|
-
* Returns true if the Gregorian year is a leap year
|
|
186
|
-
* @function
|
|
187
|
-
* @param {number} year Gregorian year
|
|
188
|
-
* @return {boolean}
|
|
189
|
-
*/
|
|
190
|
-
isLeapYear: isLeapYear$1,
|
|
191
|
-
/**
|
|
192
|
-
* Number of days in the Gregorian month for given year
|
|
193
|
-
* @function
|
|
194
|
-
* @param {number} month Gregorian month (1=January, 12=December)
|
|
195
|
-
* @param {number} year Gregorian year
|
|
196
|
-
* @return {number}
|
|
197
|
-
*/
|
|
198
|
-
daysInMonth: daysInMonth$1,
|
|
199
|
-
/**
|
|
200
|
-
* Returns true if the object is a Javascript Date
|
|
201
|
-
* @function
|
|
202
|
-
* @param {Object} obj
|
|
203
|
-
* @return {boolean}
|
|
204
|
-
*/
|
|
205
|
-
isDate: isDate,
|
|
206
|
-
/**
|
|
207
|
-
* Returns number of days since January 1 of that year
|
|
208
|
-
* @deprecated
|
|
209
|
-
* @param {Date} date Gregorian date
|
|
210
|
-
* @return {number}
|
|
211
|
-
*/
|
|
212
|
-
dayOfYear: function (date) {
|
|
213
|
-
if (!isDate(date)) {
|
|
214
|
-
throw new TypeError(`Argument not a Date: ${date}`);
|
|
215
|
-
}
|
|
216
|
-
const month = date.getMonth();
|
|
217
|
-
let doy = date.getDate() + 31 * month;
|
|
218
|
-
if (month > 1) {
|
|
219
|
-
// FEB
|
|
220
|
-
doy -= Math.floor((4 * (month + 1) + 23) / 10);
|
|
221
|
-
if (isLeapYear$1(date.getFullYear())) {
|
|
222
|
-
doy++;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return doy;
|
|
226
|
-
},
|
|
227
|
-
/**
|
|
228
|
-
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
229
|
-
* @function
|
|
230
|
-
* @param {Date} date Gregorian date
|
|
231
|
-
* @return {number}
|
|
232
|
-
*/
|
|
233
|
-
greg2abs: greg2abs,
|
|
234
|
-
/**
|
|
235
|
-
* Converts from Rata Die (R.D. number) to Gregorian date.
|
|
236
|
-
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
|
|
237
|
-
* Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
|
|
238
|
-
* Clamen, Software--Practice and Experience, Volume 23, Number 4
|
|
239
|
-
* (April, 1993), pages 383-404 for an explanation.
|
|
240
|
-
* @function
|
|
241
|
-
* @param {number} theDate - R.D. number of days
|
|
242
|
-
* @return {Date}
|
|
243
|
-
*/
|
|
244
|
-
abs2greg: abs2greg
|
|
245
|
-
};
|
|
246
|
-
|
|
247
4
|
const GERESH = '׳';
|
|
248
5
|
const GERSHAYIM = '״';
|
|
249
6
|
const heb2num = {
|
|
@@ -270,10 +27,10 @@ const heb2num = {
|
|
|
270
27
|
'ש': 300,
|
|
271
28
|
'ת': 400
|
|
272
29
|
};
|
|
273
|
-
const num2heb =
|
|
30
|
+
const num2heb = new Map();
|
|
274
31
|
Object.keys(heb2num).forEach(key => {
|
|
275
32
|
const val = heb2num[key];
|
|
276
|
-
num2heb
|
|
33
|
+
num2heb.set(val, key);
|
|
277
34
|
});
|
|
278
35
|
|
|
279
36
|
/**
|
|
@@ -326,19 +83,19 @@ function gematriya(number) {
|
|
|
326
83
|
if (thousands > 0 && thousands !== 5) {
|
|
327
84
|
const tdigits = num2digits(thousands);
|
|
328
85
|
for (const tdig of tdigits) {
|
|
329
|
-
str += num2heb
|
|
86
|
+
str += num2heb.get(tdig);
|
|
330
87
|
}
|
|
331
88
|
str += GERESH;
|
|
332
89
|
}
|
|
333
90
|
const digits = num2digits(num % 1000);
|
|
334
91
|
if (digits.length == 1) {
|
|
335
|
-
return str + num2heb
|
|
92
|
+
return str + num2heb.get(digits[0]) + GERESH;
|
|
336
93
|
}
|
|
337
94
|
for (let i = 0; i < digits.length; i++) {
|
|
338
95
|
if (i + 1 === digits.length) {
|
|
339
96
|
str += GERSHAYIM;
|
|
340
97
|
}
|
|
341
|
-
str += num2heb
|
|
98
|
+
str += num2heb.get(digits[i]);
|
|
342
99
|
}
|
|
343
100
|
return str;
|
|
344
101
|
}
|
|
@@ -386,7 +143,7 @@ const alias = {
|
|
|
386
143
|
};
|
|
387
144
|
|
|
388
145
|
/** @private */
|
|
389
|
-
const locales =
|
|
146
|
+
const locales = new Map();
|
|
390
147
|
/** @private */
|
|
391
148
|
let activeLocale = null;
|
|
392
149
|
/** @private */
|
|
@@ -410,7 +167,7 @@ class Locale {
|
|
|
410
167
|
*/
|
|
411
168
|
static lookupTranslation(id, locale) {
|
|
412
169
|
const locale0 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
413
|
-
const loc = typeof locale == 'string' && locales
|
|
170
|
+
const loc = typeof locale == 'string' && locales.get(locale0) || activeLocale;
|
|
414
171
|
const array = loc[id];
|
|
415
172
|
if (array && array.length && array[0].length) {
|
|
416
173
|
return array[0];
|
|
@@ -444,7 +201,7 @@ class Locale {
|
|
|
444
201
|
if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
|
|
445
202
|
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
446
203
|
}
|
|
447
|
-
locales
|
|
204
|
+
locales.set(locale.toLowerCase(), data.contexts['']);
|
|
448
205
|
}
|
|
449
206
|
|
|
450
207
|
/**
|
|
@@ -458,7 +215,7 @@ class Locale {
|
|
|
458
215
|
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
459
216
|
}
|
|
460
217
|
const locale0 = locale.toLowerCase();
|
|
461
|
-
const loc = locales
|
|
218
|
+
const loc = locales.get(locale0);
|
|
462
219
|
if (!loc) {
|
|
463
220
|
throw new TypeError(`Unknown locale: ${locale}`);
|
|
464
221
|
}
|
|
@@ -486,7 +243,7 @@ class Locale {
|
|
|
486
243
|
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
487
244
|
}
|
|
488
245
|
const locale0 = locale.toLowerCase();
|
|
489
|
-
const loc = locales
|
|
246
|
+
const loc = locales.get(locale0);
|
|
490
247
|
if (!loc) {
|
|
491
248
|
throw new TypeError(`Unknown locale: ${locale}`);
|
|
492
249
|
}
|
|
@@ -507,7 +264,7 @@ class Locale {
|
|
|
507
264
|
*/
|
|
508
265
|
static useLocale(locale) {
|
|
509
266
|
const locale0 = locale.toLowerCase();
|
|
510
|
-
const obj = locales
|
|
267
|
+
const obj = locales.get(locale0);
|
|
511
268
|
if (!obj) {
|
|
512
269
|
throw new RangeError(`Locale '${locale}' not found`);
|
|
513
270
|
}
|
|
@@ -529,7 +286,8 @@ class Locale {
|
|
|
529
286
|
* @return {string[]}
|
|
530
287
|
*/
|
|
531
288
|
static getLocaleNames() {
|
|
532
|
-
|
|
289
|
+
const keys = Array.from(locales.keys());
|
|
290
|
+
return keys.sort((a, b) => a.localeCompare(b));
|
|
533
291
|
}
|
|
534
292
|
|
|
535
293
|
/**
|
|
@@ -588,10 +346,170 @@ Locale.addLocale('s', noopLocale);
|
|
|
588
346
|
Locale.addLocale('', noopLocale);
|
|
589
347
|
Locale.useLocale('en');
|
|
590
348
|
|
|
349
|
+
/** @private */
|
|
350
|
+
const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
351
|
+
/** @private */
|
|
352
|
+
const monthLengths = [
|
|
353
|
+
lengths,
|
|
354
|
+
lengths.slice(),
|
|
355
|
+
];
|
|
356
|
+
monthLengths[1][2] = 29;
|
|
357
|
+
/**
|
|
358
|
+
* @private
|
|
359
|
+
*/
|
|
360
|
+
function mod$1(x, y) {
|
|
361
|
+
return x - y * Math.floor(x / y);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* @private
|
|
365
|
+
*/
|
|
366
|
+
function quotient(x, y) {
|
|
367
|
+
return Math.floor(x / y);
|
|
368
|
+
}
|
|
591
369
|
/*
|
|
592
|
-
|
|
370
|
+
const ABS_14SEP1752 = 639797;
|
|
371
|
+
const ABS_2SEP1752 = 639785;
|
|
372
|
+
*/
|
|
373
|
+
/**
|
|
374
|
+
* Gregorian date helper functions.
|
|
593
375
|
*/
|
|
376
|
+
var greg;
|
|
377
|
+
(function (greg) {
|
|
378
|
+
/**
|
|
379
|
+
* Long names of the Gregorian months (1='January', 12='December')
|
|
380
|
+
* @readonly
|
|
381
|
+
* @type {string[]}
|
|
382
|
+
*/
|
|
383
|
+
greg.monthNames = [
|
|
384
|
+
'',
|
|
385
|
+
'January',
|
|
386
|
+
'February',
|
|
387
|
+
'March',
|
|
388
|
+
'April',
|
|
389
|
+
'May',
|
|
390
|
+
'June',
|
|
391
|
+
'July',
|
|
392
|
+
'August',
|
|
393
|
+
'September',
|
|
394
|
+
'October',
|
|
395
|
+
'November',
|
|
396
|
+
'December',
|
|
397
|
+
];
|
|
398
|
+
/**
|
|
399
|
+
* Returns true if the Gregorian year is a leap year
|
|
400
|
+
* @param {number} year Gregorian year
|
|
401
|
+
* @return {boolean}
|
|
402
|
+
*/
|
|
403
|
+
function isLeapYear(year) {
|
|
404
|
+
return !(year % 4) && (!!(year % 100) || !(year % 400));
|
|
405
|
+
}
|
|
406
|
+
greg.isLeapYear = isLeapYear;
|
|
407
|
+
/**
|
|
408
|
+
* Number of days in the Gregorian month for given year
|
|
409
|
+
* @param {number} month Gregorian month (1=January, 12=December)
|
|
410
|
+
* @param {number} year Gregorian year
|
|
411
|
+
* @return {number}
|
|
412
|
+
*/
|
|
413
|
+
function daysInMonth(month, year) {
|
|
414
|
+
// 1 based months
|
|
415
|
+
return monthLengths[+isLeapYear(year)][month];
|
|
416
|
+
}
|
|
417
|
+
greg.daysInMonth = daysInMonth;
|
|
418
|
+
/**
|
|
419
|
+
* Returns true if the object is a Javascript Date
|
|
420
|
+
* @param {Object} obj
|
|
421
|
+
* @return {boolean}
|
|
422
|
+
*/
|
|
423
|
+
function isDate(obj) {
|
|
424
|
+
return typeof obj === 'object' && Date.prototype.isPrototypeOf(obj);
|
|
425
|
+
}
|
|
426
|
+
greg.isDate = isDate;
|
|
427
|
+
/**
|
|
428
|
+
* @private
|
|
429
|
+
* @param abs - R.D. number of days
|
|
430
|
+
*/
|
|
431
|
+
function yearFromFixed(abs) {
|
|
432
|
+
const l0 = abs - 1;
|
|
433
|
+
const n400 = quotient(l0, 146097);
|
|
434
|
+
const d1 = mod$1(l0, 146097);
|
|
435
|
+
const n100 = quotient(d1, 36524);
|
|
436
|
+
const d2 = mod$1(d1, 36524);
|
|
437
|
+
const n4 = quotient(d2, 1461);
|
|
438
|
+
const d3 = mod$1(d2, 1461);
|
|
439
|
+
const n1 = quotient(d3, 365);
|
|
440
|
+
const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
441
|
+
return n100 != 4 && n1 != 4 ? year + 1 : year;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* @private
|
|
445
|
+
* @param year
|
|
446
|
+
* @param month (1-12)
|
|
447
|
+
* @param day (1-31)
|
|
448
|
+
*/
|
|
449
|
+
function toFixed(year, month, day) {
|
|
450
|
+
const py = year - 1;
|
|
451
|
+
return 365 * py +
|
|
452
|
+
quotient(py, 4) -
|
|
453
|
+
quotient(py, 100) +
|
|
454
|
+
quotient(py, 400) +
|
|
455
|
+
quotient((367 * month - 362), 12) +
|
|
456
|
+
(month <= 2 ? 0 : (isLeapYear(year) ? -1 : -2)) +
|
|
457
|
+
day;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
461
|
+
* @param {Date} date Gregorian date
|
|
462
|
+
* @return {number}
|
|
463
|
+
*/
|
|
464
|
+
function greg2abs(date) {
|
|
465
|
+
if (!isDate(date)) {
|
|
466
|
+
throw new TypeError(`Argument not a Date: ${date}`);
|
|
467
|
+
}
|
|
468
|
+
const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
469
|
+
/*
|
|
470
|
+
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
471
|
+
throw new RangeError(`Invalid Date: ${date}`);
|
|
472
|
+
}
|
|
473
|
+
*/
|
|
474
|
+
return abs;
|
|
475
|
+
}
|
|
476
|
+
greg.greg2abs = greg2abs;
|
|
477
|
+
/**
|
|
478
|
+
* Converts from Rata Die (R.D. number) to Gregorian date.
|
|
479
|
+
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
|
|
480
|
+
* Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
|
|
481
|
+
* Clamen, Software--Practice and Experience, Volume 23, Number 4
|
|
482
|
+
* (April, 1993), pages 383-404 for an explanation.
|
|
483
|
+
* @param {number} abs - R.D. number of days
|
|
484
|
+
* @return {Date}
|
|
485
|
+
*/
|
|
486
|
+
function abs2greg(abs) {
|
|
487
|
+
if (typeof abs !== 'number') {
|
|
488
|
+
throw new TypeError(`Argument not a Number: ${abs}`);
|
|
489
|
+
}
|
|
490
|
+
abs = Math.trunc(abs);
|
|
491
|
+
/*
|
|
492
|
+
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
493
|
+
throw new RangeError(`Invalid Date: ${abs}`);
|
|
494
|
+
}
|
|
495
|
+
*/
|
|
496
|
+
const year = yearFromFixed(abs);
|
|
497
|
+
const priorDays = abs - toFixed(year, 1, 1);
|
|
498
|
+
const correction = abs < toFixed(year, 3, 1) ? 0 : (isLeapYear(year) ? 1 : 2);
|
|
499
|
+
const month = quotient((12 * (priorDays + correction) + 373), 367);
|
|
500
|
+
const day = abs - toFixed(year, month, 1) + 1;
|
|
501
|
+
const dt = new Date(year, month - 1, day);
|
|
502
|
+
if (year < 100 && year >= 0) {
|
|
503
|
+
dt.setFullYear(year);
|
|
504
|
+
}
|
|
505
|
+
return dt;
|
|
506
|
+
}
|
|
507
|
+
greg.abs2greg = abs2greg;
|
|
508
|
+
})(greg || (greg = {}));
|
|
594
509
|
|
|
510
|
+
/*
|
|
511
|
+
* More minimal HDate
|
|
512
|
+
*/
|
|
595
513
|
const NISAN$4 = 1;
|
|
596
514
|
const IYYAR$1 = 2;
|
|
597
515
|
// const SIVAN = 3;
|
|
@@ -605,296 +523,486 @@ const TEVET$2 = 10;
|
|
|
605
523
|
// const SHVAT = 11;
|
|
606
524
|
const ADAR_I$2 = 12;
|
|
607
525
|
const ADAR_II$1 = 13;
|
|
608
|
-
|
|
609
526
|
/**
|
|
610
527
|
* Hebrew months of the year (NISAN=1, TISHREI=7)
|
|
611
528
|
* @readonly
|
|
612
529
|
* @enum {number}
|
|
613
530
|
*/
|
|
614
531
|
const months = {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
532
|
+
/** Nissan / ניסן */
|
|
533
|
+
NISAN: 1,
|
|
534
|
+
/** Iyyar / אייר */
|
|
535
|
+
IYYAR: 2,
|
|
536
|
+
/** Sivan / סיון */
|
|
537
|
+
SIVAN: 3,
|
|
538
|
+
/** Tamuz (sometimes Tammuz) / תמוז */
|
|
539
|
+
TAMUZ: 4,
|
|
540
|
+
/** Av / אב */
|
|
541
|
+
AV: 5,
|
|
542
|
+
/** Elul / אלול */
|
|
543
|
+
ELUL: 6,
|
|
544
|
+
/** Tishrei / תִּשְׁרֵי */
|
|
545
|
+
TISHREI: 7,
|
|
546
|
+
/** Cheshvan / חשון */
|
|
547
|
+
CHESHVAN: 8,
|
|
548
|
+
/** Kislev / כסלו */
|
|
549
|
+
KISLEV: 9,
|
|
550
|
+
/** Tevet / טבת */
|
|
551
|
+
TEVET: 10,
|
|
552
|
+
/** Sh'vat / שבט */
|
|
553
|
+
SHVAT: 11,
|
|
554
|
+
/** Adar or Adar Rishon / אדר */
|
|
555
|
+
ADAR_I: 12,
|
|
556
|
+
/** Adar Sheini (only on leap years) / אדר ב׳ */
|
|
557
|
+
ADAR_II: 13,
|
|
641
558
|
};
|
|
642
|
-
const monthNames0 = [
|
|
643
|
-
|
|
559
|
+
const monthNames0 = [
|
|
560
|
+
'',
|
|
561
|
+
'Nisan',
|
|
562
|
+
'Iyyar',
|
|
563
|
+
'Sivan',
|
|
564
|
+
'Tamuz',
|
|
565
|
+
'Av',
|
|
566
|
+
'Elul',
|
|
567
|
+
'Tishrei',
|
|
568
|
+
'Cheshvan',
|
|
569
|
+
'Kislev',
|
|
570
|
+
'Tevet',
|
|
571
|
+
'Sh\'vat',
|
|
572
|
+
];
|
|
644
573
|
/**
|
|
645
574
|
* Transliterations of Hebrew month names.
|
|
646
575
|
* Regular years are index 0 and leap years are index 1.
|
|
647
576
|
* @private
|
|
648
577
|
*/
|
|
649
|
-
const monthNames = [
|
|
650
|
-
|
|
578
|
+
const monthNames = [
|
|
579
|
+
monthNames0.concat([
|
|
580
|
+
'Adar',
|
|
581
|
+
'Nisan',
|
|
582
|
+
]),
|
|
583
|
+
monthNames0.concat([
|
|
584
|
+
'Adar I',
|
|
585
|
+
'Adar II',
|
|
586
|
+
'Nisan',
|
|
587
|
+
]),
|
|
588
|
+
];
|
|
589
|
+
const edCache = new Map();
|
|
651
590
|
const EPOCH = -1373428;
|
|
652
591
|
// Avg year length in the cycle (19 solar years with 235 lunar months)
|
|
653
592
|
const AVG_HEBYEAR_DAYS = 365.24682220597794;
|
|
654
|
-
|
|
655
593
|
/**
|
|
656
594
|
* @private
|
|
657
|
-
* @param {any} n
|
|
658
|
-
* @param {string} name
|
|
659
595
|
*/
|
|
660
596
|
function assertNumber(n, name) {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
597
|
+
if (typeof n !== 'number' || isNaN(n)) {
|
|
598
|
+
throw new TypeError(`invalid parameter '${name}' not a number: ${n}`);
|
|
599
|
+
}
|
|
664
600
|
}
|
|
665
|
-
|
|
666
601
|
/**
|
|
667
602
|
* Converts Hebrew date to R.D. (Rata Die) fixed days.
|
|
668
603
|
* R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian
|
|
669
604
|
* Calendar.
|
|
670
|
-
* @private
|
|
671
605
|
* @param {number} year Hebrew year
|
|
672
606
|
* @param {number} month Hebrew month
|
|
673
607
|
* @param {number} day Hebrew date (1-30)
|
|
674
608
|
* @return {number}
|
|
675
609
|
*/
|
|
676
610
|
function hebrew2abs(year, month, day) {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
611
|
+
assertNumber(year, 'year');
|
|
612
|
+
assertNumber(month, 'month');
|
|
613
|
+
assertNumber(day, 'day');
|
|
614
|
+
if (year < 1) {
|
|
615
|
+
throw new RangeError(`hebrew2abs: invalid year ${year}`);
|
|
616
|
+
}
|
|
617
|
+
let tempabs = day;
|
|
618
|
+
if (month < TISHREI$2) {
|
|
619
|
+
for (let m = TISHREI$2; m <= monthsInYear(year); m++) {
|
|
620
|
+
tempabs += daysInMonth(m, year);
|
|
621
|
+
}
|
|
622
|
+
for (let m = NISAN$4; m < month; m++) {
|
|
623
|
+
tempabs += daysInMonth(m, year);
|
|
624
|
+
}
|
|
690
625
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
626
|
+
else {
|
|
627
|
+
for (let m = TISHREI$2; m < month; m++) {
|
|
628
|
+
tempabs += daysInMonth(m, year);
|
|
629
|
+
}
|
|
694
630
|
}
|
|
695
|
-
|
|
696
|
-
return EPOCH + elapsedDays(year) + tempabs - 1;
|
|
631
|
+
return EPOCH + elapsedDays(year) + tempabs - 1;
|
|
697
632
|
}
|
|
698
|
-
|
|
699
633
|
/**
|
|
700
634
|
* @private
|
|
701
|
-
* @param {number} year
|
|
702
|
-
* @return {number}
|
|
703
635
|
*/
|
|
704
636
|
function newYear(year) {
|
|
705
|
-
|
|
637
|
+
return EPOCH + elapsedDays(year);
|
|
706
638
|
}
|
|
707
|
-
|
|
708
639
|
/**
|
|
709
640
|
* Converts absolute R.D. days to Hebrew date
|
|
710
|
-
* @private
|
|
711
641
|
* @param {number} abs absolute R.D. days
|
|
712
642
|
* @return {SimpleHebrewDate}
|
|
713
643
|
*/
|
|
714
644
|
function abs2hebrew(abs) {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
yy: year,
|
|
733
|
-
mm: month,
|
|
734
|
-
dd: day
|
|
735
|
-
};
|
|
645
|
+
assertNumber(abs, 'abs');
|
|
646
|
+
abs = Math.trunc(abs);
|
|
647
|
+
if (abs <= EPOCH) {
|
|
648
|
+
throw new RangeError(`abs2hebrew: ${abs} is before epoch`);
|
|
649
|
+
}
|
|
650
|
+
// first, quickly approximate year
|
|
651
|
+
let year = Math.floor((abs - EPOCH) / AVG_HEBYEAR_DAYS);
|
|
652
|
+
while (newYear(year) <= abs) {
|
|
653
|
+
++year;
|
|
654
|
+
}
|
|
655
|
+
--year;
|
|
656
|
+
let month = abs < hebrew2abs(year, 1, 1) ? 7 : 1;
|
|
657
|
+
while (abs > hebrew2abs(year, month, daysInMonth(month, year))) {
|
|
658
|
+
++month;
|
|
659
|
+
}
|
|
660
|
+
const day = 1 + abs - hebrew2abs(year, month, 1);
|
|
661
|
+
return { yy: year, mm: month, dd: day };
|
|
736
662
|
}
|
|
737
|
-
|
|
738
663
|
/**
|
|
739
664
|
* Returns true if Hebrew year is a leap year
|
|
740
|
-
* @private
|
|
741
665
|
* @param {number} year Hebrew year
|
|
742
666
|
* @return {boolean}
|
|
743
667
|
*/
|
|
744
668
|
function isLeapYear(year) {
|
|
745
|
-
|
|
669
|
+
return (1 + year * 7) % 19 < 7;
|
|
746
670
|
}
|
|
747
|
-
|
|
748
671
|
/**
|
|
749
672
|
* Number of months in this Hebrew year (either 12 or 13 depending on leap year)
|
|
750
|
-
* @private
|
|
751
673
|
* @param {number} year Hebrew year
|
|
752
674
|
* @return {number}
|
|
753
675
|
*/
|
|
754
676
|
function monthsInYear(year) {
|
|
755
|
-
|
|
677
|
+
return 12 + +(isLeapYear(year)); // boolean is cast to 1 or 0
|
|
756
678
|
}
|
|
757
|
-
|
|
758
679
|
/**
|
|
759
680
|
* Number of days in Hebrew month in a given year (29 or 30)
|
|
760
|
-
* @private
|
|
761
681
|
* @param {number} month Hebrew month (e.g. months.TISHREI)
|
|
762
682
|
* @param {number} year Hebrew year
|
|
763
683
|
* @return {number}
|
|
764
684
|
*/
|
|
765
685
|
function daysInMonth(month, year) {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
686
|
+
switch (month) {
|
|
687
|
+
case IYYAR$1:
|
|
688
|
+
case TAMUZ$1:
|
|
689
|
+
case ELUL$2:
|
|
690
|
+
case TEVET$2:
|
|
691
|
+
case ADAR_II$1:
|
|
692
|
+
return 29;
|
|
693
|
+
}
|
|
694
|
+
if ((month === ADAR_I$2 && !isLeapYear(year)) ||
|
|
695
|
+
(month === CHESHVAN$1 && !longCheshvan(year)) ||
|
|
696
|
+
(month === KISLEV$2 && shortKislev(year))) {
|
|
697
|
+
return 29;
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
return 30;
|
|
701
|
+
}
|
|
779
702
|
}
|
|
780
|
-
|
|
781
703
|
/**
|
|
782
704
|
* Returns a transliterated string name of Hebrew month in year,
|
|
783
705
|
* for example 'Elul' or 'Cheshvan'.
|
|
784
|
-
* @private
|
|
785
706
|
* @param {number} month Hebrew month (e.g. months.TISHREI)
|
|
786
707
|
* @param {number} year Hebrew year
|
|
787
|
-
* @return {string}
|
|
788
708
|
*/
|
|
789
709
|
function getMonthName(month, year) {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
710
|
+
assertNumber(month, 'month');
|
|
711
|
+
assertNumber(year, 'year');
|
|
712
|
+
if (month < 1 || month > 14) {
|
|
713
|
+
throw new TypeError(`bad month argument ${month}`);
|
|
714
|
+
}
|
|
715
|
+
return monthNames[+isLeapYear(year)][month];
|
|
796
716
|
}
|
|
797
|
-
|
|
798
717
|
/**
|
|
799
718
|
* Days from sunday prior to start of Hebrew calendar to mean
|
|
800
719
|
* conjunction of Tishrei in Hebrew YEAR
|
|
801
|
-
* @private
|
|
802
720
|
* @param {number} year Hebrew year
|
|
803
721
|
* @return {number}
|
|
804
722
|
*/
|
|
805
723
|
function elapsedDays(year) {
|
|
806
|
-
|
|
807
|
-
|
|
724
|
+
const n = edCache.get(year);
|
|
725
|
+
if (typeof n === 'number') {
|
|
726
|
+
return n;
|
|
727
|
+
}
|
|
728
|
+
const elapsed = elapsedDays0(year);
|
|
729
|
+
edCache.set(year, elapsed);
|
|
730
|
+
return elapsed;
|
|
808
731
|
}
|
|
809
|
-
|
|
810
732
|
/**
|
|
811
733
|
* Days from sunday prior to start of Hebrew calendar to mean
|
|
812
734
|
* conjunction of Tishrei in Hebrew YEAR
|
|
813
735
|
* @private
|
|
814
|
-
* @param
|
|
815
|
-
* @return {number}
|
|
736
|
+
* @param year Hebrew year
|
|
816
737
|
*/
|
|
817
738
|
function elapsedDays0(year) {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
739
|
+
const prevYear = year - 1;
|
|
740
|
+
const mElapsed = 235 * Math.floor(prevYear / 19) + // Months in complete 19 year lunar (Metonic) cycles so far
|
|
741
|
+
12 * (prevYear % 19) + // Regular months in this cycle
|
|
742
|
+
Math.floor(((prevYear % 19) * 7 + 1) / 19); // Leap months this cycle
|
|
743
|
+
const pElapsed = 204 + 793 * (mElapsed % 1080);
|
|
744
|
+
const hElapsed = 5 +
|
|
745
|
+
12 * mElapsed +
|
|
746
|
+
793 * Math.floor(mElapsed / 1080) +
|
|
747
|
+
Math.floor(pElapsed / 1080);
|
|
748
|
+
const parts = (pElapsed % 1080) + 1080 * (hElapsed % 24);
|
|
749
|
+
const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24);
|
|
750
|
+
let altDay = day;
|
|
751
|
+
if (parts >= 19440 ||
|
|
752
|
+
(2 === day % 7 && parts >= 9924 && !isLeapYear(year)) ||
|
|
753
|
+
(1 === day % 7 && parts >= 16789 && isLeapYear(prevYear))) {
|
|
754
|
+
altDay++;
|
|
755
|
+
}
|
|
756
|
+
if (altDay % 7 === 0 || altDay % 7 === 3 || altDay % 7 === 5) {
|
|
757
|
+
return altDay + 1;
|
|
758
|
+
}
|
|
759
|
+
else {
|
|
760
|
+
return altDay;
|
|
761
|
+
}
|
|
831
762
|
}
|
|
832
|
-
|
|
833
763
|
/**
|
|
834
764
|
* Number of days in the hebrew YEAR.
|
|
835
765
|
* A common Hebrew calendar year can have a length of 353, 354 or 355 days
|
|
836
766
|
* A leap Hebrew calendar year can have a length of 383, 384 or 385 days
|
|
837
|
-
* @private
|
|
838
767
|
* @param {number} year Hebrew year
|
|
839
768
|
* @return {number}
|
|
840
769
|
*/
|
|
841
770
|
function daysInYear(year) {
|
|
842
|
-
|
|
771
|
+
return elapsedDays(year + 1) - elapsedDays(year);
|
|
843
772
|
}
|
|
844
|
-
|
|
845
773
|
/**
|
|
846
774
|
* true if Cheshvan is long in Hebrew year
|
|
847
|
-
* @private
|
|
848
775
|
* @param {number} year Hebrew year
|
|
849
776
|
* @return {boolean}
|
|
850
777
|
*/
|
|
851
778
|
function longCheshvan(year) {
|
|
852
|
-
|
|
779
|
+
return daysInYear(year) % 10 === 5;
|
|
853
780
|
}
|
|
854
|
-
|
|
855
781
|
/**
|
|
856
782
|
* true if Kislev is short in Hebrew year
|
|
857
|
-
* @private
|
|
858
783
|
* @param {number} year Hebrew year
|
|
859
784
|
* @return {boolean}
|
|
860
785
|
*/
|
|
861
786
|
function shortKislev(year) {
|
|
862
|
-
|
|
787
|
+
return daysInYear(year) % 10 === 3;
|
|
863
788
|
}
|
|
864
789
|
|
|
790
|
+
const NISAN$3 = months.NISAN;
|
|
791
|
+
const CHESHVAN = months.CHESHVAN;
|
|
792
|
+
const KISLEV$1 = months.KISLEV;
|
|
793
|
+
const TEVET$1 = months.TEVET;
|
|
794
|
+
const SHVAT = months.SHVAT;
|
|
795
|
+
const ADAR_I$1 = months.ADAR_I;
|
|
796
|
+
const ADAR_II = months.ADAR_II;
|
|
865
797
|
/**
|
|
798
|
+
* Returns true if the object is a Javascript Date
|
|
866
799
|
* @private
|
|
867
|
-
* @param {
|
|
800
|
+
* @param {Object} obj
|
|
868
801
|
*/
|
|
869
|
-
function
|
|
870
|
-
|
|
802
|
+
function isSimpleHebrewDate(obj) {
|
|
803
|
+
return typeof obj === 'object' && obj !== null &&
|
|
804
|
+
typeof obj.yy === 'number' &&
|
|
805
|
+
typeof obj.mm === 'number' &&
|
|
806
|
+
typeof obj.dd === 'number';
|
|
871
807
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
Hebcal - A Jewish Calendar Generator
|
|
875
|
-
Copyright (c) 1994-2020 Danny Sadinoff
|
|
876
|
-
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
877
|
-
|
|
878
|
-
https://github.com/hebcal/hebcal-es6
|
|
879
|
-
|
|
880
|
-
This program is free software; you can redistribute it and/or
|
|
881
|
-
modify it under the terms of the GNU General Public License
|
|
882
|
-
as published by the Free Software Foundation; either version 2
|
|
883
|
-
of the License, or (at your option) any later version.
|
|
884
|
-
|
|
885
|
-
This program is distributed in the hope that it will be useful,
|
|
886
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
887
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
888
|
-
GNU General Public License for more details.
|
|
889
|
-
|
|
890
|
-
You should have received a copy of the GNU General Public License
|
|
891
|
-
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
808
|
+
/**
|
|
809
|
+
* @private
|
|
892
810
|
*/
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
811
|
+
function toSimpleHebrewDate(obj) {
|
|
812
|
+
if (isSimpleHebrewDate(obj)) {
|
|
813
|
+
return obj;
|
|
814
|
+
}
|
|
815
|
+
else if (typeof obj === 'number') {
|
|
816
|
+
return abs2hebrew(obj);
|
|
817
|
+
}
|
|
818
|
+
else if (greg.isDate(obj)) {
|
|
819
|
+
const abs = greg.greg2abs(obj);
|
|
820
|
+
return abs2hebrew(abs);
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
throw new TypeError(`Argument not a Date: ${obj}`);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Calculates yahrzeit.
|
|
828
|
+
* `hyear` must be after original `date` of death.
|
|
829
|
+
* Returns `undefined` when requested year preceeds or is same as original year.
|
|
830
|
+
*
|
|
831
|
+
* Hebcal uses the algorithm defined in "Calendrical Calculations"
|
|
832
|
+
* by Edward M. Reingold and Nachum Dershowitz.
|
|
833
|
+
*
|
|
834
|
+
* The customary anniversary date of a death is more complicated and depends
|
|
835
|
+
* also on the character of the year in which the first anniversary occurs.
|
|
836
|
+
* There are several cases:
|
|
837
|
+
*
|
|
838
|
+
* * If the date of death is Marcheshvan 30, the anniversary in general depends
|
|
839
|
+
* on the first anniversary; if that first anniversary was not Marcheshvan 30,
|
|
840
|
+
* use the day before Kislev 1.
|
|
841
|
+
* * If the date of death is Kislev 30, the anniversary in general again depends
|
|
842
|
+
* on the first anniversary — if that was not Kislev 30, use the day before
|
|
843
|
+
* Tevet 1.
|
|
844
|
+
* * If the date of death is Adar II, the anniversary is the same day in the
|
|
845
|
+
* last month of the Hebrew year (Adar or Adar II).
|
|
846
|
+
* * If the date of death is Adar I 30, the anniversary in a Hebrew year that
|
|
847
|
+
* is not a leap year (in which Adar only has 29 days) is the last day in
|
|
848
|
+
* Shevat.
|
|
849
|
+
* * In all other cases, use the normal (that is, same month number) anniversary
|
|
850
|
+
* of the date of death. [Calendrical Calculations p. 113]
|
|
851
|
+
* @example
|
|
852
|
+
* import {getYahrzeit} from '@hebcal/hdate';
|
|
853
|
+
* const dt = new Date(2014, 2, 2); // '2014-03-02' == '30 Adar I 5774'
|
|
854
|
+
* const anniversary = getYahrzeit(5780, dt); // '2/25/2020' == '30 Sh\'vat 5780'
|
|
855
|
+
* @param {number} hyear Hebrew year
|
|
856
|
+
* @param {Date | SimpleHebrewDate | number} date Gregorian or Hebrew date of death
|
|
857
|
+
* @return {Date} anniversary occurring in `hyear`
|
|
858
|
+
*/
|
|
859
|
+
function getYahrzeit(hyear, date) {
|
|
860
|
+
const hd = getYahrzeitHD(hyear, date);
|
|
861
|
+
if (typeof hd === 'undefined') {
|
|
862
|
+
return hd;
|
|
863
|
+
}
|
|
864
|
+
return greg.abs2greg(hebrew2abs(hd.yy, hd.mm, hd.dd));
|
|
865
|
+
}
|
|
866
|
+
function getYahrzeitHD(hyear, date) {
|
|
867
|
+
let hDeath = toSimpleHebrewDate(date);
|
|
868
|
+
if (hyear <= hDeath.yy) {
|
|
869
|
+
// Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy}
|
|
870
|
+
return undefined;
|
|
871
|
+
}
|
|
872
|
+
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hDeath.yy + 1)) {
|
|
873
|
+
// If it's Heshvan 30 it depends on the first anniversary;
|
|
874
|
+
// if that was not Heshvan 30, use the day before Kislev 1.
|
|
875
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV$1, 1) - 1);
|
|
876
|
+
}
|
|
877
|
+
else if (hDeath.mm == KISLEV$1 && hDeath.dd == 30 && shortKislev(hDeath.yy + 1)) {
|
|
878
|
+
// If it's Kislev 30 it depends on the first anniversary;
|
|
879
|
+
// if that was not Kislev 30, use the day before Teveth 1.
|
|
880
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, TEVET$1, 1) - 1);
|
|
881
|
+
}
|
|
882
|
+
else if (hDeath.mm == ADAR_II) {
|
|
883
|
+
// If it's Adar II, use the same day in last month of year (Adar or Adar II).
|
|
884
|
+
hDeath.mm = monthsInYear(hyear);
|
|
885
|
+
}
|
|
886
|
+
else if (hDeath.mm == ADAR_I$1 && hDeath.dd == 30 && !isLeapYear(hyear)) {
|
|
887
|
+
// If it's the 30th in Adar I and year is not a leap year
|
|
888
|
+
// (so Adar has only 29 days), use the last day in Shevat.
|
|
889
|
+
hDeath.dd = 30;
|
|
890
|
+
hDeath.mm = SHVAT;
|
|
891
|
+
}
|
|
892
|
+
// In all other cases, use the normal anniversary of the date of death.
|
|
893
|
+
// advance day to rosh chodesh if needed
|
|
894
|
+
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hyear)) {
|
|
895
|
+
hDeath.mm = KISLEV$1;
|
|
896
|
+
hDeath.dd = 1;
|
|
897
|
+
}
|
|
898
|
+
else if (hDeath.mm == KISLEV$1 && hDeath.dd == 30 && shortKislev(hyear)) {
|
|
899
|
+
hDeath.mm = TEVET$1;
|
|
900
|
+
hDeath.dd = 1;
|
|
901
|
+
}
|
|
902
|
+
hDeath.yy = hyear;
|
|
903
|
+
return hDeath;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Calculates a birthday or anniversary (non-yahrzeit).
|
|
907
|
+
* `hyear` must be after original `date` of anniversary.
|
|
908
|
+
* Returns `undefined` when requested year preceeds or is same as original year.
|
|
909
|
+
*
|
|
910
|
+
* Hebcal uses the algorithm defined in "Calendrical Calculations"
|
|
911
|
+
* by Edward M. Reingold and Nachum Dershowitz.
|
|
912
|
+
*
|
|
913
|
+
* The birthday of someone born in Adar of an ordinary year or Adar II of
|
|
914
|
+
* a leap year is also always in the last month of the year, be that Adar
|
|
915
|
+
* or Adar II. The birthday in an ordinary year of someone born during the
|
|
916
|
+
* first 29 days of Adar I in a leap year is on the corresponding day of Adar;
|
|
917
|
+
* in a leap year, the birthday occurs in Adar I, as expected.
|
|
918
|
+
*
|
|
919
|
+
* Someone born on the thirtieth day of Marcheshvan, Kislev, or Adar I
|
|
920
|
+
* has his birthday postponed until the first of the following month in
|
|
921
|
+
* years where that day does not occur. [Calendrical Calculations p. 111]
|
|
922
|
+
* @example
|
|
923
|
+
* import {getBirthdayOrAnniversary} from '@hebcal/hdate';
|
|
924
|
+
* const dt = new Date(2014, 2, 2); // '2014-03-02' == '30 Adar I 5774'
|
|
925
|
+
* const anniversary = getBirthdayOrAnniversary(5780, dt); // '3/26/2020' == '1 Nisan 5780'
|
|
926
|
+
* @param {number} hyear Hebrew year
|
|
927
|
+
* @param {Date | SimpleHebrewDate | number} date Gregorian or Hebrew date of event
|
|
928
|
+
* @return {Date} anniversary occurring in `hyear`
|
|
929
|
+
*/
|
|
930
|
+
function getBirthdayOrAnniversary(hyear, date) {
|
|
931
|
+
const hd = getBirthdayHD(hyear, date);
|
|
932
|
+
if (typeof hd === 'undefined') {
|
|
933
|
+
return hd;
|
|
934
|
+
}
|
|
935
|
+
return greg.abs2greg(hebrew2abs(hd.yy, hd.mm, hd.dd));
|
|
936
|
+
}
|
|
937
|
+
function getBirthdayHD(hyear, date) {
|
|
938
|
+
const orig = toSimpleHebrewDate(date);
|
|
939
|
+
const origYear = orig.yy;
|
|
940
|
+
if (hyear === origYear) {
|
|
941
|
+
return orig;
|
|
942
|
+
}
|
|
943
|
+
else if (hyear < origYear) {
|
|
944
|
+
// Hebrew year ${hyear} occurs on or before original date in ${origYear}
|
|
945
|
+
return undefined;
|
|
946
|
+
}
|
|
947
|
+
const isOrigLeap = isLeapYear(origYear);
|
|
948
|
+
let month = orig.mm;
|
|
949
|
+
let day = orig.dd;
|
|
950
|
+
if ((month == ADAR_I$1 && !isOrigLeap) || (month == ADAR_II && isOrigLeap)) {
|
|
951
|
+
month = monthsInYear(hyear);
|
|
952
|
+
}
|
|
953
|
+
else if (month == CHESHVAN && day == 30 && !longCheshvan(hyear)) {
|
|
954
|
+
month = KISLEV$1;
|
|
955
|
+
day = 1;
|
|
956
|
+
}
|
|
957
|
+
else if (month == KISLEV$1 && day == 30 && shortKislev(hyear)) {
|
|
958
|
+
month = TEVET$1;
|
|
959
|
+
day = 1;
|
|
960
|
+
}
|
|
961
|
+
else if (month == ADAR_I$1 && day == 30 && isOrigLeap && !isLeapYear(hyear)) {
|
|
962
|
+
month = NISAN$3;
|
|
963
|
+
day = 1;
|
|
964
|
+
}
|
|
965
|
+
return { yy: hyear, mm: month, dd: day };
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* @private
|
|
970
|
+
* @param {string} msg
|
|
971
|
+
*/
|
|
972
|
+
function throwTypeError(msg) {
|
|
973
|
+
throw new TypeError(msg);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/*
|
|
977
|
+
Hebcal - A Jewish Calendar Generator
|
|
978
|
+
Copyright (c) 1994-2020 Danny Sadinoff
|
|
979
|
+
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
980
|
+
|
|
981
|
+
https://github.com/hebcal/hebcal-es6
|
|
982
|
+
|
|
983
|
+
This program is free software; you can redistribute it and/or
|
|
984
|
+
modify it under the terms of the GNU General Public License
|
|
985
|
+
as published by the Free Software Foundation; either version 2
|
|
986
|
+
of the License, or (at your option) any later version.
|
|
987
|
+
|
|
988
|
+
This program is distributed in the hope that it will be useful,
|
|
989
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
990
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
991
|
+
GNU General Public License for more details.
|
|
992
|
+
|
|
993
|
+
You should have received a copy of the GNU General Public License
|
|
994
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
995
|
+
*/
|
|
996
|
+
|
|
997
|
+
// eslint-disable-next-line require-jsdoc
|
|
998
|
+
function mod(x, y) {
|
|
999
|
+
return x - y * Math.floor(x / y);
|
|
1000
|
+
}
|
|
1001
|
+
const UNITS_DAY = 'day';
|
|
1002
|
+
const UNITS_WEEK = 'week';
|
|
1003
|
+
const UNITS_MONTH = 'month';
|
|
1004
|
+
const UNITS_YEAR = 'year';
|
|
1005
|
+
const UNITS_SINGLE = {
|
|
898
1006
|
d: UNITS_DAY,
|
|
899
1007
|
w: UNITS_WEEK,
|
|
900
1008
|
M: UNITS_MONTH,
|
|
@@ -980,7 +1088,7 @@ class HDate {
|
|
|
980
1088
|
day = new Date();
|
|
981
1089
|
}
|
|
982
1090
|
// 1 argument
|
|
983
|
-
const abs0 = typeof day === 'number' && !isNaN(day) ? day : isDate(day) ? greg2abs(day) : HDate.isHDate(day) ? {
|
|
1091
|
+
const abs0 = typeof day === 'number' && !isNaN(day) ? day : greg.isDate(day) ? greg.greg2abs(day) : HDate.isHDate(day) ? {
|
|
984
1092
|
dd: day.day,
|
|
985
1093
|
mm: day.month,
|
|
986
1094
|
yy: day.year
|
|
@@ -1069,19 +1177,6 @@ class HDate {
|
|
|
1069
1177
|
return mod(this.abs(), 7);
|
|
1070
1178
|
}
|
|
1071
1179
|
|
|
1072
|
-
/**
|
|
1073
|
-
* Sets the year of the date. Returns the object it was called upon.
|
|
1074
|
-
* @private
|
|
1075
|
-
* @deprecated
|
|
1076
|
-
* @param {number} year
|
|
1077
|
-
* @return {HDate}
|
|
1078
|
-
*/
|
|
1079
|
-
setFullYear(year) {
|
|
1080
|
-
this.year = year;
|
|
1081
|
-
fix(this);
|
|
1082
|
-
return this;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
1180
|
/**
|
|
1086
1181
|
* Sets the day of the month of the date. Returns the object it was called upon
|
|
1087
1182
|
* @private
|
|
@@ -1110,7 +1205,7 @@ class HDate {
|
|
|
1110
1205
|
* @return {Date}
|
|
1111
1206
|
*/
|
|
1112
1207
|
greg() {
|
|
1113
|
-
return abs2greg(this.abs());
|
|
1208
|
+
return greg.abs2greg(this.abs());
|
|
1114
1209
|
}
|
|
1115
1210
|
|
|
1116
1211
|
/**
|
|
@@ -1925,14 +2020,6 @@ class Event {
|
|
|
1925
2020
|
observedIn(il) {
|
|
1926
2021
|
return il ? this.observedInIsrael() : this.observedInDiaspora();
|
|
1927
2022
|
}
|
|
1928
|
-
/**
|
|
1929
|
-
* @deprecated
|
|
1930
|
-
* Optional additional event attributes (e.g. `eventTimeStr`, `cholHaMoedDay`)
|
|
1931
|
-
* @return {Object}
|
|
1932
|
-
*/
|
|
1933
|
-
getAttrs() {
|
|
1934
|
-
return this;
|
|
1935
|
-
}
|
|
1936
2023
|
/**
|
|
1937
2024
|
* Makes a clone of this Event object
|
|
1938
2025
|
* @return {Event}
|
|
@@ -2025,372 +2112,1422 @@ class HebrewDateEvent extends Event {
|
|
|
2025
2112
|
return hd.render(locale0, false);
|
|
2026
2113
|
}
|
|
2027
2114
|
}
|
|
2028
|
-
/**
|
|
2029
|
-
* Helper function to render a Hebrew date
|
|
2030
|
-
* @deprecated
|
|
2031
|
-
* @param {number} day
|
|
2032
|
-
* @param {string} monthName
|
|
2033
|
-
* @param {number} fullYear
|
|
2034
|
-
* @return {string}
|
|
2035
|
-
*/
|
|
2036
|
-
static renderHebrew(day, monthName, fullYear) {
|
|
2037
|
-
return gematriya(day) + ' ' + monthName + ' ' + gematriya(fullYear);
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
|
-
class Sun {
|
|
2042
|
-
constructor(date, latitude, longitude) {
|
|
2043
|
-
this.date = date;
|
|
2044
|
-
this.latitude = latitude;
|
|
2045
|
-
this.longitude = longitude;
|
|
2046
|
-
|
|
2047
|
-
this.julianDate = getJD(date);
|
|
2048
|
-
}
|
|
2049
|
-
|
|
2050
|
-
get solarNoon() {
|
|
2051
|
-
return calcSolNoon(this.julianDate, this.longitude, this.date);
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
timeAtAngle(angle, rising) {
|
|
2055
|
-
return calcSunriseSet(rising, angle, this.julianDate, this.date, this.latitude, this.longitude);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
function formatDate(date, minutes) {
|
|
2060
|
-
const seconds = (minutes - Math.floor(minutes)) * 60;
|
|
2061
|
-
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), 0, minutes, seconds));
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
function calcTimeJulianCent(jd) {
|
|
2065
|
-
const T = (jd - 2451545.0) / 36525.0;
|
|
2066
|
-
return T;
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
function radToDeg(angleRad) {
|
|
2070
|
-
return (180.0 * angleRad / Math.PI);
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
function degToRad(angleDeg) {
|
|
2074
|
-
return (Math.PI * angleDeg / 180.0);
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
function calcGeomMeanLongSun(t) {
|
|
2078
|
-
let L0 = 280.46646 + t * (36000.76983 + t * (0.0003032));
|
|
2079
|
-
while (L0 > 360.0) {
|
|
2080
|
-
L0 -= 360.0;
|
|
2081
|
-
}
|
|
2082
|
-
while (L0 < 0.0) {
|
|
2083
|
-
L0 += 360.0;
|
|
2084
|
-
}
|
|
2085
|
-
return L0; // in degrees
|
|
2086
|
-
}
|
|
2087
|
-
|
|
2088
|
-
function calcGeomMeanAnomalySun(t) {
|
|
2089
|
-
const M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
|
|
2090
|
-
return M; // in degrees
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
function calcEccentricityEarthOrbit(t) {
|
|
2094
|
-
const e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
|
|
2095
|
-
return e; // unitless
|
|
2096
|
-
}
|
|
2097
|
-
|
|
2098
|
-
function calcSunEqOfCenter(t) {
|
|
2099
|
-
const m = calcGeomMeanAnomalySun(t);
|
|
2100
|
-
const mrad = degToRad(m);
|
|
2101
|
-
const sinm = Math.sin(mrad);
|
|
2102
|
-
const sin2m = Math.sin(mrad + mrad);
|
|
2103
|
-
const sin3m = Math.sin(mrad + mrad + mrad);
|
|
2104
|
-
const C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289;
|
|
2105
|
-
return C; // in degrees
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
function calcSunTrueLong(t) {
|
|
2109
|
-
const l0 = calcGeomMeanLongSun(t);
|
|
2110
|
-
const c = calcSunEqOfCenter(t);
|
|
2111
|
-
const O = l0 + c;
|
|
2112
|
-
return O; // in degrees
|
|
2113
2115
|
}
|
|
2114
2116
|
|
|
2115
|
-
function calcSunApparentLong(t) {
|
|
2116
|
-
const o = calcSunTrueLong(t);
|
|
2117
|
-
const omega = 125.04 - 1934.136 * t;
|
|
2118
|
-
const lambda = o - 0.00569 - 0.00478 * Math.sin(degToRad(omega));
|
|
2119
|
-
return lambda; // in degrees
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
function calcMeanObliquityOfEcliptic(t) {
|
|
2123
|
-
const seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * (0.001813)));
|
|
2124
|
-
const e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0;
|
|
2125
|
-
return e0; // in degrees
|
|
2126
|
-
}
|
|
2127
|
-
|
|
2128
|
-
function calcObliquityCorrection(t) {
|
|
2129
|
-
const e0 = calcMeanObliquityOfEcliptic(t);
|
|
2130
|
-
const omega = 125.04 - 1934.136 * t;
|
|
2131
|
-
const e = e0 + 0.00256 * Math.cos(degToRad(omega));
|
|
2132
|
-
return e; // in degrees
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
|
-
function calcSunDeclination(t) {
|
|
2136
|
-
const e = calcObliquityCorrection(t);
|
|
2137
|
-
const lambda = calcSunApparentLong(t);
|
|
2138
|
-
|
|
2139
|
-
const sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda));
|
|
2140
|
-
const theta = radToDeg(Math.asin(sint));
|
|
2141
|
-
return theta; // in degrees
|
|
2142
|
-
}
|
|
2117
|
+
const n=36e11,t=864e11,e=[1,1e3,1e6,1e9,6e10,n,t],o=[9,6,3];function r(n){return n<=6}function i(n){return n>=6}const s$1=a("overflow",{constrain:0,reject:1},0);function a(n,t,e){const o=function(n,t,e){return (o,r)=>{if(void 0===o){const t=null!=r?r:e;if(void 0===t)throw new RangeError(`Must specify a ${n}`);return t}if(void 0===t[o])throw new RangeError(`Invalid ${n}: ${o}`);return t[o]}}(n,t,e);return (t,e)=>{const r=d(t);return o(r[n],e)}}function c(n,t,e,o){if(void 0===n)return t;if(!Number.isFinite(n))throw new RangeError("Number must be finite");n=Math.trunc(n);const r=Math.min(Math.max(n,t),e);if(r!==n&&1===o)throw new RangeError("Invalid overflowed value "+n);return r}function u(n,t){const e={};for(const o in t)void 0!==n[o]&&(e[o]=t[o](n[o]));return e}function d(n,t){if(void 0===n&&!t)return {};if(!h(n))throw TypeError("options must be an object or undefined");return n}const l=/object|function/;function h(n){return null!==n&&l.test(typeof n)}const f=a("roundingMode",{halfExpand:Math.round,ceil:Math.ceil,trunc:Math.trunc,floor:Math.floor});function m(){const n=new WeakMap;return [n.get.bind(n),n.set.bind(n)]}function g(n,t){Object.defineProperties(n.prototype,y(t,(n=>({get:n}))));}function y(n,t){const e={};for(const o in n)e[o]=t(n[o],o);return e}function w(n,t,e){const o={};for(const r of t)o[r]=e(n[r]);return o}function p(n,t){const e={};return n.forEach(((n,o)=>{e[n]=t(n,o);})),e}const v=["nanosecond","microsecond","millisecond","second","minute","hour"],M=[...v,"day","week","month","year"],b=M.map((n=>n+"s")),S=p(M,((n,t)=>t)),I=p(b,((n,t)=>t));function F(n,t,e,o){var r;let i;if(void 0===n){if(void 0===t)throw new RangeError("Unit is required");i=t;}else if(i=null!=(r=S[n])?r:I[n],void 0===i||i<e||i>o)throw new RangeError("Invalid unit "+n);return i}function O(n,t,o,r,i,s){var a;const c=d(n),u=null!=(a=c.roundingIncrement)?a:1,l=F(c.smallestUnit,o,r,i),h=f(c,s?Math.round:Math.trunc);let m=c.largestUnit;"auto"===m&&(m=void 0);const g=F(m,t=Math.max(t,l),r,i);if(l>g)throw new RangeError("Bad smallestUnit/largestUnit");if(l<6){const n=e[l+1],t=e[l]*u;if(n===t)throw new RangeError("Must not equal larger unit");if(n%t)throw new RangeError("Must divide into larger unit")}return {smallestUnit:l,largestUnit:g,roundingFunc:h,roundingIncrement:u}}function T(n,o,r,i){var s;const a=d("string"==typeof n?{smallestUnit:n}:n,!0),c=null!=(s=a.roundingIncrement)?s:1,u=F(a.smallestUnit,void 0,o,r),l=f(a,Math.round),h=e[u]*c;if(6===u){if(1!==c)throw new RangeError("When smallestUnit is days, roundingIncrement must be 1")}else {const n=i?t:e[u+1];if(!i&&n===h)throw new RangeError("Must not equal larger unit");if(n%h)throw new RangeError("Must divide into larger unit")}return {smallestUnit:u,roundingFunc:l,incNano:h}}const D$1=Symbol();function N(n,t,...e){return t instanceof n?t:n.from(t,...e)}class Y{toJSON(){return this.toString()}}class E extends Y{valueOf(){throw new Error("Cannot convert object using valueOf")}}const[Z,C]=m();class U extends E{constructor(n){super(),C(this,Object.freeze(n));}getISOFields(){return Z(this)}}function P(n,t){return n<t?-1:n>t?1:0}function R(n){return P(n,0)}function k(n,t,e){return e(n/t)*t}function x(n){return k(n,6e10,j)}function j(n){return Math.round(Math.abs(n))*R(n)}function q(n,t,e){const o=n.div(t).mult(t),r=n.sub(o).toNumber();return o.add(e(r/t)*t)}function H(n,t){return (n%t+t)%t}function L(n,t){return $(e=String(n),t,"0")+e;var e;}function B(n,t,e){return n+$(n,t,e)}function $(n,t,e){return new Array(Math.max(0,t-n.length+1)).join(e)}function A(n){return n<0?"-":"+"}const z=Math.pow(10,8);class W{constructor(n,t){this.high=n,this.low=t;}sign(){return R(this.high)||R(this.low)}neg(){return new W(-this.high||0,-this.low||0)}abs(){return this.sign()<0?this.neg():this}add(n){const[t,e]=J(n);return Q(this.high+t,this.low+e)}sub(n){const[t,e]=J(n);return Q(this.high-t,this.low-e)}mult(n){return Q(this.high*n,this.low*n)}div(n){const t=this.high/n;let e=String(t);-1!==e.indexOf("e-")&&(e=t.toFixed(20));const o=e.indexOf(".");let r=0;if(-1!==o){let n=e.substr(o+1);n=B(n,8,"0"),n=n.substr(0,8),r=parseInt(n)*(R(t)||1);}return Q(Math.trunc(t)||0,Math.trunc(this.low/n)+r)}toNumber(){return this.high*z+this.low}toBigInt(){return BigInt(this.high)*BigInt(z)+BigInt(this.low)}}function K(n,t){let e,o;if(n instanceof W)e=n.high,o=n.low;else if("number"==typeof n){if(t)throw new TypeError("Must supply bigint, not number");e=Math.trunc(n/z),o=n%z||0;}else if("bigint"==typeof n){const t=BigInt(z);e=Number(n/t),o=Number(n%t||0);}else {if("string"!=typeof n)throw new Error("Invalid type of BigNano");{if((n=n.trim()).match(/\D/))throw new SyntaxError(`Cannot parse ${n} to a BigInt`);const t=n.length-8;e=Number(n.substr(t)),o=Number(n.substr(0,t));}}return new W(e,o)}function G(n,t){return P(n.high,t.high)||P(n.low,t.low)}function J(n){return "number"==typeof n?[0,n]:[n.high,n.low]}function Q(n,t){let e=t%z||0,o=n+Math.trunc(t/z);const r=R(o),i=R(e);return i&&r&&i!==r&&(o+=i,e-=z*i),new W(o,e)}const V=b.concat("sign");function X(n){return w(n,V,(n=>-n||0))}function _(n,t){var e,o,r,i,s,a,c,u,d,l;return nn({years:null!=(e=t.years)?e:n.years,months:null!=(o=t.months)?o:n.months,weeks:null!=(r=t.weeks)?r:n.weeks,days:null!=(i=t.days)?i:n.days,hours:null!=(s=t.hours)?s:n.hours,minutes:null!=(a=t.minutes)?a:n.minutes,seconds:null!=(c=t.seconds)?c:n.seconds,milliseconds:null!=(u=t.milliseconds)?u:n.milliseconds,microseconds:null!=(d=t.microseconds)?d:n.microseconds,nanoseconds:null!=(l=t.nanoseconds)?l:n.nanoseconds})}function nn(n){return {...n,sign:tn(n)}}function tn(n){let t=0;for(const e of b){if(n[e]){t=R(n[e]);break}}return t}function en(n){let t=9;for(;t>0&&!n[b[t]];)t--;return t}const on={isoHour:0,isoMinute:0,isoSecond:0,isoMillisecond:0,isoMicrosecond:0,isoNanosecond:0},rn={hours:0,minutes:0,seconds:0,milliseconds:0,microseconds:0,nanoseconds:0};function sn(n){return {isoHour:n.hour||0,isoMinute:n.minute||0,isoSecond:n.second||0,isoMillisecond:n.millisecond||0,isoMicrosecond:n.microsecond||0,isoNanosecond:n.nanosecond||0}}function an(n){return K(t).mult(n.days).add(cn(n))}function cn(t){return K(t.nanoseconds).add(K(t.microseconds).mult(1e3)).add(K(t.milliseconds).mult(1e6)).add(K(t.seconds).mult(1e9)).add(K(t.minutes).mult(6e10)).add(K(t.hours).mult(n))}function un(t){return t.isoHour*n+6e10*t.isoMinute+1e9*t.isoSecond+1e6*t.isoMillisecond+1e3*t.isoMicrosecond+t.isoNanosecond}function dn(e,o){let r,i=0,s=0,a=0,c=0,u=0,d=0;switch(o){case 6:r=e.div(t),i=r.toNumber(),e=e.sub(r.mult(t));case 5:r=e.div(n),s=r.toNumber(),e=e.sub(r.mult(n));case 4:r=e.div(6e10),a=r.toNumber(),e=e.sub(r.mult(6e10));case 3:r=e.div(1e9),c=r.toNumber(),e=e.sub(r.mult(1e9));case 2:r=e.div(1e6),u=r.toNumber(),e=e.sub(r.mult(1e6));case 1:r=e.div(1e3),d=r.toNumber(),e=e.sub(r.mult(1e3));}return nn({years:0,months:0,weeks:0,days:i,hours:s,minutes:a,seconds:c,milliseconds:u,microseconds:d,nanoseconds:e.toNumber()})}function ln(e){const o=Math.floor(e/t);e-=o*t;const r=Math.floor(e/n);e-=r*n;const i=Math.floor(e/6e10);e-=6e10*i;const s=Math.floor(e/1e9);e-=1e9*s;const a=Math.floor(e/1e6);e-=1e6*a;const c=Math.floor(e/1e3);return [{isoHour:r,isoMinute:i,isoSecond:s,isoMillisecond:a,isoMicrosecond:c,isoNanosecond:e-=1e3*c},o]}const hn={gregory:{bce:-1,ce:0},ethioaa:{era0:0},ethiopic:{era0:0,era1:5500},coptic:{era0:-1,era1:0},roc:{beforeroc:-1,minguo:0},buddhist:{be:0},islamic:{ah:0},indian:{saka:0},persian:{ap:0},japanese:{bce:-1,ce:0,meiji:1867,taisho:1911,showa:1925,heisei:1988,reiwa:2018}};class fn{constructor(n){this.id=n;}monthCode(n,t){return "M"+L(n,2)}convertMonthCode(n,t){const e=/L$/.test(n),o=parseInt(n.substr(1));if(e)throw new RangeError("Calendar system doesnt support leap months");return [o,!1]}}function mn(n,t,e,o){var r;let i=null==(r=hn[gn(n)])?void 0:r[e];if(void 0===i){if(!o)throw new Error("Unkown era "+e);i=0;}return (i+t)*(R(i)||1)}function gn(n){return n.split("-")[0]}class yn extends fn{computeFields(n){const t=Fn(n);return {era:void 0,eraYear:void 0,year:t.isoYear,month:t.isoMonth,day:t.isoDay}}epochMilliseconds(n,t,e){return Sn(n,t,e)}daysInMonth(n,t){return 2===t?this.inLeapYear(n)?29:28:4===t||6===t||9===t||11===t?30:31}monthsInYear(){return 12}inLeapYear(n){return n%4==0&&(n%100!=0||n%400==0)}guessYearForMonthDay(){return pn}normalizeISOYearForMonthDay(){return pn}}const wn=new yn("iso8601"),pn=1972,vn=Symbol();function Mn(n){return bn(n.isoYear,n.isoMonth,n.isoDay,n.isoHour,n.isoMinute,n.isoSecond,n.isoMillisecond,n.isoMicrosecond,n.isoNanosecond)}function bn(n,t,e,o,r,i,s,a,c){return K(Sn(n,t,e,o,r,i,s)).mult(1e6).add(1e3*(null!=a?a:0)+(null!=c?c:0))}function Sn(n,t,e,o,r,i,s){const a=R(n);let c,u,d=0;const l=n>=0&&n<1e3,h=l?n+1200:n;for(;d<31;d++){c=e-a*d;const n=Date.UTC(h,t-1,c,null!=o?o:0,null!=r?r:0,null!=i?i:0,null!=s?s:0);if(!En(n)){u=n+a*d*864e5;break}}return (void 0===u||c<1||c>wn.daysInMonth(n,t))&&Zn(),l&&(u=new Date(u).setUTCFullYear(n)),u}function In(n){let t=n.div(1e6),e=n.sub(t.mult(1e6)).toNumber();e<0&&(e+=1e6,t=t.sub(1));const o=Math.floor(e/1e3);return e-=1e3*o,{...Fn(t.toNumber()),isoMicrosecond:o,isoNanosecond:e}}function Fn(n){const[t,e]=Yn(n);return {isoYear:t.getUTCFullYear(),isoMonth:t.getUTCMonth()+1,isoDay:t.getUTCDate()+e,isoHour:t.getUTCHours(),isoMinute:t.getUTCMinutes(),isoSecond:t.getUTCSeconds(),isoMillisecond:t.getUTCMilliseconds()}}function On(n){var t;return null!=(t=n[vn])?t:Mn(n.getISOFields())}function Tn(n){return Math.floor(Sn(n,1,1)/1e3)}function Dn(n){return Yn(n.div(1e6).toNumber())[0].getUTCFullYear()}function Nn(n,t,e){const[o,r]=Yn(Sn(n,t,e));return H(o.getUTCDay()+r,7)||7}function Yn(n){const t=R(n);let e,o=0;for(;o<31;o++){const r=new Date(n-t*o*864e5);if(!En(r)){e=r;break}}return void 0===e&&Zn(),[e,t*o]}function En(n){return isNaN(n.valueOf())}function Zn(){throw new RangeError("Date outside of supported range")}function Cn(n,t){return Math.round((t-n)/864e5)}function Un(n,t){return n+864e5*t}function Pn(n,t){return !Rn(n,t)&&n.calendar.toString()===t.calendar.toString()}function Rn(n,t){return G(Mn(n.getISOFields()),Mn(t.getISOFields()))}function kn(n,t){return P(un(n.getISOFields()),un(t.getISOFields()))}function xn(n,t){return P(n.year,t.year)||P(n.month,t.month)||P(n.day,t.day)}function jn(n,t){return G(n[vn],t[vn])}function qn(n,t,e,o,r){return [n=Number(n),t=c(t,1,o.monthsInYear(n),r),e=c(e,1,o.daysInMonth(n,t),r)]}function Hn(n,t){const[e,o,r]=qn(n.isoYear,n.isoMonth,n.isoDay,wn,t);return {isoYear:e,isoMonth:o,isoDay:r}}function Ln(n,t){return {...Hn(n,t),...Bn(n,t)}}function Bn({isoHour:n,isoMinute:t,isoSecond:e,isoMillisecond:o,isoMicrosecond:r,isoNanosecond:i},s){return {isoHour:n=c(n,0,23,s),isoMinute:t=c(t,0,59,s),isoSecond:e=c(e,0,59,s),isoMillisecond:o=c(o,0,999,s),isoMicrosecond:r=c(r,0,999,s),isoNanosecond:i=c(i,0,999,s)}}const $n={era:String,eraYear:Number,year:Number,month:Number,monthCode:String},An={...$n,day:Number},zn={hour:Number,minute:Number,second:Number,millisecond:Number,microsecond:Number,nanosecond:Number},Wn={era:String,eraYear:Number,year:Number,month:Number,monthCode:String,day:Number},Kn=p(b,(()=>Number));class Gn extends yn{computeFields(n){const t=super.computeFields(n),{year:e}=t;return {...t,era:e<1?"bce":"ce",eraYear:e<1?-(e-1):e}}}const Jn=a("calendarName",{auto:0,never:1,always:2},0),Qn=a("disambiguation",{compatible:0,earlier:1,later:2,reject:3},0);function Vn(n,t=4){const r=d(n),i=r.smallestUnit,s=r.fractionalSecondDigits;let a,u=0,l=1;return void 0!==i?(u=F(i,void 0,0,t),l=e[u],a=o[u]||0):void 0!==s&&"auto"!==s&&(a=c(s,0,9,1),l=Math.pow(10,9-a)),{smallestUnit:u,fractionalSecondDigits:a,roundingFunc:f(n,Math.trunc),incNano:l}}const Xn=a("timeZoneName",{auto:0,never:1},0);function _n(n,t){return nt(n)+"T"+et(n,t)}function nt(n){return tt(n)+"-"+L(n.isoDay,2)}function tt(n){const{isoYear:t}=n;return (t<1e3||t>9999?A(t)+L(Math.abs(t),6):L(t,4))+"-"+L(n.isoMonth,2)}function et(n,t){const e=[L(n.isoHour,2)];return t.smallestUnit<=4&&(e.push(L(n.isoMinute,2)),t.smallestUnit<=3&&e.push(L(n.isoSecond,2)+st(n.isoMillisecond,n.isoMicrosecond,n.isoNanosecond,t.fractionalSecondDigits)[0])),e.join(":")}function ot(n){const[t,e]=ln(Math.abs(n)),o=st(t.isoMillisecond,t.isoMicrosecond,t.isoNanosecond,void 0)[0];return A(n)+L(t.isoHour+24*e,2)+":"+L(t.isoMinute,2)+(t.isoSecond||o?":"+L(t.isoSecond,2)+o:"")}function rt(n,t){return n&&(2===t||1!==t&&"iso8601"!==n)?`[u-ca=${n}]`:""}function it(n){return n.map((([n,t,e])=>{if(e||n){return Math.abs(n).toLocaleString("fullwide",{useGrouping:!1})+t}return ""})).join("")}function st(n,t,o,r,i,s){let a=K(n).mult(1e6).add(K(t).mult(1e3)).add(o);i&&(a=q(a,void 0===r?e[s]:Math.pow(10,9-r),i));const c=a.abs(),u=c.div(1e9);let d=L(c.sub(u.mult(1e9)).toNumber(),9);return d=void 0===r?d.replace(/0+$/,""):d.substr(0,r),[d?"."+d:"",u.toNumber()*(a.sign()||1)]}function at(n){g(n,{epochNanoseconds(){return this[vn].toBigInt()},epochMicroseconds(){return this[vn].div(1e3).toBigInt()},epochMilliseconds(){return this[vn].div(1e6).toNumber()},epochSeconds(){return this[vn].div(1e9).toNumber()}});}const ct={calendar:"calendar"};for(const n of M)ct[n]="iso"+((ut=n).charAt(0).toUpperCase()+ut.slice(1));var ut;function dt(n,t=[]){g(n,p(t.concat("calendar"),(n=>function(){return this.getISOFields()[ct[n]]})));}const lt=["era","eraYear","year","month","monthCode","daysInMonth","daysInYear","monthsInYear","inLeapYear"],ht=[...lt,"day","dayOfWeek","dayOfYear","weekOfYear","daysInWeek"];function ft(n,t){g(n,p(t,(n=>function(){const t=this.calendar[n](this);return Object.defineProperty(this,n,{value:t}),t})));}function mt(n,t){(n.prototype||n)[Symbol.toStringTag]="Temporal."+t;}const gt=a("offset",{prefer:0,use:1,ignore:2,reject:3});function yt(n,e,o=0){const r=n.getPossibleInstantsFor(e);if(1===r.length)return r[0];if(3===o)throw new RangeError("Ambiguous offset");if(r.length)return r[2===o?1:0];{const r=function(n,e){const o=On(e),r=n.getOffsetNanosecondsFor(new Yr(o.sub(t)));return n.getOffsetNanosecondsFor(new Yr(o.add(t)))-r}(n,e),i=n.getPossibleInstantsFor(e.add({nanoseconds:r*(1===o?-1:1)}));return i[1===o?0:i.length-1]}}function wt({year:n,month:t,day:e},o,r,i){n+=o;const s=c(t,1,r.monthsInYear(n),i);let a=t===s?e:1;return a=c(a,1,r.daysInMonth(n,s),i),{year:n,month:s,day:a}}function pt({year:n,month:t,day:e},o,r,i){if(o){if(t+=o,o<0)for(;t<1;)t+=r.monthsInYear(--n);else {let e;for(;t>(e=r.monthsInYear(n));)t-=e,n++;}e=c(e,1,r.daysInMonth(n,t),i);}return {year:n,month:t,day:e}}function vt({isoYear:n,isoMonth:t,isoDay:e},o){if(o){let r=Sn(n,t,e);r=Un(r,o),({isoYear:n,isoMonth:t,isoDay:e}=Fn(r));}return {isoYear:n,isoMonth:t,isoDay:e}}function Mt(n,t){if(en(t)>=6)throw new RangeError("Duration cant have units >= days");return n.add(cn(t))}function bt(n,t,e=3,o){const{offsetNanoseconds:r,timeZone:i,Z:s}=n;if(void 0!==r&&2!==e){if(1===e||s)return Mn(n).sub(r);{const o=St(n,r,i,t);if(void 0!==o)return o;if(3===e)throw new RangeError("Mismatching offset/timezone")}}return yt(i,Ho(n),Qn(o))[vn]}function St(n,t,e,o){const r=e.getPossibleInstantsFor(Ho(n)),i=Mn(n),s=o?x(t):t;for(const n of r){const t=n[vn],e=i.sub(t).toNumber();if((o?x(e):e)===s)return t}}function It(n){const{timeZone:t}=n,e={...n,...on,calendar:new mr("iso8601")},o={...vt(e,1),...on,calendar:new mr("iso8601")},r=yt(t,Ho(e))[vn];return yt(t,Ho(o))[vn].sub(r).toNumber()}const Ft="(\\d{2})(:?(\\d{2})(:?(\\d{2})([.,](\\d{1,9}))?)?)?",Ot="([+-])"+Ft,Tt="(Z|"+Ot+")?(\\[([^=\\]]+)\\])?(\\[u-ca=([^\\]]+)\\])?",Dt=Pt("([+-]\\d{6}|\\d{4})-?(\\d{2})"+Tt),Nt=Pt("(--)?(\\d{2})-?(\\d{2})"+Tt),Yt=Pt("([+-]\\d{6}|\\d{4})-?(\\d{2})-?(\\d{2})([T ](\\d{2})(:?(\\d{2})(:?(\\d{2})([.,](\\d{1,9}))?)?)?)?"+Tt),Et=Pt("T?"+Ft+Tt),Zt=Pt(Ot),Ct=/^([-+])?P(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T((\d+)([.,](\d{1,9}))?H)?((\d+)([.,](\d{1,9}))?M)?((\d+)([.,](\d{1,9}))?S)?)?$/i,Ut=/\u2212/g;function Pt(n){return new RegExp(`^${n}$`,"i")}function Rt(n){return n.replace(Ut,"-")}function kt(n){const t=Lt(n);if(!t)throw _t("dateTime",n);return t}function xt(n){const t=Bt(n);if(!t)throw _t("dateTime",n);return t}function jt(n){const t=zt(n);if(void 0===t)throw _t("timeZone",n);return t}function qt(n){let t=function(n){const t=Et.exec(Rt(n));if(t)return Kt(t.slice(1))}(n);if(void 0!==t){if("T"!==n.charAt(0)){const e=$t(n)||At(n);e&&function(n){try{return Hn(n,1),!0}catch(n){return !1}}(e)&&(t=void 0);}}else t=Bt(n,!0);if(void 0===t)throw _t("time",n);return t}const Ht=/^Z$/i;function Lt(n){const t=Yt.exec(Rt(n));if(t)return function(n){const t=n[11];let e,o=!1;t&&(o=Ht.test(t),e=o?0:Gt(n.slice(12)));return {...Wt(n),timeZone:n[21],offsetNanoseconds:e,Z:o}}(t.slice(1))}function Bt(n,t,e){const o=Yt.exec(Rt(n));if(o&&(e||!Ht.test(o[12]))&&(!t||o[4]))return Wt(o.slice(1))}function $t(n){const t=Dt.exec(Rt(n));if(t)return {calendar:(e=t.slice(1))[14],isoYear:Vt(e[0]),isoMonth:Vt(e[1]),isoDay:1};var e;}function At(n){const t=Nt.exec(Rt(n));if(t)return {calendar:(e=t.slice(1))[15],isoYear:pn,isoMonth:Vt(e[1]),isoDay:Vt(e[2])};var e;}function zt(n){const t=Zt.exec(Rt(n));if(t)return Gt(t.slice(1))}function Wt(n){return {calendar:n[23],isoYear:Vt(n[0]),isoMonth:Vt(n[1]),isoDay:Vt(n[2]),...Kt(n.slice(4))}}function Kt(n){const t=Qt(n[4]);return {...ln(Jt(n[6]||""))[0],isoHour:Qt(n[0]),isoMinute:Qt(n[2]),isoSecond:60===t?59:t}}function Gt(t){return ("+"===t[0]?1:-1)*function(t){return Qt(t[0])*n+6e10*Qt(t[2])+1e9*Qt(t[4])+Jt(t[6]||"")}(t.slice(1))}function Jt(n){return parseInt(B(n,9,"0"))}function Qt(n){return parseInt(n||"0")}function Vt(n){return parseInt(n||"1")}function Xt(n){return void 0===n?void 0:parseInt(n)}function _t(n,t){throw new RangeError(`Cannot parse ${n} '${t}'`)}function ne(n){return {...n,calendar:void 0===n.calendar?gr():new mr(n.calendar)}}function te(n){return {...ne(n),timeZone:new we(n.timeZone)}}class ee{constructor(n){this.id=n;}}class oe extends ee{constructor(n,t){super(n),this.offsetNano=t;}getPossibleOffsets(){return [this.offsetNano]}getOffset(){return this.offsetNano}getTransition(){}}function re(n,t){const e={},o=n.formatToParts(t);for(const n of o)e[n.type]=n.value;return e}const ie={bc:"bce",ad:"ce"};function se(n){return n=n.toLowerCase().normalize("NFD").replace(/[^a-z0-9]/g,""),ie[n]||n}const ae=Intl.DateTimeFormat;function ce(n){return [].concat(n||[])}const ue={"Pacific/Apia":{2011:[[de(13017528e5),-36e12,-396e11],[de(13168728e5),-396e11,-36e12],[de(13252392e5),-36e12,504e11]]}};function de(n){return K(n).mult(1e6)}const le=(new Date).getUTCFullYear()+10,he=[182,91,273];class fe extends ee{constructor(n){const t=new ae("en-GB",{era:"short",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",timeZone:n});super(t.resolvedOptions().timeZone),this.format=t,this.yearEndOffsets={},this.transitionsInYear=ue[n]||{};}getPossibleOffsets(n){let t;const e=[this.getTransition(n,-1),this.getTransition(n.sub(1),1)].filter(Boolean);for(const o of e){const[e,r,i]=o,s=n.sub(r),a=n.sub(i);if(G(e,s)>0&&G(e,a)>0)return [r];if(!(G(e,s)<=0&&G(e,a)<=0))return r<i?[]:[r,i];t=i;}return void 0!==t?[t]:[1e9*this.getYearEndOffsetSec(Dn(n))]}getOffset(n){return 1e9*this.getOffsetForEpochSecs(n.div(1e9).toNumber())}getOffsetForEpochSecs(n){const t=re(this.format,1e3*n);let e=parseInt(t.year);"bce"===se(t.era)&&(e=-(e-1));const o=Sn(e,parseInt(t.month),parseInt(t.day),parseInt(t.hour),parseInt(t.minute),parseInt(t.second));return Math.floor(o/1e3)-n}getTransition(n,t){let e=Dn(n);if(e>le){const o=this.getTransitionFrom(e,e+t,t,n);if(o||t>0)return o;e=le;}return this.getTransitionFrom(Math.max(e,1847),t<0?1846:le,t,n)}getTransitionFrom(n,t,e,o){for(;n!==t;n+=e){let t=this.getTransitionsInYear(n);e<0&&(t=t.slice().reverse());for(const n of t)if(G(n[0],o)===e)return n}}getYearEndOffsetSec(n){const{yearEndOffsets:t}=this;return t[n]||(t[n]=this.getOffsetForEpochSecs(Tn(n+1)-1))}getTransitionsInYear(n){const{transitionsInYear:t}=this;return t[n]||(t[n]=this.computeTransitionsInYear(n))}computeTransitionsInYear(n){const t=this.getYearEndOffsetSec(n-1),e=this.getYearEndOffsetSec(n),o=Tn(n)-1,r=Tn(n+1)-1;if(t!==e)return [this.searchTransition(o,r,t,e)];const i=this.searchIsland(t,o);return void 0!==i?[this.searchTransition(o,i[0],t,i[1]),this.searchTransition(i[0],r,i[1],e)]:[]}searchTransition(n,t,e,o){for(;t-n>1;){const o=Math.floor(n+(t-n)/2);this.getOffsetForEpochSecs(o)===e?n=o:t=o;}return [K(t).mult(1e9),1e9*e,1e9*o]}searchIsland(n,t){for(const e of he){const o=t+86400*e,r=this.getOffsetForEpochSecs(o);if(r!==n)return [o,r]}}}const me={UTC:new oe("UTC",0)};const[ge,ye]=m();class we extends Y{constructor(n){if(!n)throw new RangeError("Invalid timezone ID");super(),ye(this,function(n){const e=(n=String(n)).toLocaleUpperCase();if(me[e])return me[e];const o=zt(n);if(void 0!==o){if(Math.abs(o)>t)throw new RangeError("Offset out of bounds");return new oe(ot(o),o)}return me[e]=new fe(n)}(n));}static from(n){if(h(n))return function(n){const t=n.timeZone;if(void 0===t)return n;if(h(t)&&void 0===t.timeZone)return t;return new we(t)}(n);const t=Lt(String(n));if(t){if(t.timeZone){const n=te(t);return function(n){const{offsetNanoseconds:t,timeZone:e,Z:o}=n;if(void 0!==t&&!o&&void 0===St(n,t,e,!0))throw new RangeError("Mismatching offset/timezone")}(n),n.timeZone}if(t.Z)return new we("UTC");if(void 0!==t.offsetNanoseconds)return new we(ot(t.offsetNanoseconds))}return new we(String(n))}get id(){return this.toString()}getOffsetStringFor(n){return ot(this.getOffsetNanosecondsFor(n))}getOffsetNanosecondsFor(n){const t=N(Yr,n);return ge(this).getOffset(t[vn])}getPlainDateTimeFor(n,t=gr()){const e=N(Yr,n);return Ho({...In(e[vn].add(this.getOffsetNanosecondsFor(e))),calendar:N(mr,t)})}getInstantFor(n,t){return yt(this,N(qo,n),Qn(t))}getPossibleInstantsFor(n){const t=Mn(N(qo,n).getISOFields());return ge(this).getPossibleOffsets(t).map((n=>new Yr(t.sub(n))))}getPreviousTransition(n){const t=N(Yr,n),e=ge(this).getTransition(t[vn],-1);return e?new Yr(e[0]):null}getNextTransition(n){const t=N(Yr,n),e=ge(this).getTransition(t[vn],1);return e?new Yr(e[0]):null}toString(){return ge(this).id}}function pe(n){if(void 0===n.timeZone)throw new TypeError("Must specify timeZone");return N(we,n.timeZone)}mt(we,"TimeZone");const ve=Le((function(n,t,e){const o=Ce(n,t,e);if(o)return {...o,timeZone:pe(n),offsetNanoseconds:void 0!==n.offset?jt(String(n.offset)):void 0}})),Me=Le(Ce),be=Le(Ue),Se=Le((function(n,t){const e=pr(n),o=je(n,$n,e);if(Be(o))return e.yearMonthFromFields(o,t)})),Ie=Le((function(n,t){const e=pr(n),o=je(n,Wn,e);if(Be(o))return void 0===n.year&&void 0===n.calendar&&(o.year=pn),e.monthDayFromFields(o,t)})),Fe=Le(Pe),Oe=Le((function(n,t,e,o){const r=Re(n,t,e,o),i=void 0!==t.offset;if(r||i)return {...r||n.getISOFields(),timeZone:n.timeZone,offsetNanoseconds:i?jt(String(t.offset)):n.offsetNanoseconds}}),!0),Te=Le(Re,!0),De=Le(ke,!0),Ne=Le((function(n,t,e){const o=n.calendar;if(Be(je(t,$n,o))){const r=He(n,t,$n,o);return o.yearMonthFromFields(r,e)}}),!0),Ye=Le((function(n,t,e){const o=n.calendar;if(Be(je(t,Wn,o))){const r=He(n,t,Wn,o);return o.monthDayFromFields(r,e)}}),!0),Ee=Le(xe,!0),Ze=Le((function(n){const t=u(n,Kn);if(Be(t))return t}));function Ce(n,t,e){const o=Ue(n,e),r=Pe(n,t);if(o)return {...o.getISOFields(),...r||on}}function Ue(n,t){const e=pr(n),o=je(n,An,e);if(Be(o))return e.dateFromFields(o,t)}function Pe(n,t){const e=u(n,zn);if(Be(e))return Bn(sn(e),t)}function Re(n,t,e,o){const r=ke(n,t,o),i=xe(n,t,e);if(r||i)return {...n.getISOFields(),...r?r.getISOFields():{},...i}}function ke(n,t,e){const o=n.calendar,r=je(t,An,o);if(Be(r)){const t=He(n,r,An,o);return o.dateFromFields(t,e)}}function xe(n,t,e){const o=u(t,zn);if(Be(o)){return Bn(sn((r=n,i=o,y(zn,((n,t)=>{var e;return null!=(e=i[t])?e:r[t]})))),e)}var r,i;}function je(n,t,e){let o=Object.keys(t);return o=e.fields?Array.prototype.slice.call(e.fields(o)):Object.keys(qe(e,o)),qe(n,o)}function qe(n,t){const e={};for(const o of t)void 0!==n[o]&&(e[o]=n[o]);return e}function He(n,t,e,o){const r=je(n,e,o);return o.mergeFields?o.mergeFields(r,t):yr(r,t)}function Le(n,t){return (...e)=>{if(t){const n=e[1];if(!h(n))throw new TypeError("must be object-like");if(void 0!==n.calendar)throw new TypeError("calendar not allowed");if(void 0!==n.timeZone)throw new TypeError("timeZone not allowed")}const o=n(...e);if(!o)throw new TypeError("No valid fields");return o}}function Be(n){return Object.keys(n).length>0}const $e=K(t).mult(1e8),Ae=$e.mult(-1),ze=$e.add(86399999999999),We=Ae.sub(86399999999999);function Ke(n,t){const e=Mn(n);Ge(e),cr(e,t);}function Ge(n){-1!==G(n,We)&&1!==G(n,ze)||Zn();}function Je(n,t){const e=Xe(un(n),t),[o,r]=ln(e);return {...vt(n,r),...o}}function Qe(n,t){const e=Xe(un(n),t),[o]=ln(e);return o}function Ve(n,t){const[e,o]=function(n){const t=In(n);return [bn(t.isoYear,t.isoMonth,t.isoDay),un(t)]}(n),r=Xe(o,t);return e.add(r)}function Xe(n,t){return k(n,t.incNano,t.roundingFunc)}function _e(n,t,e){return (o,r)=>{const i=io(n,r)?{}:{...n,...t};return {buildKey:ro(o,r,!1),buildFormat:function(n,t){return new ae(o,{calendar:n,timeZone:t||void 0,...i,...r,...e})},buildEpochMilli:no}}}function no(n){return n.epochMilliseconds}function to(n,t,e){return (o,r)=>{const i=io(n,r)?{}:n;return {buildKey:ro(o,r,e),buildFormat:function(n,e){return new ae(o,{calendar:n,...i,...r,...t,timeZone:e,timeZoneName:void 0})},buildEpochMilli:void 0!==r.timeZone?eo.bind(null,new we(r.timeZone)):oo}}}function eo(n,t){const e=Ho({...on,...t.getISOFields()});return n.getInstantFor(e).epochMilliseconds}function oo(n){return Sn((t=n.getISOFields()).isoYear,t.isoMonth,t.isoDay,t.isoHour,t.isoMinute,t.isoSecond,t.isoMillisecond);var t;}function ro(n,t,e){var o;const r=null!=(o=t.calendar)?o:function(n){for(const t of n){const n=t.match(/-u-ca-(.*)$/);if(n)return n[1]}return}(n),i=t.timeZone;return function(n,t){var o,s,a,c;const u=null==(o=n.calendar)?void 0:o.id,d=null==(s=n.timeZone)?void 0:s.id;if(t){if((null==(a=t.calendar)?void 0:a.id)!==u)throw new RangeError("Mismatching calendar");if((null==(c=t.timeZone)?void 0:c.id)!==d)throw new RangeError("Mismatching timeZone")}if((e||"iso8601"!==u)&&void 0!==u&&void 0!==r&&r!==u)throw new RangeError("Non-iso calendar mismatch");if(void 0!==d&&void 0!==i&&i!==d)throw new RangeError("Given timeZone must agree");return [r||u||"iso8601",i||d||"UTC"]}}function io(n,t){for(const e in n)if(void 0!==t[e])return !0;return !1}function so(n,t){n.prototype.toLocaleString=function(n,e){const o=t(ce(n),e||{});return o.buildFormat(...o.buildKey(this)).format(o.buildEpochMilli(this))},n.prototype[D$1]=t;}function co(n){const t=function(n){const t=Ct.exec(Rt(n));if(t){let n,e,o,r;[n,r]=uo(t[8],t[10],5,void 0),[e,r]=uo(t[12],t[14],4,r),[o,r]=uo(t[16],t[18],3,r);const i=function(n){const t={};for(const e in n)void 0!==n[e]&&(t[e]=n[e]);return t}({years:Xt(t[2]),months:Xt(t[3]),weeks:Xt(t[4]),days:Xt(t[5]),hours:n,minutes:e,seconds:o});if(!Object.keys(i).length)throw new RangeError("Duration string must have at least one field");const s=dn(K(r||0),2);i.milliseconds=s.milliseconds,i.microseconds=s.microseconds,i.nanoseconds=s.nanoseconds;let a=nn(i);return "-"===t[1]&&(a=X(a)),a}}(n);if(void 0===t)throw _t("duration",n);return t}function uo(n,t,o,r){if(void 0!==n){if(void 0!==r)throw new RangeError("Partial units must be last unit");return [parseInt(n),void 0!==t?Jt(t)*(e[o]/1e9):void 0]}if(void 0!==r){const n=Math.trunc(r/e[o]);return [n,r-n*e[o]]}return [void 0,void 0]}const lo=a("offset",{auto:0,never:1},0);class ho extends U{constructor(n=0,t=0,e=0,o=0,r=0,i=0){super({...Bn({isoHour:n,isoMinute:t,isoSecond:e,isoMillisecond:o,isoMicrosecond:r,isoNanosecond:i},1),calendar:gr()});}static from(n,t){const e=s$1(t);return fo(n instanceof ho?n.getISOFields():"object"==typeof n?Fe(n,e):qt(String(n)))}static compare(n,t){return kn(N(ho,n),N(ho,t))}with(n,t){return fo(Ee(this,n,s$1(t)))}add(n){return go(this,N(ko,n))}subtract(n){return go(this,X(N(ko,n)))}until(n,t){return yo(this,N(ho,n),t)}since(n,t){return yo(N(ho,n),this,t)}round(n){const t=T(n,0,5);return fo(Qe(this.getISOFields(),t))}equals(n){return !kn(this,N(ho,n))}toString(n){const t=Vn(n);return et(Qe(this.getISOFields(),t),t)}toZonedDateTime(n){const t=N(Sr,n.plainDate),e=N(we,n.timeZone);return Fo({...t.getISOFields(),...this.getISOFields(),timeZone:e})}toPlainDateTime(n){return N(Sr,n).toPlainDateTime(this)}}function fo(n){return new ho(n.isoHour,n.isoMinute,n.isoSecond,n.isoMillisecond,n.isoMicrosecond,n.isoNanosecond)}function mo(n){return N(ho,null!=n?n:{hour:0})}function go(n,t){return fo(function(n,t){const e=un(n)+cn(t).toNumber(),[o]=ln(e);return o}(n.getISOFields(),t))}function yo(n,t,o){const r=O(o,5,0,0,5);return xo(function(n,t,o){return dn(K(k(un(t)-un(n),e[o.smallestUnit]*o.roundingIncrement,o.roundingFunc)),o.largestUnit)}(n.getISOFields(),t.getISOFields(),r))}mt(ho,"PlainTime"),dt(ho,v),so(ho,(function(n,t){return {buildKey:()=>["",""],buildFormat:()=>new ae(n,{hour:"numeric",minute:"2-digit",second:"2-digit",...t,timeZone:"UTC",timeZoneName:void 0,year:void 0,month:void 0,day:void 0,weekday:void 0}),buildEpochMilli:n=>Math.trunc(un(n.getISOFields())/1e6)}}));const wo={day:1};class po extends U{constructor(n,t,e=gr(),o=1){const r=Hn({isoYear:n,isoMonth:t,isoDay:o},1),i=N(mr,e);var s,a;s=r,a=i.toString(),cr(Mn(s),a),super({...r,calendar:i});}static from(n,t){if(s$1(t),n instanceof po)return vo(n.getISOFields());if("object"==typeof n)return Se(n,t);const e=function(n){const t=$t(n)||Bt(n);if(!t)throw _t("yearMonth",n);return t}(String(n));return void 0===e.calendar&&(e.isoDay=1),vo(ne(e))}static compare(n,t){return Rn(N(po,n),N(po,t))}with(n,t){return Ne(this,n,t)}add(n,t){return Mo(this,N(ko,n),t)}subtract(n,t){return Mo(this,X(N(ko,n)),t)}until(n,t){return bo(this,N(po,n),!1,t)}since(n,t){return bo(this,N(po,n),!0,t)}equals(n){return !Rn(this,N(po,n))}toString(n){const t=this.getISOFields(),e=t.calendar.toString(),o=Jn(n);return ("iso8601"===e?tt(t):nt(t))+rt(e,o)}toPlainDate(n){return this.calendar.dateFromFields({year:this.year,month:this.month,day:n.day})}}function vo(n){return new po(n.isoYear,n.isoMonth,n.calendar,n.isoDay)}function Mo(n,t,e){return n.toPlainDate({day:t.sign<0?n.daysInMonth:1}).add(t,e).toPlainYearMonth()}function bo(n,t,e,o){return xo(Tr(n.toPlainDate(wo),t.toPlainDate(wo),vr(n,t),e,O(o,9,8,8,9)))}mt(po,"PlainYearMonth"),dt(po),ft(po,lt),so(po,to({year:"numeric",month:"numeric"},{weekday:void 0,day:void 0,hour:void 0,minute:void 0,second:void 0},!0));const So=Symbol();class Io extends U{constructor(n,t,e=gr()){const o=N(we,t),r=N(mr,e),i=K(n),[s,a]=Oo(i,o);Ke(s,r.toString()),super({...s,calendar:r,timeZone:o,offset:ot(a)}),this[vn]=i,this[So]=a;}static from(n,t){const e=gt(t,3),o=s$1(t);if(n instanceof Io)return new Io(n.epochNanoseconds,n.timeZone,n.calendar);const r="object"==typeof n;return Fo(r?ve(n,o,t):te(kt(String(n))),!r,e,t)}static compare(n,t){return jn(N(Io,n),N(Io,t))}get timeZone(){return this.getISOFields().timeZone}get offsetNanoseconds(){return this[So]}get offset(){return this.getISOFields().offset}with(n,t){Qn(t);const e=s$1(t),o=gt(t,0);return Fo(Oe(this,n,e,t),!1,o,t)}withPlainDate(n){const t=N(Sr,n),e=t.toPlainDateTime(this),{timeZone:o}=this,r=yt(o,e);return new Io(r.epochNanoseconds,o,Mr(this,t))}withPlainTime(n){return Fo({...this.getISOFields(),...void 0===n?on:N(ho,n).getISOFields()})}withCalendar(n){return new Io(this.epochNanoseconds,this.timeZone,n)}withTimeZone(n){return new Io(this.epochNanoseconds,n,this.calendar)}add(n,t){return To(this,N(ko,n),t)}subtract(n,t){return To(this,X(N(ko,n)),t)}until(n,t){return No(this,N(Io,n),!1,t)}since(n,t){return No(this,N(Io,n),!0,t)}round(n){return Do(this,T(n,0,6))}equals(n){return t=this,e=N(Io,n),Pn(t,e)&&t.timeZone.toString()===e.timeZone.toString();var t,e;}startOfDay(){return Fo({...this.getISOFields(),...on,offsetNanoseconds:this.offsetNanoseconds},!1,0)}get hoursInDay(){return It(this.getISOFields())/n}toString(n){const t=Vn(n),e=lo(n),o=Xn(n),r=Jn(n),i=Do(this,t);return _n(i.getISOFields(),t)+(0===e?ot(x(i.offsetNanoseconds)):"")+(s=this.timeZone.toString(),1!==o?`[${s}]`:"")+rt(this.calendar.toString(),r);var s;}toPlainYearMonth(){return vo(this.getISOFields())}toPlainMonthDay(){return this.calendar.monthDayFromFields(this)}toPlainDateTime(){return Ho(this.getISOFields())}toPlainDate(){return Ir(this.getISOFields())}toPlainTime(){return fo(this.getISOFields())}toInstant(){return new Yr(this.epochNanoseconds)}}function Fo(n,t,e,o){const r=bt(n,t,e,o);return new Io(r,n.timeZone,n.calendar)}function Oo(n,t){const e=new Yr(n),o=t.getOffsetNanosecondsFor(e);return [In(n.add(o)),o]}function To(n,t,e){const o=n.getISOFields(),r=function(n,t,e){const{calendar:o,timeZone:r}=n,i=o.dateAdd(Ir(n),_(t,rn),e);return yt(r,Ho({...n,...i.getISOFields()}))[vn].add(cn(t))}(o,t,e);return new Io(r,o.timeZone,o.calendar)}function Do(n,t){const e=n.getISOFields(),o=function(n,t,e){const{calendar:o,timeZone:r}=n;let i,s,a=un(n);return 6===e.smallestUnit?(i=on,s=e.roundingFunc(a/It(n))):(a=Xe(a,e),[i,s]=ln(a)),bt({...vt(n,s),...i,offsetNanoseconds:t,calendar:o,timeZone:r},!1,0)}(e,n.offsetNanoseconds,t);return new Io(o,e.timeZone,e.calendar)}function No(n,t,e,o){const r=O(o,5,0,0,9),{largestUnit:i}=r;if(i>=6&&n.timeZone.id!==t.timeZone.id)throw new Error("Must be same timeZone");return xo(Or(n,t,vr(n,t),e,r))}function Yo(n){if(void 0===n)return;if(h(n))return n instanceof Io||n instanceof qo?n:N(void 0!==n.timeZone?Io:qo,n);if("symbol"==typeof n)throw new TypeError("Incorrect relativeTo type");const t=Lt(String(n));if(t)return void 0!==t.timeZone?Fo(te(t),!0):Ho(ne(t));throw new RangeError("Invalid value of relativeTo")}function Eo(n,t,e,o){return (e instanceof Sr?function(n,t,e,o){const r=e.add(n);return [o.dateUntil(e,r,{largestUnit:M[t]}),r]}(n,Math.max(6,t),e,o):Zo(n,t,e,o))[0]}function Zo(n,t,e,o,r){const i=!0!==r&&t>7&&n.weeks;i&&(n=_(n,{weeks:0}));let s=e.add(n),a=Dr(e,s,o,t);return i&&(a=_(a,{weeks:i}),s=s.add({weeks:i})),[a,s]}function Co(n,t,e,o){const r=b[t],{sign:i}=n;if(!i)return n;const s={};for(let e=9;e>=t;e--){const t=b[e];s[t]=n[t];}const a={[r]:i},c=e.add(s),u=c.add(a),d=On(c),l=On(u),h=On(o).sub(d).toNumber()/l.sub(d).toNumber()*i;return s[r]+=h,s}function Uo(n,t,o,r,s,a){const{largestUnit:c,smallestUnit:u,roundingIncrement:d,roundingFunc:l}=a;if(!i(c)){return dn(q(On(o).sub(On(t)).mult(s?-1:1),e[u]*d,l),c)}let h=Co(n,u,t,o);const f=b[u];function m(){const n=h[f];h[f]=k(n,d,l);}return l===Math.round&&m(),s&&(h=X(h)),l!==Math.round&&m(),u>0&&(h=s?X(Eo(X(h),c,t,r)):Eo(h,c,t,r)),h}mt(Io,"ZonedDateTime"),dt(Io,v),ft(Io,ht),at(Io),so(Io,_e({year:"numeric",month:"numeric",day:"numeric",weekday:void 0,hour:"numeric",minute:"2-digit",second:"2-digit"},{timeZoneName:"short"},{}));const[Po,Ro]=m();class ko extends E{constructor(n=0,t=0,e=0,o=0,r=0,i=0,s=0,a=0,c=0,u=0){super();const d=Ze({years:n,months:t,weeks:e,days:o,hours:r,minutes:i,seconds:s,milliseconds:a,microseconds:c,nanoseconds:u});Ro(this,function(n){const t=nn(n),{sign:e}=t;for(const n of b){const o=t[n],r=R(t[n]);if(r&&r!==e)throw new RangeError("All fields must be same sign");if(!Number.isInteger(o))throw new RangeError("Duration fields must be integers")}return t}(d));}static from(n){return xo("object"==typeof n?Ze(n):co(n))}static compare(n,t,e){return function(n,t,e){if(void 0===e&&en(n)<=6&&en(t)<=6)return G(an(n),an(t));if(!e)throw new RangeError("Need relativeTo");const o=e.add(n),r=e.add(t);return void 0!==e[vn]?jn(o,r):Rn(o,r)}(N(ko,n),N(ko,t),Yo(d(e).relativeTo))}get years(){return Po(this).years}get months(){return Po(this).months}get weeks(){return Po(this).weeks}get days(){return Po(this).days}get hours(){return Po(this).hours}get minutes(){return Po(this).minutes}get seconds(){return Po(this).seconds}get milliseconds(){return Po(this).milliseconds}get microseconds(){return Po(this).microseconds}get nanoseconds(){return Po(this).nanoseconds}get sign(){return Po(this).sign}get blank(){return !this.sign}with(n){return xo({...Po(this),...Ze(n)})}negated(){return xo(X(Po(this)))}abs(){return xo(w(Po(this),V,(n=>Math.abs(n))))}add(n,t){return jo(this,N(ko,n),t)}subtract(n,t){return jo(this,X(N(ko,n)),t)}round(n){const t="string"==typeof n?{smallestUnit:n}:n;if(!h(t))throw new TypeError("Must specify options");if(void 0===t.largestUnit&&void 0===t.smallestUnit)throw new RangeError("Must specify either largestUnit or smallestUnit");const o=O(t,en(this),0,0,9,!0),i=Yo(t.relativeTo);return xo(function(n,t,o,i){const{largestUnit:s,smallestUnit:a,roundingIncrement:c,roundingFunc:u}=t;if(void 0===o&&en(n)<=6&&r(s)&&r(a))return dn(q(an(n),e[a]*c,u),s);if(!o)throw new RangeError("Need relativeTo");const[d,l]=Zo(n,s,o,i);return Uo(d,o,l,i,!1,t)}(this,o,i,i?i.calendar:void 0))}total(n){const t=function(n){let t,e;return "string"==typeof n?e=n:(e=d(n).unit,t=n.relativeTo),{unit:F(e,void 0,0,9),relativeTo:t}}(n),o=Yo(t.relativeTo);return function(n,t,o,i){if(void 0===o&&en(n)<=6&&r(t))return an(n).toNumber()/e[t];if(!o)throw new RangeError("Need relativeTo");const[s,a]=Zo(n,t,o,i,!0);return Co(s,t,o,a)[b[t]]}(this,t.unit,o,o?o.calendar:void 0)}toString(n){const t=Vn(n,3);return function(n,t){const{smallestUnit:e,fractionalSecondDigits:o,roundingFunc:r}=t,{sign:i}=n,s=n.hours,a=n.minutes;let c=n.seconds,u="";if(e<=3){const t=st(n.milliseconds,n.microseconds,n.nanoseconds,o,r,e);u=t[0],c+=t[1];}const d=void 0!==o||u||!i;return (i<0?"-":"")+"P"+it([[n.years,"Y"],[n.months,"M"],[n.weeks,"W"],[n.days,"D"]])+(s||a||c||d?"T"+it([[s,"H"],[a,"M"],[e<=3?c:0,u+"S",d]]):"")}(Po(this),t)}toLocaleString(n,t){return this.toString()}}function xo(n){return new ko(n.years,n.months,n.weeks,n.days,n.hours,n.minutes,n.seconds,n.milliseconds,n.microseconds,n.nanoseconds)}function jo(n,t,e){const o=Yo(d(e).relativeTo);return xo(function(n,t,e,o){const r=Math.max(en(n),en(t));if(void 0===e&&r<=6)return dn(an(n).add(an(t)),r);if(!e)throw new RangeError("Need relativeTo");const i=e.add(n).add(t);return Dr(e,i,o,r)}(n,t,o,o?o.calendar:void 0))}mt(ko,"Duration");class qo extends U{constructor(n,t,e,o=0,r=0,i=0,s=0,a=0,c=0,u=gr()){const d=Ln({isoYear:n,isoMonth:t,isoDay:e,isoHour:o,isoMinute:r,isoSecond:i,isoMillisecond:s,isoMicrosecond:a,isoNanosecond:c},1),l=N(mr,u);Ke(d,l.toString()),super({...d,calendar:l});}static from(n,t){const e=s$1(t);return Ho(n instanceof qo?n.getISOFields():"object"==typeof n?Me(n,e,t):ne(xt(String(n))))}static compare(n,t){return Rn(N(qo,n),N(qo,t))}with(n,t){const e=s$1(t);return Ho(Te(this,n,e,t))}withPlainDate(n){const t=N(Sr,n);return Ho({...this.getISOFields(),...t.getISOFields(),calendar:Mr(this,t)})}withPlainTime(n){return Ho({...this.getISOFields(),...mo(n).getISOFields()})}withCalendar(n){return Ho({...this.getISOFields(),calendar:N(mr,n)})}add(n,t){return Lo(this,N(ko,n),t)}subtract(n,t){return Lo(this,X(N(ko,n)),t)}until(n,t){return Bo(this,N(qo,n),!1,t)}since(n,t){return Bo(this,N(qo,n),!0,t)}round(n){const t=T(n,0,6);return Ho({...Je(this.getISOFields(),t),calendar:this.calendar})}equals(n){return Pn(this,N(qo,n))}toString(n){const t=Vn(n),e=Jn(n);return _n(Je(this.getISOFields(),t),t)+rt(this.calendar.toString(),e)}toZonedDateTime(n,t){const e=N(we,n),o=yt(e,this,Qn(t));return new Io(o.epochNanoseconds,e,this.calendar)}toPlainYearMonth(){return vo(this.getISOFields())}toPlainMonthDay(){return this.calendar.monthDayFromFields(this)}toPlainDate(){return Ir(this.getISOFields())}toPlainTime(){return fo(this.getISOFields())}}function Ho(n){return new qo(n.isoYear,n.isoMonth,n.isoDay,n.isoHour,n.isoMinute,n.isoSecond,n.isoMillisecond,n.isoMicrosecond,n.isoNanosecond,n.calendar)}function Lo(n,t,e){const o=function(n,t,e){const{calendar:o}=n;return In(Mn(o.dateAdd(Ir(n),_(t,rn),e).getISOFields()).add(un(n)).add(cn(t)))}(n.getISOFields(),t,e);return Ho({...o,calendar:n.calendar})}function Bo(n,t,e,o){const r=O(o,6,0,0,9);return xo(Or(n,t,vr(n,t),e,r))}mt(qo,"PlainDateTime"),dt(qo,v),ft(qo,ht),so(qo,to({year:"numeric",month:"numeric",day:"numeric",weekday:void 0,hour:"numeric",minute:"2-digit",second:"2-digit"},{}));class $o extends U{constructor(n,t,e=gr(),o=pn){super({...Hn({isoYear:o,isoMonth:n,isoDay:t},1),calendar:N(mr,e)});}static from(n,t){if(s$1(t),n instanceof $o)return Ao(n.getISOFields());if("object"==typeof n)return Ie(n,t);const e=function(n){const t=At(n)||Bt(n);if(!t)throw _t("monthDay",n);return t}(String(n));return void 0===e.calendar&&(e.isoYear=pn),Ao(ne(e))}with(n,t){return Ye(this,n,t)}equals(n){return !Rn(this,N($o,n))}toString(n){const t=this.getISOFields(),e=t.calendar.toString(),o=Jn(n);return ("iso8601"===e?function(n){return L(n.isoMonth,2)+"-"+L(n.isoDay,2)}(t):nt(t))+rt(e,o)}toPlainDate(n){return this.calendar.dateFromFields({year:n.year,monthCode:this.monthCode,day:this.day},{overflow:"reject"})}}function Ao(n){return new $o(n.isoMonth,n.isoDay,n.calendar,n.isoYear)}function zo(n){return n instanceof Sr||n instanceof qo||n instanceof Io||n instanceof po||n instanceof $o}function Wo(n,t,e){let o;if(n instanceof Sr)o=n;else if(zo(n)){if(e&&n instanceof $o)throw new TypeError("PlainMonthDay not allowed");o=Ir(n.getISOFields());}else o=Sr.from(n);return br(o.calendar,t),o}function Ko(n,t,e){if(zo(n))return n.getISOFields();let{era:o,eraYear:r,year:i,month:a,monthCode:c,day:u}=n;const d=void 0!==r&&void 0!==o?mn(t.id,r,o):void 0;if(void 0===i){if(void 0===d)throw new TypeError("Must specify either a year or an era & eraYear");i=d;}else if(void 0!==d&&d!==i)throw new RangeError("year and era/eraYear must match");if(void 0===u)throw new TypeError("Must specify day");const l=s$1(e);if(void 0!==c){const[n,e]=t.convertMonthCode(c,i);if(void 0!==a&&a!==n)throw new RangeError("Month doesnt match with monthCode");if(a=n,e){if(1===l)throw new RangeError("Month code out of range");u=t.daysInMonth(i,a);}}else if(void 0===a)throw new TypeError("Must specify either a month or monthCode");return [i,a,u]=qn(i,a,u,t,l),Fn(t.epochMilliseconds(i,a,u))}function Go(n,t){if(zo(n)){if(t&&n instanceof $o)throw new TypeError("PlainMonthDay not allowed");return n.getISOFields()}return Sr.from(n).getISOFields()}function Jo(n,t){return Cn(n.epochMilliseconds(t,1,1),n.epochMilliseconds(t+1,1,1))}function Qo(n,t,e,o){return Cn(n.epochMilliseconds(t,1,1),n.epochMilliseconds(t,e,o))+1}mt($o,"PlainMonthDay"),dt($o),ft($o,["monthCode","day"]),so($o,to({month:"numeric",day:"numeric"},{weekday:void 0,year:void 0,hour:void 0,minute:void 0,second:void 0},!0));const Vo={hebrew:6,chinese:0,dangi:0};class Xo extends fn{constructor(n){const t=_o(n);if(e=n,o=t.resolvedOptions().calendar,gn(e)!==gn(o))throw new RangeError("Invalid calendar: "+n);var e,o;super(n),this.format=t,this.yearCorrection=this.computeFieldsDumb(0).year-1970,this.monthCacheByYear={};}epochMilliseconds(n,t,e){return Un(this.queryMonthCache(n)[0][t-1],e-1)}daysInMonth(n,t){const e=this.queryMonthCache(n)[0],o=e[t-1];t>=e.length&&(n++,t=0);return Cn(o,this.queryMonthCache(n)[0][t])}monthsInYear(n){return this.queryMonthCache(n)[0].length}monthCode(n,t){const e=this.queryLeapMonthByYear(t);return !e||n<e?super.monthCode(n,t):super.monthCode(n-1,t)+(n===e?"L":"")}convertMonthCode(n,t){const e=this.queryLeapMonthByYear(t);let o=/L$/.test(n),r=parseInt(n.substr(1)),i=!1;if(o){const n=Vo[this.id];if(void 0===n)throw new RangeError("Calendar system doesnt support leap months");if(n){if(r!==n-1)throw new RangeError("Invalid leap-month month code")}else if(r<=1||r>=12)throw new RangeError("Invalid leap-month month code")}return !o||e&&r===e-1||(i=!0,o=!1),(o||e&&r>=e)&&r++,[r,i]}inLeapYear(n){const t=Jo(this,n);return t>Jo(this,n-1)&&t>Jo(this,n+1)}guessYearForMonthDay(n,t){let e=1970+this.yearCorrection;const o=e+100;for(;e<o;e++){const[o,r]=this.convertMonthCode(n,e);if(!r&&o<=this.monthsInYear(e)&&t<=this.daysInMonth(e,o))return e}throw new Error("Could not guess year")}normalizeISOYearForMonthDay(n){return n}computeFields(n){const t=this.computeFieldsDumb(n),e=this.queryMonthCache(t.year)[2];return {...t,month:e[t.month]}}computeFieldsDumb(n){const t=re(this.format,n);let e,o,r=parseInt(t.relatedYear||t.year);var i;return t.era&&(i=this.id,void 0!==hn[gn(i)])&&(e=se(t.era),o=r,r=mn(this.id,o,e,!0)),{era:e,eraYear:o,year:r,month:t.month,day:parseInt(t.day)}}queryLeapMonthByYear(n){const t=this.queryMonthCache(n),e=this.queryMonthCache(n-1),o=this.queryMonthCache(n+1);if(t[0].length>e[0].length&&t[0].length>o[0].length){const n=t[1],o=e[1];for(let t=0;t<o.length;t++)if(o[t]!==n[t])return t+1}}queryMonthCache(n){const{monthCacheByYear:t}=this;return t[n]||(t[n]=this.buildMonthCache(n))}buildMonthCache(n){const t=[],e=[],o={};let r=Sn(this.guessISOYear(n),1,1);for(r=Un(r,400);;){const o=this.computeFieldsDumb(r);if(o.year<n)break;r=Un(r,1-o.day),o.year===n&&(t.unshift(r),e.unshift(o.month)),r=Un(r,-1);}for(let n=0;n<e.length;n++)o[e[n]]=n+1;return [t,e,o]}guessISOYear(n){return n-this.yearCorrection}}function _o(n){return new ae("en-US",{calendar:n,era:"short",year:"numeric",month:"short",day:"numeric",timeZone:"UTC"})}const nr=Sn(1868,9,8);const tr={gregory:Gn,japanese:class extends Gn{constructor(){super(...arguments),this.format=_o("japanese");}computeFields(n){const t=super.computeFields(n);if(n>=nr){const e=re(this.format,n);t.era=se(e.era),t.eraYear=parseInt(e.relatedYear||e.year);}return t}},islamic:class extends Xo{guessISOYear(n){return Math.ceil(32*n/33+622)}}},er={iso8601:wn};function or(n){const t=(n=String(n)).toLocaleLowerCase();return er[t]||(er[t]=new(tr[gn(t)]||Xo)(n))}const rr=Sn(1582,10,15),ir=Sn(622,7,18),sr={buddhist:rr,japanese:rr,roc:rr,islamic:ir,"islamic-rgsa":ir,indian:0},ar={};function cr(n,t){return ur(n.div(1e6).toNumber(),t)}function ur(n,t){if(function(n,t){return function(n){let t=ar[n];if(void 0===t){const e=sr[n];if(void 0===e)t=!1;else {let o=or(n);o instanceof Xo||(o=new Xo(n));const r=e-864e5,i=o.computeFields(r);t=r!==o.epochMilliseconds(i.year,i.month,i.day);}ar[n]=t;}return t}(t)&&n<sr[t]}(n,t))throw new RangeError("Invalid timestamp for calendar")}function dr(n,t,e){const o=7+t-e;return -H(Nn(n,1,o)-t,7)+o-1}function lr(n,t,e){const o=dr(n,t,e),r=dr(n+1,t,e);return (Jo(wn,n)-o+r)/7}const[hr,fr]=m();class mr extends Y{constructor(n){super(),"islamicc"===n&&(n="islamic-civil"),fr(this,or(n));}static from(n){if(h(n))return function(n){const t=n.calendar;if(void 0===t)return n;if(h(t)&&void 0===t.calendar)return t;return new mr(t)}(n);const t=Bt(String(n),!1,!0);return new mr(t?t.calendar||"iso8601":String(n))}get id(){return this.toString()}era(n){const t=Go(n,!0);return wr(hr(this),t.isoYear,t.isoMonth,t.isoDay).era}eraYear(n){const t=Go(n,!0);return wr(hr(this),t.isoYear,t.isoMonth,t.isoDay).eraYear}year(n){const t=Go(n,!0);return wr(hr(this),t.isoYear,t.isoMonth,t.isoDay).year}month(n){const t=Go(n,!0);return wr(hr(this),t.isoYear,t.isoMonth,t.isoDay).month}monthCode(n){const t=Wo(n,this);return hr(this).monthCode(t.month,t.year)}day(n){const t=Go(n);return wr(hr(this),t.isoYear,t.isoMonth,t.isoDay).day}dayOfWeek(n){const t=Go(n,!0);return Nn(t.isoYear,t.isoMonth,t.isoDay)}dayOfYear(n){const t=Wo(n,this,!0);return Qo(hr(this),t.year,t.month,t.day)}weekOfYear(n){const t=Go(n,!0);return function(n,t,e,o,r){const i=dr(n,o,r),s=Math.floor((Qo(wn,n,t,e)-i-1)/7)+1;if(s<1)return s+lr(n-1,o,r);const a=lr(n,o,r);return s>a?s-a:s}(t.isoYear,t.isoMonth,t.isoDay,1,4)}daysInWeek(n){return Go(n,!0),7}daysInMonth(n){const t=Wo(n,this,!0);return hr(this).daysInMonth(t.year,t.month)}daysInYear(n){const t=Wo(n,this,!0);return Jo(hr(this),t.year)}monthsInYear(n){const t=Wo(n,this,!0);return hr(this).monthsInYear(t.year)}inLeapYear(n){return hr(this).inLeapYear(this.year(n))}dateFromFields(n,t){const e=Ko(u(n,An),hr(this),t);return new Sr(e.isoYear,e.isoMonth,e.isoDay,this)}yearMonthFromFields(n,t){const e=Ko({...u(n,$n),day:1},hr(this),t);return new po(e.isoYear,e.isoMonth,this,e.isoDay)}monthDayFromFields(n,t){const e=hr(this);let{era:o,eraYear:r,year:i,month:s,monthCode:a,day:c}=u(n,Wn);if(void 0===c)throw new TypeError("required property 'day' missing or undefined");if(void 0!==a?i=pn:void 0!==o&&void 0!==r&&(i=mn(e.id,r,o)),void 0===i){if(void 0===a)throw new TypeError("either year or monthCode required with month");i=e.guessYearForMonthDay(a,c);}const d=Ko({year:i,month:s,monthCode:a,day:c},e,t);return new $o(d.isoMonth,d.isoDay,this,e.normalizeISOYearForMonthDay(d.isoYear))}dateAdd(n,e,o){const r=hr(this),i=function(n,e,o,r){n=pt(n=wt(n,e.years,o,r),e.months,o,r);let i=o.epochMilliseconds(n.year,n.month,n.day);const s=Math.trunc(cn(e).div(t).toNumber());return i=Un(i,7*e.weeks+e.days+s),Fn(i)}(N(Sr,n,o),N(ko,e),r,s$1(o));return new Sr(i.isoYear,i.isoMonth,i.isoDay,this)}dateUntil(n,t,e){const o=hr(this),r=N(Sr,n),i=N(Sr,t),s=d(e).largestUnit,a="auto"===s?6:F(s,6,6,9);return br(this,vr(r,i)),xo(function(n,t,e,o){let r=0,i=0,s=0,a=0;switch(o){case 9:r=function(n,t,e){const[,o,r]=qn(t.year,n.month,n.day,e,0),i=xn(t,n),s=P(t.month,o)||P(t.day,r);return t.year-n.year-(s&&i&&s!==i?i:0)}(n,t,e),n=wt(n,r,e,0);case 8:i=function(n,t,e){let o=0;const r=xn(t,n);if(r){let{year:i}=n;for(;i!==t.year;)o+=e.monthsInYear(i)*r,i+=r;const[,s,a]=qn(t.year,n.month,n.day,e,0);o+=t.month-s;const c=P(t.day,a);c&&r&&c!==r&&(o-=r);}return o}(n,t,e),n=pt(n,i,e,0);}a=Cn(e.epochMilliseconds(n.year,n.month,n.day),e.epochMilliseconds(t.year,t.month,t.day)),7===o&&(s=Math.trunc(a/7),a%=7);return nn({years:r,months:i,weeks:s,days:a,hours:0,minutes:0,seconds:0,milliseconds:0,microseconds:0,nanoseconds:0})}(r,i,o,a))}fields(n){return n.slice()}mergeFields(n,t){return yr(n,t)}toString(){return hr(this).id}}function gr(){return new mr("iso8601")}function yr(n,t){var e;const o={...n,...t};if(void 0!==n.year){delete o.era,delete o.eraYear,delete o.year;let e=!1;void 0===t.era&&void 0===t.eraYear||(o.era=t.era,o.eraYear=t.eraYear,e=!0),void 0!==t.year&&(o.year=t.year,e=!0),e||(o.year=n.year);}if(void 0!==n.monthCode){delete o.monthCode,delete o.month;let e=!1;void 0!==t.month&&(o.month=t.month,e=!0),void 0!==t.monthCode&&(o.monthCode=t.monthCode,e=!0),e||(o.monthCode=n.monthCode);}return void 0!==n.day&&(o.day=null!=(e=t.day)?e:n.day),o}function wr(n,t,e,o){const r=Sn(t,e,o);return ur(r,n.id),n.computeFields(r)}function pr(n){return void 0===n.calendar?gr():N(mr,n.calendar)}function vr(n,t){const{calendar:e}=n;return br(e,t.calendar),e}function Mr(n,t){const e=n.calendar,o=t.calendar;if("iso8601"===e.id)return o;if("iso8601"===o.id)return e;if(e.id!==o.id)throw new RangeError("Non-ISO calendars incompatible");return e}function br(n,t){if(n.toString()!==t.toString())throw new RangeError("Calendars must match")}mt(mr,"Calendar");class Sr extends U{constructor(n,t,e,o=gr()){const r=Hn({isoYear:n,isoMonth:t,isoDay:e},1),i=N(mr,o);!function(n,t){const e=Mn(n);Ge(e.add(e.sign()<0?86399999999999:0)),cr(e,t);}(r,i.toString()),super({...r,calendar:i});}static from(n,t){return s$1(t),n instanceof Sr?Ir(n.getISOFields()):"object"==typeof n?be(n,t):Ir(ne(xt(String(n))))}static compare(n,t){return Rn(N(Sr,n),N(Sr,t))}with(n,t){return De(this,n,t)}withCalendar(n){const t=this.getISOFields();return new Sr(t.isoYear,t.isoMonth,t.isoDay,n)}add(n,t){return this.calendar.dateAdd(this,n,t)}subtract(n,t){return this.calendar.dateAdd(this,N(ko,n).negated(),t)}until(n,t){return Fr(this,N(Sr,n),!1,t)}since(n,t){return Fr(this,N(Sr,n),!0,t)}equals(n){return !Rn(this,N(Sr,n))}toString(n){const t=Jn(n),e=this.getISOFields();return nt(e)+rt(e.calendar.toString(),t)}toZonedDateTime(n){const t=function(n){let t,e;if("string"==typeof n)e=n;else {if("object"!=typeof n)throw new TypeError("Invalid options/timeZone argument");if(void 0!==n.id?e=n:(e=n.timeZone,t=n.plainTime),void 0===e)throw new TypeError("Invalid timeZone argument")}return {plainTime:t,timeZone:e}}(n),e=N(we,t.timeZone),o=void 0===t.plainTime?void 0:N(ho,t.plainTime);return Fo({...this.getISOFields(),...o?o.getISOFields():on,timeZone:e})}toPlainDateTime(n){return Ho({...this.getISOFields(),...mo(n).getISOFields()})}toPlainYearMonth(){return vo(this.getISOFields())}toPlainMonthDay(){return this.calendar.monthDayFromFields(this)}}function Ir(n){return new Sr(n.isoYear,n.isoMonth,n.isoDay,n.calendar)}function Fr(n,t,e,o){return xo(Tr(n,t,vr(n,t),e,O(o,6,6,6,9)))}function Or(n,t,e,o,r){return Uo(Dr(n,t,e,r.largestUnit),n,t,e,o,r)}function Tr(n,t,e,o,r){return Uo(e.dateUntil(n,t,{largestUnit:M[r.largestUnit]}),n,t,e,o,r)}function Dr(n,t,e,o){if(!i(o))return Nr(n,t,o);const r=Ir({...n.getISOFields(),calendar:e});let s,a,c,u,d,l=Ir({...t.getISOFields(),calendar:e});do{a=e.dateUntil(r,l,{largestUnit:M[o]}),s=n.add(a),c=Nr(s,t,5),u=a.sign,d=c.sign;}while(u&&d&&u!==d&&(l=l.add({days:d})));return f=c,{sign:(h=a).sign||f.sign,years:h.years+f.years,months:h.months+f.months,weeks:h.weeks+f.weeks,days:h.days+f.days,hours:h.hours+f.hours,minutes:h.minutes+f.minutes,seconds:h.seconds+f.seconds,milliseconds:h.milliseconds+f.milliseconds,microseconds:h.microseconds+f.microseconds,nanoseconds:h.nanoseconds+f.nanoseconds};var h,f;}function Nr(n,t,e){return dn(On(t).sub(On(n)),e)}mt(Sr,"PlainDate"),dt(Sr),ft(Sr,ht),so(Sr,to({year:"numeric",month:"numeric",day:"numeric",weekday:void 0},{hour:void 0,minute:void 0,second:void 0}));class Yr extends E{constructor(n){super();const t=K(n,!0);!function(n){-1!==G(n,Ae)&&1!==G(n,$e)||Zn();}(t),this[vn]=t;}static from(n){if(n instanceof Yr)return new Yr(n.epochNanoseconds);const t=kt(String(n)),e=t.offsetNanoseconds;if(void 0===e)throw new RangeError("Must specify an offset");return new Yr(Mn(Ln(t,1)).sub(e))}static fromEpochSeconds(n){return new Yr(K(n).mult(1e9))}static fromEpochMilliseconds(n){return new Yr(K(n).mult(1e6))}static fromEpochMicroseconds(n){return new Yr(n*BigInt(1e3))}static fromEpochNanoseconds(n){return new Yr(n)}static compare(n,t){return jn(N(Yr,n),N(Yr,t))}add(n){return new Yr(Mt(this[vn],N(ko,n)))}subtract(n){return new Yr(Mt(this[vn],X(N(ko,n))))}until(n,t){return Er(this,N(Yr,n),t)}since(n,t){return Er(N(Yr,n),this,t)}round(n){const t=T(n,0,5,!0);return new Yr(Ve(this[vn],t))}equals(n){return !jn(this,N(Yr,n))}toString(n){const t=d(n).timeZone;return this.toZonedDateTimeISO(null!=t?t:"UTC").toString({...n,offset:void 0===t?"never":"auto",timeZoneName:"never"})+(void 0===t?"Z":"")}toZonedDateTimeISO(n){return new Io(this.epochNanoseconds,n)}toZonedDateTime(n){if(!h(n))throw new TypeError("Must specify options");if(void 0===n.calendar)throw new TypeError("Must specify a calendar");if(void 0===n.timeZone)throw new TypeError("Must specify a timeZone");return new Io(this.epochNanoseconds,n.timeZone,n.calendar)}}function Er(n,t,o){const r=O(o,3,0,0,5);return xo(function(n,t,o){return dn(q(t.sub(n),e[o.smallestUnit]*o.roundingIncrement,o.roundingFunc),o.largestUnit)}(n[vn],t[vn],r))}mt(Yr,"Instant"),at(Yr),so(Yr,_e({year:"numeric",month:"numeric",day:"numeric",weekday:void 0,hour:"numeric",minute:"2-digit",second:"2-digit"},{timeZoneName:void 0},{}));const Hr={zonedDateTimeISO:function(n){return Fo(Br("iso8601",n))},zonedDateTime:function(n,t){return Fo(Br(n,t))},plainDateTimeISO:function(n){return Ho(Br("iso8601",n))},plainDateTime:function(n,t){return Ho(Br(n,t))},plainDateISO:function(n){return Ir(Br("iso8601",n))},plainDate:function(n,t){return Ir(Br(n,t))},plainTimeISO:function(n){return fo(Br("iso8601",n))},instant:function(){return new Yr($r())},timeZone:Lr};mt(Hr,"Now");function Lr(){return new we((new ae).resolvedOptions().timeZone)}function Br(n,t=Lr()){const e=N(we,t);return {...Oo($r(),e)[0],timeZone:e,calendar:N(mr,n)}}function $r(){return K(Date.now()).mult(1e6)}const Ar={PlainYearMonth:po,PlainMonthDay:$o,PlainDate:Sr,PlainTime:ho,PlainDateTime:qo,ZonedDateTime:Io,Instant:Yr,Calendar:mr,TimeZone:we,Duration:ko,Now:Hr,[Symbol.toStringTag]:"Temporal"};
|
|
2143
2118
|
|
|
2144
|
-
|
|
2145
|
-
const epsilon = calcObliquityCorrection(t);
|
|
2146
|
-
const l0 = calcGeomMeanLongSun(t);
|
|
2147
|
-
const e = calcEccentricityEarthOrbit(t);
|
|
2148
|
-
const m = calcGeomMeanAnomalySun(t);
|
|
2119
|
+
const s=Ar;
|
|
2149
2120
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
const sin2m = Math.sin(2.0 * degToRad(m));
|
|
2158
|
-
|
|
2159
|
-
const Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m;
|
|
2160
|
-
return radToDeg(Etime) * 4.0; // in minutes of time
|
|
2121
|
+
/**
|
|
2122
|
+
* java.lang.Math.toRadians
|
|
2123
|
+
* @private
|
|
2124
|
+
* @param degrees
|
|
2125
|
+
*/
|
|
2126
|
+
function degreesToRadians(degrees) {
|
|
2127
|
+
return (degrees * Math.PI) / 180;
|
|
2161
2128
|
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2129
|
+
/**
|
|
2130
|
+
* java.lang.Math.toDegrees
|
|
2131
|
+
* @private
|
|
2132
|
+
* @param radians
|
|
2133
|
+
*/
|
|
2134
|
+
function radiansToDegrees(radians) {
|
|
2135
|
+
return (radians * 180) / Math.PI;
|
|
2169
2136
|
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2137
|
+
const Long_MIN_VALUE = NaN;
|
|
2138
|
+
/**
|
|
2139
|
+
* A class that contains location information such as latitude and longitude required for astronomical calculations. The
|
|
2140
|
+
* elevation field may not be used by some calculation engines and would be ignored if set. Check the documentation for
|
|
2141
|
+
* specific implementations of the {@link AstronomicalCalculator} to see if elevation is calculated as part of the
|
|
2142
|
+
* algorithm.
|
|
2143
|
+
*
|
|
2144
|
+
* @author © Eliyahu Hershfeld 2004 - 2016
|
|
2145
|
+
* @version 1.1
|
|
2146
|
+
*/
|
|
2147
|
+
class GeoLocation {
|
|
2148
|
+
/**
|
|
2149
|
+
* GeoLocation constructor with parameters for all required fields.
|
|
2150
|
+
*
|
|
2151
|
+
* @param {string} name
|
|
2152
|
+
* The location name for display use such as "Lakewood, NJ"
|
|
2153
|
+
* @param {number} latitude
|
|
2154
|
+
* the latitude in a double format such as 40.095965 for Lakewood, NJ.
|
|
2155
|
+
* <b>Note: </b> For latitudes south of the equator, a negative value should be used.
|
|
2156
|
+
* @param {number} longitude
|
|
2157
|
+
* double the longitude in a double format such as -74.222130 for Lakewood, NJ.
|
|
2158
|
+
* <b>Note: </b> For longitudes east of the <a href="http://en.wikipedia.org/wiki/Prime_Meridian">Prime
|
|
2159
|
+
* Meridian </a> (Greenwich), a negative value should be used.
|
|
2160
|
+
* @param {number} elevation
|
|
2161
|
+
* the elevation above sea level in Meters. Elevation is not used in most algorithms used for calculating
|
|
2162
|
+
* sunrise and set.
|
|
2163
|
+
* @param {string} timeZoneId
|
|
2164
|
+
* the <code>TimeZone</code> for the location.
|
|
2165
|
+
*/
|
|
2166
|
+
constructor(name, latitude, longitude, elevationOrTimeZoneId, timeZoneId) {
|
|
2167
|
+
/**
|
|
2168
|
+
* @private
|
|
2169
|
+
* @see #getLocationName()
|
|
2170
|
+
* @see #setLocationName(String)
|
|
2171
|
+
*/
|
|
2172
|
+
this.locationName = null;
|
|
2173
|
+
let elevation = 0;
|
|
2174
|
+
if (timeZoneId) {
|
|
2175
|
+
elevation = elevationOrTimeZoneId;
|
|
2176
|
+
}
|
|
2177
|
+
else {
|
|
2178
|
+
timeZoneId = elevationOrTimeZoneId;
|
|
2179
|
+
}
|
|
2180
|
+
this.setLocationName(name);
|
|
2181
|
+
this.setLatitude(latitude);
|
|
2182
|
+
this.setLongitude(longitude);
|
|
2183
|
+
this.setElevation(elevation);
|
|
2184
|
+
this.setTimeZone(timeZoneId);
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Method to get the elevation in Meters.
|
|
2188
|
+
*
|
|
2189
|
+
* @return {number} Returns the elevation in Meters.
|
|
2190
|
+
*/
|
|
2191
|
+
getElevation() {
|
|
2192
|
+
return this.elevation;
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Method to set the elevation in Meters <b>above </b> sea level.
|
|
2196
|
+
*
|
|
2197
|
+
* @param {number} elevation
|
|
2198
|
+
* The elevation to set in Meters. An IllegalArgumentException will be thrown if the value is a negative.
|
|
2199
|
+
*/
|
|
2200
|
+
setElevation(elevation) {
|
|
2201
|
+
this.elevation = elevation;
|
|
2202
|
+
}
|
|
2203
|
+
setLatitude(latitude) {
|
|
2204
|
+
if (typeof latitude !== 'number')
|
|
2205
|
+
throw new TypeError('Invalid latitude');
|
|
2206
|
+
if (latitude < -90 || latitude > 90) {
|
|
2207
|
+
throw new RangeError(`Latitude ${latitude} out of range [-90,90]`);
|
|
2208
|
+
}
|
|
2209
|
+
this.latitude = latitude;
|
|
2178
2210
|
}
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2211
|
+
/**
|
|
2212
|
+
* @return {number} Returns the latitude.
|
|
2213
|
+
*/
|
|
2214
|
+
getLatitude() {
|
|
2215
|
+
return this.latitude;
|
|
2216
|
+
}
|
|
2217
|
+
setLongitude(longitude) {
|
|
2218
|
+
if (typeof longitude !== 'number')
|
|
2219
|
+
throw new TypeError('Invalid longitude');
|
|
2220
|
+
if (longitude < -180 || longitude > 180) {
|
|
2221
|
+
throw new RangeError(`Longitude ${longitude} out of range [-180,180]`);
|
|
2222
|
+
}
|
|
2223
|
+
this.longitude = longitude;
|
|
2182
2224
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2225
|
+
/**
|
|
2226
|
+
* @return {number} Returns the longitude.
|
|
2227
|
+
*/
|
|
2228
|
+
getLongitude() {
|
|
2229
|
+
return this.longitude;
|
|
2185
2230
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
return formatDate(date, solNoonLocal);
|
|
2219
|
-
// return timeString(solNoonLocal, 3);
|
|
2220
|
-
}
|
|
2221
|
-
|
|
2222
|
-
function calcSunriseSetUTC(rise, angle, JD, latitude, longitude) {
|
|
2223
|
-
const t = calcTimeJulianCent(JD);
|
|
2224
|
-
const eqTime = calcEquationOfTime(t);
|
|
2225
|
-
const solarDec = calcSunDeclination(t);
|
|
2226
|
-
let hourAngle = calcHourAngle(angle, latitude, solarDec);
|
|
2227
|
-
//alert("HA = " + radToDeg(hourAngle));
|
|
2228
|
-
if (!rise) hourAngle = -hourAngle;
|
|
2229
|
-
const delta = longitude + radToDeg(hourAngle);
|
|
2230
|
-
const timeUTC = 720 - (4.0 * delta) - eqTime; // in minutes
|
|
2231
|
-
return timeUTC;
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
|
-
function calcSunriseSet(rise, angle, JD, date, latitude, longitude)
|
|
2235
|
-
// rise = 1 for sunrise, 0 for sunset
|
|
2236
|
-
{
|
|
2237
|
-
const timeUTC = calcSunriseSetUTC(rise, angle, JD, latitude, longitude);
|
|
2238
|
-
const newTimeUTC = calcSunriseSetUTC(rise, angle, JD + timeUTC / 1440.0, latitude, longitude);
|
|
2239
|
-
if (isNumber(newTimeUTC)) {
|
|
2240
|
-
|
|
2241
|
-
return formatDate(date, newTimeUTC);
|
|
2242
|
-
|
|
2243
|
-
} else { // no sunrise/set found
|
|
2244
|
-
return new Date(NaN);
|
|
2231
|
+
/**
|
|
2232
|
+
* @return {string|null} Returns the location name.
|
|
2233
|
+
*/
|
|
2234
|
+
getLocationName() {
|
|
2235
|
+
return this.locationName;
|
|
2236
|
+
}
|
|
2237
|
+
/**
|
|
2238
|
+
* @param {string|null} name
|
|
2239
|
+
* The setter method for the display name.
|
|
2240
|
+
*/
|
|
2241
|
+
setLocationName(name) {
|
|
2242
|
+
this.locationName = name;
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* @return {string} Returns the timeZone.
|
|
2246
|
+
*/
|
|
2247
|
+
getTimeZone() {
|
|
2248
|
+
return this.timeZoneId;
|
|
2249
|
+
}
|
|
2250
|
+
/**
|
|
2251
|
+
* Method to set the TimeZone. If this is ever set after the GeoLocation is set in the
|
|
2252
|
+
* {@link AstronomicalCalendar}, it is critical that
|
|
2253
|
+
* {@link AstronomicalCalendar#getCalendar()}.
|
|
2254
|
+
* {@link java.util.Calendar#setTimeZone(TimeZone) setTimeZone(TimeZone)} be called in order for the
|
|
2255
|
+
* AstronomicalCalendar to output times in the expected offset. This situation will arise if the
|
|
2256
|
+
* AstronomicalCalendar is ever {@link AstronomicalCalendar#clone() cloned}.
|
|
2257
|
+
*
|
|
2258
|
+
* @param {string} timeZone
|
|
2259
|
+
* The timeZone to set.
|
|
2260
|
+
*/
|
|
2261
|
+
setTimeZone(timeZoneId) {
|
|
2262
|
+
this.timeZoneId = timeZoneId;
|
|
2245
2263
|
}
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
const degreesBelowHorizon = {
|
|
2249
|
-
sunrise: 0.833,
|
|
2250
|
-
sunriseEnd: 0.3,
|
|
2251
|
-
twilight: 6,
|
|
2252
|
-
nauticalTwilight: 12,
|
|
2253
|
-
night: 18,
|
|
2254
|
-
goldenHour: -6
|
|
2255
|
-
};
|
|
2256
|
-
|
|
2257
|
-
class SolarCalc {
|
|
2258
|
-
constructor(date, latitude, longitude) {
|
|
2259
|
-
this.date = date;
|
|
2260
|
-
this.lat = latitude;
|
|
2261
|
-
this.longitude = longitude;
|
|
2262
|
-
|
|
2263
|
-
this.sun = new Sun(date, latitude, longitude);
|
|
2264
|
-
}
|
|
2265
|
-
|
|
2266
|
-
get solarNoon() {
|
|
2267
|
-
return this.sun.solarNoon;
|
|
2268
|
-
}
|
|
2269
|
-
|
|
2270
|
-
get sunrise() {
|
|
2271
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.sunrise, true);
|
|
2272
|
-
}
|
|
2273
|
-
|
|
2274
|
-
get sunset() {
|
|
2275
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.sunrise);
|
|
2276
|
-
}
|
|
2277
|
-
|
|
2278
|
-
get sunriseEnd() {
|
|
2279
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.sunriseEnd, true);
|
|
2280
|
-
}
|
|
2281
|
-
|
|
2282
|
-
get sunsetStart() {
|
|
2283
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.sunriseEnd, false);
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
get civilDawn() {
|
|
2287
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.twilight, true);
|
|
2288
|
-
}
|
|
2289
|
-
|
|
2290
|
-
get dawn() {
|
|
2291
|
-
return this.civilDawn;
|
|
2292
|
-
}
|
|
2293
|
-
|
|
2294
|
-
get civilDusk() {
|
|
2295
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.twilight, false);
|
|
2296
|
-
}
|
|
2297
|
-
|
|
2298
|
-
get dusk() {
|
|
2299
|
-
return this.civilDusk;
|
|
2300
|
-
}
|
|
2301
|
-
|
|
2302
|
-
get nauticalDawn() {
|
|
2303
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.nauticalTwilight, true);
|
|
2304
|
-
}
|
|
2305
|
-
|
|
2306
|
-
get nauticalDusk() {
|
|
2307
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.nauticalTwilight, false);
|
|
2308
|
-
}
|
|
2309
|
-
|
|
2310
|
-
get nightStart() {
|
|
2311
|
-
return this.astronomicalDusk;
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
get astronomicalDusk() {
|
|
2315
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.night, false);
|
|
2316
|
-
}
|
|
2317
|
-
|
|
2318
|
-
get astronomicalDawn() {
|
|
2319
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.night, true);
|
|
2320
|
-
}
|
|
2321
|
-
|
|
2322
|
-
get nightEnd() {
|
|
2323
|
-
return this.astronomicalDawn;
|
|
2324
|
-
}
|
|
2325
|
-
|
|
2326
|
-
get goldenHourStart() {
|
|
2327
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.goldenHour, false);
|
|
2328
|
-
}
|
|
2329
|
-
|
|
2330
|
-
get goldenHourEnd() {
|
|
2331
|
-
return this.sun.timeAtAngle(degreesBelowHorizon.goldenHour, true);
|
|
2332
|
-
}
|
|
2333
2264
|
}
|
|
2334
|
-
|
|
2335
|
-
const _formatters = {};
|
|
2336
|
-
|
|
2337
2265
|
/**
|
|
2266
|
+
* The commonly used average solar refraction. Calendrical Calculations lists a more accurate global average of
|
|
2267
|
+
* 34.478885263888294
|
|
2338
2268
|
* @private
|
|
2339
|
-
* @param {string} tzid
|
|
2340
|
-
* @return {Intl.DateTimeFormat}
|
|
2341
2269
|
*/
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
if (fmt) return fmt;
|
|
2345
|
-
const f = new Intl.DateTimeFormat('en-US', {
|
|
2346
|
-
year: 'numeric',
|
|
2347
|
-
month: '2-digit',
|
|
2348
|
-
day: '2-digit',
|
|
2349
|
-
hour: '2-digit',
|
|
2350
|
-
minute: '2-digit',
|
|
2351
|
-
second: '2-digit',
|
|
2352
|
-
hour12: false,
|
|
2353
|
-
timeZone: tzid
|
|
2354
|
-
});
|
|
2355
|
-
_formatters[tzid] = f;
|
|
2356
|
-
return f;
|
|
2357
|
-
}
|
|
2358
|
-
const dateFormatRegex = /^(\d+).(\d+).(\d+),?\s+(\d+).(\d+).(\d+)/;
|
|
2359
|
-
|
|
2270
|
+
const refraction = 34 / 60;
|
|
2271
|
+
// private double refraction = 34.478885263888294 / 60d;
|
|
2360
2272
|
/**
|
|
2273
|
+
* The commonly used average solar radius in minutes of a degree.
|
|
2361
2274
|
* @private
|
|
2362
|
-
* @param {string} tzid
|
|
2363
|
-
* @param {Date} date
|
|
2364
|
-
* @return {string}
|
|
2365
2275
|
*/
|
|
2366
|
-
|
|
2367
|
-
const str = getFormatter$1(tzid).format(date);
|
|
2368
|
-
const m = dateFormatRegex.exec(str);
|
|
2369
|
-
let hour = m[4];
|
|
2370
|
-
if (hour == '24') hour = '00';
|
|
2371
|
-
m[3] = pad4(m[3]);
|
|
2372
|
-
return `${m[3]}-${m[1]}-${m[2]}T${hour}:${m[5]}:${m[6]}Z`;
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2276
|
+
const solarRadius = 16 / 60;
|
|
2375
2277
|
/**
|
|
2278
|
+
* The commonly used average earth radius in KM. At this time, this only affects elevation adjustment and not the
|
|
2279
|
+
* sunrise and sunset calculations. The value currently defaults to 6356.9 KM.
|
|
2376
2280
|
* @private
|
|
2377
|
-
* @param {string} tzid
|
|
2378
|
-
* @param {Date} date
|
|
2379
|
-
* @return {number}
|
|
2380
2281
|
*/
|
|
2381
|
-
|
|
2382
|
-
const utcStr = getPseudoISO('UTC', date);
|
|
2383
|
-
const localStr = getPseudoISO(tzid, date);
|
|
2384
|
-
const diffMs = new Date(utcStr).getTime() - new Date(localStr).getTime();
|
|
2385
|
-
return Math.ceil(diffMs / 1000 / 60);
|
|
2386
|
-
}
|
|
2387
|
-
|
|
2282
|
+
const earthRadius = 6356.9; // in KM
|
|
2388
2283
|
/**
|
|
2389
|
-
*
|
|
2390
|
-
*
|
|
2391
|
-
*
|
|
2284
|
+
* Implementation of sunrise and sunset methods to calculate astronomical times based on the <a
|
|
2285
|
+
* href="http://noaa.gov">NOAA</a> algorithm. This calculator uses the Java algorithm based on the implementation by <a
|
|
2286
|
+
* href="http://noaa.gov">NOAA - National Oceanic and Atmospheric Administration</a>'s <a href =
|
|
2287
|
+
* "http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html">Surface Radiation Research Branch</a>. NOAA's <a
|
|
2288
|
+
* href="http://www.srrb.noaa.gov/highlights/sunrise/solareqns.PDF">implementation</a> is based on equations from <a
|
|
2289
|
+
* href="http://www.willbell.com/math/mc1.htm">Astronomical Algorithms</a> by <a
|
|
2290
|
+
* href="http://en.wikipedia.org/wiki/Jean_Meeus">Jean Meeus</a>. Added to the algorithm is an adjustment of the zenith
|
|
2291
|
+
* to account for elevation. The algorithm can be found in the <a
|
|
2292
|
+
* href="http://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation</a> article.
|
|
2293
|
+
*
|
|
2294
|
+
* @author © Eliyahu Hershfeld 2011 - 2019
|
|
2392
2295
|
*/
|
|
2393
|
-
|
|
2296
|
+
class NOAACalculator {
|
|
2297
|
+
/**
|
|
2298
|
+
* A constructor that takes in <a href="http://en.wikipedia.org/wiki/Geolocation">geolocation</a> information as a
|
|
2299
|
+
* parameter. The default {@link AstronomicalCalculator#getDefault() AstronomicalCalculator} used for solar
|
|
2300
|
+
* calculations is the the {@link NOAACalculator}.
|
|
2301
|
+
*
|
|
2302
|
+
* @param {GeoLocation} geoLocation
|
|
2303
|
+
* The location information used for calculating astronomical sun times.
|
|
2304
|
+
* @param {Temporal.PlainDate} date
|
|
2305
|
+
*
|
|
2306
|
+
* @see #setAstronomicalCalculator(AstronomicalCalculator) for changing the calculator class.
|
|
2307
|
+
*/
|
|
2308
|
+
constructor(geoLocation, date) {
|
|
2309
|
+
this.date = date;
|
|
2310
|
+
this.geoLocation = geoLocation;
|
|
2311
|
+
}
|
|
2312
|
+
/**
|
|
2313
|
+
* The getSunrise method Returns a `Date` representing the
|
|
2314
|
+
* {@link AstronomicalCalculator#getElevationAdjustment(double) elevation adjusted} sunrise time. The zenith used
|
|
2315
|
+
* for the calculation uses {@link #GEOMETRIC_ZENITH geometric zenith} of 90° plus
|
|
2316
|
+
* {@link AstronomicalCalculator#getElevationAdjustment(double)}. This is adjusted by the
|
|
2317
|
+
* {@link AstronomicalCalculator} to add approximately 50/60 of a degree to account for 34 archminutes of refraction
|
|
2318
|
+
* and 16 archminutes for the sun's radius for a total of {@link AstronomicalCalculator#adjustZenith 90.83333°}.
|
|
2319
|
+
* See documentation for the specific implementation of the {@link AstronomicalCalculator} that you are using.
|
|
2320
|
+
*
|
|
2321
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` representing the exact sunrise time. If the calculation can't be computed such as
|
|
2322
|
+
* in the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it
|
|
2323
|
+
* does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2324
|
+
* @see AstronomicalCalculator#adjustZenith
|
|
2325
|
+
* @see #getSeaLevelSunrise()
|
|
2326
|
+
* @see AstronomicalCalendar#getUTCSunrise
|
|
2327
|
+
*/
|
|
2328
|
+
getSunrise() {
|
|
2329
|
+
const sunrise = this.getUTCSunrise0(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2330
|
+
if (Number.isNaN(sunrise))
|
|
2331
|
+
return null;
|
|
2332
|
+
return this.getDateFromTime(sunrise, true);
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* A method that returns the sunrise without {@link AstronomicalCalculator#getElevationAdjustment(double) elevation
|
|
2336
|
+
* adjustment}. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible light,
|
|
2337
|
+
* something that is not affected by elevation. This method returns sunrise calculated at sea level. This forms the
|
|
2338
|
+
* base for dawn calculations that are calculated as a dip below the horizon before sunrise.
|
|
2339
|
+
*
|
|
2340
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` representing the exact sea-level sunrise time. If the calculation can't be computed
|
|
2341
|
+
* such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one
|
|
2342
|
+
* where it does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2343
|
+
* @see AstronomicalCalendar#getSunrise
|
|
2344
|
+
* @see AstronomicalCalendar#getUTCSeaLevelSunrise
|
|
2345
|
+
* @see #getSeaLevelSunset()
|
|
2346
|
+
*/
|
|
2347
|
+
getSeaLevelSunrise() {
|
|
2348
|
+
const sunrise = this.getUTCSeaLevelSunrise(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2349
|
+
if (Number.isNaN(sunrise))
|
|
2350
|
+
return null;
|
|
2351
|
+
return this.getDateFromTime(sunrise, true);
|
|
2352
|
+
}
|
|
2353
|
+
/**
|
|
2354
|
+
* A method that returns the beginning of civil twilight (dawn) using a zenith of {@link #CIVIL_ZENITH 96°}.
|
|
2355
|
+
*
|
|
2356
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of civil twilight using a zenith of 96°. If the calculation
|
|
2357
|
+
* can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2358
|
+
* @see #CIVIL_ZENITH
|
|
2359
|
+
*/
|
|
2360
|
+
getBeginCivilTwilight() {
|
|
2361
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.CIVIL_ZENITH);
|
|
2362
|
+
}
|
|
2363
|
+
/**
|
|
2364
|
+
* A method that returns the beginning of nautical twilight using a zenith of {@link #NAUTICAL_ZENITH 102°}.
|
|
2365
|
+
*
|
|
2366
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of nautical twilight using a zenith of 102°. If the
|
|
2367
|
+
* calculation can't be computed null will be returned. See detailed explanation on top of the page.
|
|
2368
|
+
* @see #NAUTICAL_ZENITH
|
|
2369
|
+
*/
|
|
2370
|
+
getBeginNauticalTwilight() {
|
|
2371
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.NAUTICAL_ZENITH);
|
|
2372
|
+
}
|
|
2373
|
+
/**
|
|
2374
|
+
* A method that returns the beginning of astronomical twilight using a zenith of {@link #ASTRONOMICAL_ZENITH
|
|
2375
|
+
* 108°}.
|
|
2376
|
+
*
|
|
2377
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the beginning of astronomical twilight using a zenith of 108°. If the
|
|
2378
|
+
* calculation can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2379
|
+
* @see #ASTRONOMICAL_ZENITH
|
|
2380
|
+
*/
|
|
2381
|
+
getBeginAstronomicalTwilight() {
|
|
2382
|
+
return this.getSunriseOffsetByDegrees(NOAACalculator.ASTRONOMICAL_ZENITH);
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* The getSunset method Returns a `Date` representing the
|
|
2386
|
+
* {@link AstronomicalCalculator#getElevationAdjustment(double) elevation adjusted} sunset time. The zenith used for
|
|
2387
|
+
* the calculation uses {@link #GEOMETRIC_ZENITH geometric zenith} of 90° plus
|
|
2388
|
+
* {@link AstronomicalCalculator#getElevationAdjustment(double)}. This is adjusted by the
|
|
2389
|
+
* {@link AstronomicalCalculator} to add approximately 50/60 of a degree to account for 34 archminutes of refraction
|
|
2390
|
+
* and 16 archminutes for the sun's radius for a total of {@link AstronomicalCalculator#adjustZenith 90.83333°}.
|
|
2391
|
+
* See documentation for the specific implementation of the {@link AstronomicalCalculator} that you are using. Note:
|
|
2392
|
+
* In certain cases the calculates sunset will occur before sunrise. This will typically happen when a timezone
|
|
2393
|
+
* other than the local timezone is used (calculating Los Angeles sunset using a GMT timezone for example). In this
|
|
2394
|
+
* case the sunset date will be incremented to the following date.
|
|
2395
|
+
*
|
|
2396
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing the exact sunset time. If the calculation can't be computed such as in
|
|
2397
|
+
* the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it
|
|
2398
|
+
* does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2399
|
+
* @see AstronomicalCalculator#adjustZenith
|
|
2400
|
+
* @see #getSeaLevelSunset()
|
|
2401
|
+
* @see AstronomicalCalendar#getUTCSunset
|
|
2402
|
+
*/
|
|
2403
|
+
getSunset() {
|
|
2404
|
+
const sunset = this.getUTCSunset0(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2405
|
+
if (Number.isNaN(sunset))
|
|
2406
|
+
return null;
|
|
2407
|
+
return this.getDateFromTime(sunset, false);
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2410
|
+
* A method that returns the sunset without {@link AstronomicalCalculator#getElevationAdjustment(double) elevation
|
|
2411
|
+
* adjustment}. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible light,
|
|
2412
|
+
* something that is not affected by elevation. This method returns sunset calculated at sea level. This forms the
|
|
2413
|
+
* base for dusk calculations that are calculated as a dip below the horizon after sunset.
|
|
2414
|
+
*
|
|
2415
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing the exact sea-level sunset time. If the calculation can't be computed
|
|
2416
|
+
* such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one
|
|
2417
|
+
* where it does not set, a null will be returned. See detailed explanation on top of the page.
|
|
2418
|
+
* @see AstronomicalCalendar#getSunset
|
|
2419
|
+
* @see AstronomicalCalendar#getUTCSeaLevelSunset 2see {@link #getSunset()}
|
|
2420
|
+
*/
|
|
2421
|
+
getSeaLevelSunset() {
|
|
2422
|
+
const sunset = this.getUTCSeaLevelSunset(NOAACalculator.GEOMETRIC_ZENITH);
|
|
2423
|
+
if (Number.isNaN(sunset))
|
|
2424
|
+
return null;
|
|
2425
|
+
return this.getDateFromTime(sunset, false);
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* A method that returns the end of civil twilight using a zenith of {@link #CIVIL_ZENITH 96°}.
|
|
2429
|
+
*
|
|
2430
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of civil twilight using a zenith of {@link #CIVIL_ZENITH 96°}. If
|
|
2431
|
+
* the calculation can't be computed, null will be returned. See detailed explanation on top of the page.
|
|
2432
|
+
* @see #CIVIL_ZENITH
|
|
2433
|
+
*/
|
|
2434
|
+
getEndCivilTwilight() {
|
|
2435
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.CIVIL_ZENITH);
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* A method that returns the end of nautical twilight using a zenith of {@link #NAUTICAL_ZENITH 102°}.
|
|
2439
|
+
*
|
|
2440
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of nautical twilight using a zenith of {@link #NAUTICAL_ZENITH 102°}
|
|
2441
|
+
* . If the calculation can't be computed, null will be returned. See detailed explanation on top of the
|
|
2442
|
+
* page.
|
|
2443
|
+
* @see #NAUTICAL_ZENITH
|
|
2444
|
+
*/
|
|
2445
|
+
getEndNauticalTwilight() {
|
|
2446
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.NAUTICAL_ZENITH);
|
|
2447
|
+
}
|
|
2448
|
+
/**
|
|
2449
|
+
* A method that returns the end of astronomical twilight using a zenith of {@link #ASTRONOMICAL_ZENITH 108°}.
|
|
2450
|
+
*
|
|
2451
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the end of astronomical twilight using a zenith of {@link #ASTRONOMICAL_ZENITH
|
|
2452
|
+
* 108°}. If the calculation can't be computed, null will be returned. See detailed explanation on top
|
|
2453
|
+
* of the page.
|
|
2454
|
+
* @see #ASTRONOMICAL_ZENITH
|
|
2455
|
+
*/
|
|
2456
|
+
getEndAstronomicalTwilight() {
|
|
2457
|
+
return this.getSunsetOffsetByDegrees(NOAACalculator.ASTRONOMICAL_ZENITH);
|
|
2458
|
+
}
|
|
2459
|
+
/**
|
|
2460
|
+
* A utility method that returns a date offset by the offset time passed in. Please note that the level of light
|
|
2461
|
+
* during twilight is not affected by elevation, so if this is being used to calculate an offset before sunrise or
|
|
2462
|
+
* after sunset with the intent of getting a rough "level of light" calculation, the sunrise or sunset time passed
|
|
2463
|
+
* to this method should be sea level sunrise and sunset.
|
|
2464
|
+
*
|
|
2465
|
+
* @param {Temporal.ZonedDateTime | null} time
|
|
2466
|
+
* the start time
|
|
2467
|
+
* @param {number} offset
|
|
2468
|
+
* the offset in milliseconds to add to the time.
|
|
2469
|
+
* @return {Temporal.ZonedDateTime | null} the `Date` with the offset in milliseconds added to it
|
|
2470
|
+
*/
|
|
2471
|
+
static getTimeOffset(time, offset) {
|
|
2472
|
+
if (time === null || offset === Long_MIN_VALUE || Number.isNaN(offset)) {
|
|
2473
|
+
return null;
|
|
2474
|
+
}
|
|
2475
|
+
return time.add({ milliseconds: offset });
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* A utility method that returns the time of an offset by degrees below or above the horizon of
|
|
2479
|
+
* {@link #getSunrise() sunrise}. Note that the degree offset is from the vertical, so for a calculation of 14°
|
|
2480
|
+
* before sunrise, an offset of 14 + {@link #GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2481
|
+
*
|
|
2482
|
+
* @param {number} offsetZenith
|
|
2483
|
+
* the degrees before {@link #getSunrise()} to use in the calculation. For time after sunrise use
|
|
2484
|
+
* negative numbers. Note that the degree offset is from the vertical, so for a calculation of 14°
|
|
2485
|
+
* before sunrise, an offset of 14 + {@link #GEOMETRIC_ZENITH} = 104 would have to be passed as a
|
|
2486
|
+
* parameter.
|
|
2487
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` of the offset after (or before) {@link #getSunrise()}. If the calculation
|
|
2488
|
+
* can't be computed such as in the Arctic Circle where there is at least one day a year where the sun does
|
|
2489
|
+
* not rise, and one where it does not set, a null will be returned. See detailed explanation on top of the
|
|
2490
|
+
* page.
|
|
2491
|
+
*/
|
|
2492
|
+
getSunriseOffsetByDegrees(offsetZenith) {
|
|
2493
|
+
const dawn = this.getUTCSunrise0(offsetZenith);
|
|
2494
|
+
if (Number.isNaN(dawn))
|
|
2495
|
+
return null;
|
|
2496
|
+
return this.getDateFromTime(dawn, true);
|
|
2497
|
+
}
|
|
2498
|
+
/**
|
|
2499
|
+
* A utility method that returns the time of an offset by degrees below or above the horizon of {@link #getSunset()
|
|
2500
|
+
* sunset}. Note that the degree offset is from the vertical, so for a calculation of 14° after sunset, an
|
|
2501
|
+
* offset of 14 + {@link #GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2502
|
+
*
|
|
2503
|
+
* @param {number} offsetZenith
|
|
2504
|
+
* the degrees after {@link #getSunset()} to use in the calculation. For time before sunset use negative
|
|
2505
|
+
* numbers. Note that the degree offset is from the vertical, so for a calculation of 14° after
|
|
2506
|
+
* sunset, an offset of 14 + {@link #GEOMETRIC_ZENITH} = 104 would have to be passed as a parameter.
|
|
2507
|
+
* @return {Temporal.ZonedDateTime | null} The `Date`of the offset after (or before) {@link #getSunset()}. If the calculation can't
|
|
2508
|
+
* be computed such as in the Arctic Circle where there is at least one day a year where the sun does not
|
|
2509
|
+
* rise, and one where it does not set, a null will be returned. See detailed explanation on top of the
|
|
2510
|
+
* page.
|
|
2511
|
+
*/
|
|
2512
|
+
getSunsetOffsetByDegrees(offsetZenith) {
|
|
2513
|
+
const sunset = this.getUTCSunset0(offsetZenith);
|
|
2514
|
+
if (Number.isNaN(sunset))
|
|
2515
|
+
return null;
|
|
2516
|
+
return this.getDateFromTime(sunset, false);
|
|
2517
|
+
}
|
|
2518
|
+
/**
|
|
2519
|
+
* A method that returns the sunrise in UTC time without correction for time zone offset from GMT and without using
|
|
2520
|
+
* daylight savings time.
|
|
2521
|
+
*
|
|
2522
|
+
* @param {number} zenith
|
|
2523
|
+
* the degrees below the horizon. For time after sunrise use negative numbers.
|
|
2524
|
+
* @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
|
|
2525
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2526
|
+
* not set, {@link Double#NaN} will be returned. See detailed explanation on top of the page.
|
|
2527
|
+
*/
|
|
2528
|
+
getUTCSunrise0(zenith) {
|
|
2529
|
+
return this.getUTCSunrise(this.getAdjustedDate(), this.geoLocation, zenith, true);
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* A method that returns the sunrise in UTC time without correction for time zone offset from GMT and without using
|
|
2533
|
+
* daylight savings time. Non-sunrise and sunset calculations such as dawn and dusk, depend on the amount of visible
|
|
2534
|
+
* light, something that is not affected by elevation. This method returns UTC sunrise calculated at sea level. This
|
|
2535
|
+
* forms the base for dawn calculations that are calculated as a dip below the horizon before sunrise.
|
|
2536
|
+
*
|
|
2537
|
+
* @param {number} zenith
|
|
2538
|
+
* the degrees below the horizon. For time after sunrise use negative numbers.
|
|
2539
|
+
* @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
|
|
2540
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2541
|
+
* not set, {@link Double#NaN} will be returned. See detailed explanation on top of the page.
|
|
2542
|
+
* @see AstronomicalCalendar#getUTCSunrise
|
|
2543
|
+
* @see AstronomicalCalendar#getUTCSeaLevelSunset
|
|
2544
|
+
*/
|
|
2545
|
+
getUTCSeaLevelSunrise(zenith) {
|
|
2546
|
+
return this.getUTCSunrise(this.getAdjustedDate(), this.geoLocation, zenith, false);
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* A method that returns the sunset in UTC time without correction for time zone offset from GMT and without using
|
|
2550
|
+
* daylight savings time.
|
|
2551
|
+
*
|
|
2552
|
+
* @param {number} zenith
|
|
2553
|
+
* the degrees below the horizon. For time after sunset use negative numbers.
|
|
2554
|
+
* @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
|
|
2555
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2556
|
+
* not set, {@link Double#NaN} will be returned. See detailed explanation on top of the page.
|
|
2557
|
+
* @see AstronomicalCalendar#getUTCSeaLevelSunset
|
|
2558
|
+
*/
|
|
2559
|
+
getUTCSunset0(zenith) {
|
|
2560
|
+
return this.getUTCSunset(this.getAdjustedDate(), this.geoLocation, zenith, true);
|
|
2561
|
+
}
|
|
2562
|
+
/**
|
|
2563
|
+
* A method that returns the sunset in UTC time without correction for elevation, time zone offset from GMT and
|
|
2564
|
+
* without using daylight savings time. Non-sunrise and sunset calculations such as dawn and dusk, depend on the
|
|
2565
|
+
* amount of visible light, something that is not affected by elevation. This method returns UTC sunset calculated
|
|
2566
|
+
* at sea level. This forms the base for dusk calculations that are calculated as a dip below the horizon after
|
|
2567
|
+
* sunset.
|
|
2568
|
+
*
|
|
2569
|
+
* @param {number} zenith
|
|
2570
|
+
* the degrees below the horizon. For time before sunset use negative numbers.
|
|
2571
|
+
* @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
|
|
2572
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2573
|
+
* not set, {@link Double#NaN} will be returned. See detailed explanation on top of the page.
|
|
2574
|
+
* @see AstronomicalCalendar#getUTCSunset
|
|
2575
|
+
* @see AstronomicalCalendar#getUTCSeaLevelSunrise
|
|
2576
|
+
*/
|
|
2577
|
+
getUTCSeaLevelSunset(zenith) {
|
|
2578
|
+
return this.getUTCSunset(this.getAdjustedDate(), this.geoLocation, zenith, false);
|
|
2579
|
+
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Adjusts the <code>Calendar</code> to deal with edge cases where the location crosses the antimeridian.
|
|
2582
|
+
* @private
|
|
2583
|
+
* @see GeoLocation#getAntimeridianAdjustment()
|
|
2584
|
+
* @return the adjusted Calendar
|
|
2585
|
+
*/
|
|
2586
|
+
getAdjustedDate() {
|
|
2587
|
+
return this.date;
|
|
2588
|
+
}
|
|
2589
|
+
/**
|
|
2590
|
+
* Method to return the adjustment to the zenith required to account for the elevation. Since a person at a higher
|
|
2591
|
+
* elevation can see farther below the horizon, the calculation for sunrise / sunset is calculated below the horizon
|
|
2592
|
+
* used at sea level. This is only used for sunrise and sunset and not times before or after it such as
|
|
2593
|
+
* {@link AstronomicalCalendar#getBeginNauticalTwilight() nautical twilight} since those
|
|
2594
|
+
* calculations are based on the level of available light at the given dip below the horizon, something that is not
|
|
2595
|
+
* affected by elevation, the adjustment should only made if the zenith == 90° {@link #adjustZenith adjusted}
|
|
2596
|
+
* for refraction and solar radius. The algorithm used is
|
|
2597
|
+
*
|
|
2598
|
+
* <pre>
|
|
2599
|
+
* elevationAdjustment = Math.toDegrees(Math.acos(earthRadiusInMeters / (earthRadiusInMeters + elevationMeters)));
|
|
2600
|
+
* </pre>
|
|
2601
|
+
*
|
|
2602
|
+
* The source of this algorithm is <a href="http://www.calendarists.com">Calendrical Calculations</a> by Edward M.
|
|
2603
|
+
* Reingold and Nachum Dershowitz. An alternate algorithm that produces an almost identical (but not accurate)
|
|
2604
|
+
* result found in Ma'aglay Tzedek by Moishe Kosower and other sources is:
|
|
2605
|
+
*
|
|
2606
|
+
* <pre>
|
|
2607
|
+
* elevationAdjustment = 0.0347 * Math.sqrt(elevationMeters);
|
|
2608
|
+
* </pre>
|
|
2609
|
+
*
|
|
2610
|
+
* @param {number} elevation
|
|
2611
|
+
* elevation in Meters.
|
|
2612
|
+
* @return {number} the adjusted zenith
|
|
2613
|
+
*/
|
|
2614
|
+
getElevationAdjustment(elevation) {
|
|
2615
|
+
// double elevationAdjustment = 0.0347 * Math.sqrt(elevation);
|
|
2616
|
+
const elevationAdjustment = radiansToDegrees(Math.acos(earthRadius / (earthRadius + elevation / 1000)));
|
|
2617
|
+
return elevationAdjustment;
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Adjusts the zenith of astronomical sunrise and sunset to account for solar refraction, solar radius and
|
|
2621
|
+
* elevation. The value for Sun's zenith and true rise/set Zenith (used in this class and subclasses) is the angle
|
|
2622
|
+
* that the center of the Sun makes to a line perpendicular to the Earth's surface. If the Sun were a point and the
|
|
2623
|
+
* Earth were without an atmosphere, true sunset and sunrise would correspond to a 90° zenith. Because the Sun
|
|
2624
|
+
* is not a point, and because the atmosphere refracts light, this 90° zenith does not, in fact, correspond to
|
|
2625
|
+
* true sunset or sunrise, instead the centre of the Sun's disk must lie just below the horizon for the upper edge
|
|
2626
|
+
* to be obscured. This means that a zenith of just above 90° must be used. The Sun subtends an angle of 16
|
|
2627
|
+
* minutes of arc (this can be changed via the {@link #setSolarRadius(double)} method , and atmospheric refraction
|
|
2628
|
+
* accounts for 34 minutes or so (this can be changed via the {@link #setRefraction(double)} method), giving a total
|
|
2629
|
+
* of 50 arcminutes. The total value for ZENITH is 90+(5/6) or 90.8333333° for true sunrise/sunset. Since a
|
|
2630
|
+
* person at an elevation can see blow the horizon of a person at sea level, this will also adjust the zenith to
|
|
2631
|
+
* account for elevation if available. Note that this will only adjust the value if the zenith is exactly 90 degrees.
|
|
2632
|
+
* For values below and above this no correction is done. As an example, astronomical twilight is when the sun is
|
|
2633
|
+
* 18° below the horizon or {@link AstronomicalCalendar#ASTRONOMICAL_ZENITH 108°
|
|
2634
|
+
* below the zenith}. This is traditionally calculated with none of the above mentioned adjustments. The same goes
|
|
2635
|
+
* for various <em>tzais</em> and <em>alos</em> times such as the
|
|
2636
|
+
* {@link ZmanimCalendar#ZENITH_16_POINT_1 16.1°} dip used in
|
|
2637
|
+
* {@link ComplexZmanimCalendar#getAlos16Point1Degrees()}.
|
|
2638
|
+
*
|
|
2639
|
+
* @param {number} zenith
|
|
2640
|
+
* the azimuth below the vertical zenith of 90°. For sunset typically the {@link #adjustZenith
|
|
2641
|
+
* zenith} used for the calculation uses geometric zenith of 90° and {@link #adjustZenith adjusts}
|
|
2642
|
+
* this slightly to account for solar refraction and the sun's radius. Another example would be
|
|
2643
|
+
* {@link AstronomicalCalendar#getEndNauticalTwilight()} that passes
|
|
2644
|
+
* {@link AstronomicalCalendar#NAUTICAL_ZENITH} to this method.
|
|
2645
|
+
* @param {number} elevation
|
|
2646
|
+
* elevation in Meters.
|
|
2647
|
+
* @return {number} The zenith adjusted to include the {@link #getSolarRadius sun's radius}, {@link #getRefraction
|
|
2648
|
+
* refraction} and {@link #getElevationAdjustment elevation} adjustment. This will only be adjusted for
|
|
2649
|
+
* sunrise and sunset (if the zenith == 90°)
|
|
2650
|
+
* @see #getElevationAdjustment(double)
|
|
2651
|
+
*/
|
|
2652
|
+
adjustZenith(zenith, elevation) {
|
|
2653
|
+
let adjustedZenith = zenith;
|
|
2654
|
+
if (zenith === NOAACalculator.GEOMETRIC_ZENITH) {
|
|
2655
|
+
// only adjust if it is exactly sunrise or sunset
|
|
2656
|
+
adjustedZenith =
|
|
2657
|
+
zenith +
|
|
2658
|
+
(solarRadius + refraction + this.getElevationAdjustment(elevation));
|
|
2659
|
+
}
|
|
2660
|
+
return adjustedZenith;
|
|
2661
|
+
}
|
|
2662
|
+
/**
|
|
2663
|
+
* @see AstronomicalCalculator#getUTCSunrise(Calendar, GeoLocation, double, boolean)
|
|
2664
|
+
*/
|
|
2665
|
+
getUTCSunrise(date, geoLocation, zenith, adjustForElevation) {
|
|
2666
|
+
const elevation = adjustForElevation
|
|
2667
|
+
? geoLocation.getElevation()
|
|
2668
|
+
: 0;
|
|
2669
|
+
const adjustedZenith = this.adjustZenith(zenith, elevation);
|
|
2670
|
+
let sunrise = NOAACalculator.getSunriseUTC(NOAACalculator.getJulianDay(date), geoLocation.getLatitude(), -geoLocation.getLongitude(), adjustedZenith);
|
|
2671
|
+
sunrise = sunrise / 60;
|
|
2672
|
+
// ensure that the time is >= 0 and < 24
|
|
2673
|
+
while (sunrise < 0) {
|
|
2674
|
+
sunrise += 24;
|
|
2675
|
+
}
|
|
2676
|
+
while (sunrise >= 24) {
|
|
2677
|
+
sunrise -= 24;
|
|
2678
|
+
}
|
|
2679
|
+
return sunrise;
|
|
2680
|
+
}
|
|
2681
|
+
/**
|
|
2682
|
+
* @see AstronomicalCalculator#getUTCSunset(Calendar, GeoLocation, double, boolean)
|
|
2683
|
+
*/
|
|
2684
|
+
getUTCSunset(date, geoLocation, zenith, adjustForElevation) {
|
|
2685
|
+
const elevation = adjustForElevation
|
|
2686
|
+
? geoLocation.getElevation()
|
|
2687
|
+
: 0;
|
|
2688
|
+
const adjustedZenith = this.adjustZenith(zenith, elevation);
|
|
2689
|
+
let sunset = NOAACalculator.getSunsetUTC(NOAACalculator.getJulianDay(date), geoLocation.getLatitude(), -geoLocation.getLongitude(), adjustedZenith);
|
|
2690
|
+
sunset = sunset / 60;
|
|
2691
|
+
// ensure that the time is >= 0 and < 24
|
|
2692
|
+
while (sunset < 0) {
|
|
2693
|
+
sunset += 24;
|
|
2694
|
+
}
|
|
2695
|
+
while (sunset >= 24) {
|
|
2696
|
+
sunset -= 24;
|
|
2697
|
+
}
|
|
2698
|
+
return sunset;
|
|
2699
|
+
}
|
|
2700
|
+
/**
|
|
2701
|
+
* A utility method that will allow the calculation of a temporal (solar) hour based on the sunrise and sunset
|
|
2702
|
+
* passed as parameters to this method. An example of the use of this method would be the calculation of a
|
|
2703
|
+
* non-elevation adjusted temporal hour by passing in {@link #getSeaLevelSunrise() sea level sunrise} and
|
|
2704
|
+
* {@link #getSeaLevelSunset() sea level sunset} as parameters.
|
|
2705
|
+
*
|
|
2706
|
+
* @param {Temporal.ZonedDateTime | null} startOfDay
|
|
2707
|
+
* The start of the day.
|
|
2708
|
+
* @param {Temporal.ZonedDateTime | null} endOfDay
|
|
2709
|
+
* The end of the day.
|
|
2710
|
+
*
|
|
2711
|
+
* @return {number} the <code>long</code> millisecond length of the temporal hour. If the calculation can't be computed a
|
|
2712
|
+
* {@link Long#MIN_VALUE} will be returned. See detailed explanation on top of the page.
|
|
2713
|
+
*
|
|
2714
|
+
* @see #getTemporalHour()
|
|
2715
|
+
*/
|
|
2716
|
+
getTemporalHour(startOfDay = this.getSeaLevelSunrise(), endOfDay = this.getSeaLevelSunset()) {
|
|
2717
|
+
if (startOfDay === null || endOfDay === null) {
|
|
2718
|
+
return Long_MIN_VALUE;
|
|
2719
|
+
}
|
|
2720
|
+
const delta = endOfDay.epochMilliseconds - startOfDay.epochMilliseconds;
|
|
2721
|
+
return Math.floor(delta / 12);
|
|
2722
|
+
}
|
|
2723
|
+
/**
|
|
2724
|
+
* A method that returns sundial or solar noon. It occurs when the Sun is <a href
|
|
2725
|
+
* ="http://en.wikipedia.org/wiki/Transit_%28astronomy%29">transiting</a> the <a
|
|
2726
|
+
* href="http://en.wikipedia.org/wiki/Meridian_%28astronomy%29">celestial meridian</a>. In this class it is
|
|
2727
|
+
* calculated as halfway between the sunrise and sunset passed to this method. This time can be slightly off the
|
|
2728
|
+
* real transit time due to changes in declination (the lengthening or shortening day).
|
|
2729
|
+
*
|
|
2730
|
+
* @param {Temporal.ZonedDateTime | null} startOfDay
|
|
2731
|
+
* the start of day for calculating the sun's transit. This can be sea level sunrise, visual sunrise (or
|
|
2732
|
+
* any arbitrary start of day) passed to this method.
|
|
2733
|
+
* @param {Temporal.ZonedDateTime | null} endOfDay
|
|
2734
|
+
* the end of day for calculating the sun's transit. This can be sea level sunset, visual sunset (or any
|
|
2735
|
+
* arbitrary end of day) passed to this method.
|
|
2736
|
+
*
|
|
2737
|
+
* @return {Temporal.ZonedDateTime | null} The `Date` representing Sun's transit. If the calculation can't be computed such as in the
|
|
2738
|
+
* Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
|
|
2739
|
+
* not set, null will be returned. See detailed explanation on top of the page.
|
|
2740
|
+
*/
|
|
2741
|
+
getSunTransit(startOfDay = this.getSeaLevelSunrise(), endOfDay = this.getSeaLevelSunset()) {
|
|
2742
|
+
const temporalHour = this.getTemporalHour(startOfDay, endOfDay);
|
|
2743
|
+
return NOAACalculator.getTimeOffset(startOfDay, temporalHour * 6);
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* A method that returns a `Date` from the time passed in as a parameter.
|
|
2747
|
+
* @protected
|
|
2748
|
+
* @param {number} time
|
|
2749
|
+
* The time to be set as the time for the `Date`. The time expected is in the format: 18.75
|
|
2750
|
+
* for 6:45:00 PM.
|
|
2751
|
+
* @param {boolean} isSunrise true if the time is sunrise, and false if it is sunset
|
|
2752
|
+
* @return {Temporal.ZonedDateTime | null} The Date.
|
|
2753
|
+
*/
|
|
2754
|
+
getDateFromTime(time, isSunrise) {
|
|
2755
|
+
if (Number.isNaN(time)) {
|
|
2756
|
+
return null;
|
|
2757
|
+
}
|
|
2758
|
+
let calculatedTime = time;
|
|
2759
|
+
let cal = this.getAdjustedDate();
|
|
2760
|
+
// let cal = new Temporal.PlainDate(adj.year, adj.month, adj.day);
|
|
2761
|
+
const hours = Math.trunc(calculatedTime); // retain only the hours
|
|
2762
|
+
calculatedTime -= hours;
|
|
2763
|
+
const minutes = Math.trunc((calculatedTime *= 60)); // retain only the minutes
|
|
2764
|
+
calculatedTime -= minutes;
|
|
2765
|
+
const seconds = Math.trunc((calculatedTime *= 60)); // retain only the seconds
|
|
2766
|
+
calculatedTime -= seconds; // remaining milliseconds
|
|
2767
|
+
// Check if a date transition has occurred, or is about to occur - this indicates the date of the event is
|
|
2768
|
+
// actually not the target date, but the day prior or after
|
|
2769
|
+
const localTimeHours = Math.trunc(this.geoLocation.getLongitude() / 15);
|
|
2770
|
+
if (isSunrise && localTimeHours + hours > 18) {
|
|
2771
|
+
cal = cal.add({ days: -1 });
|
|
2772
|
+
// cal = cal.minus({days: 1});
|
|
2773
|
+
}
|
|
2774
|
+
else if (!isSunrise && localTimeHours + hours < 6) {
|
|
2775
|
+
cal = cal.add({ days: 1 });
|
|
2776
|
+
}
|
|
2777
|
+
return cal
|
|
2778
|
+
.toZonedDateTime({
|
|
2779
|
+
timeZone: 'UTC',
|
|
2780
|
+
plainTime: new s.PlainTime(hours, minutes, seconds, Math.trunc(calculatedTime * 1000)),
|
|
2781
|
+
})
|
|
2782
|
+
.withTimeZone(this.geoLocation.getTimeZone());
|
|
2783
|
+
}
|
|
2784
|
+
/**
|
|
2785
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> from a Java Calendar
|
|
2786
|
+
* @private
|
|
2787
|
+
* @param {Temporal.ZonedDateTime} date
|
|
2788
|
+
* The Java Calendar
|
|
2789
|
+
* @return the Julian day corresponding to the date Note: Number is returned for start of day. Fractional days
|
|
2790
|
+
* should be added later.
|
|
2791
|
+
*/
|
|
2792
|
+
static getJulianDay(date) {
|
|
2793
|
+
let { year, month } = date;
|
|
2794
|
+
const { day } = date;
|
|
2795
|
+
if (month <= 2) {
|
|
2796
|
+
year -= 1;
|
|
2797
|
+
month += 12;
|
|
2798
|
+
}
|
|
2799
|
+
const a = Math.trunc(year / 100);
|
|
2800
|
+
const b = Math.trunc(2 - a + a / 4);
|
|
2801
|
+
return (Math.floor(365.25 * (year + 4716)) +
|
|
2802
|
+
Math.floor(30.6001 * (month + 1)) +
|
|
2803
|
+
day +
|
|
2804
|
+
b -
|
|
2805
|
+
1524.5);
|
|
2806
|
+
}
|
|
2807
|
+
/**
|
|
2808
|
+
* Convert <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> to centuries since J2000.0.
|
|
2809
|
+
* @private
|
|
2810
|
+
* @param julianDay
|
|
2811
|
+
* the Julian Day to convert
|
|
2812
|
+
* @return the centuries since 2000 Julian corresponding to the Julian Day
|
|
2813
|
+
*/
|
|
2814
|
+
static getJulianCenturiesFromJulianDay(julianDay) {
|
|
2815
|
+
return ((julianDay - NOAACalculator.JULIAN_DAY_JAN_1_2000) /
|
|
2816
|
+
NOAACalculator.JULIAN_DAYS_PER_CENTURY);
|
|
2817
|
+
}
|
|
2818
|
+
/**
|
|
2819
|
+
* Convert centuries since J2000.0 to <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a>.
|
|
2820
|
+
* @private
|
|
2821
|
+
* @param julianCenturies
|
|
2822
|
+
* the number of Julian centuries since J2000.0
|
|
2823
|
+
* @return the Julian Day corresponding to the Julian centuries passed in
|
|
2824
|
+
*/
|
|
2825
|
+
static getJulianDayFromJulianCenturies(julianCenturies) {
|
|
2826
|
+
return (julianCenturies * NOAACalculator.JULIAN_DAYS_PER_CENTURY +
|
|
2827
|
+
NOAACalculator.JULIAN_DAY_JAN_1_2000);
|
|
2828
|
+
}
|
|
2829
|
+
/**
|
|
2830
|
+
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_longitude">Mean Longitude</a> of the Sun.
|
|
2831
|
+
* @private
|
|
2832
|
+
* @param julianCenturies
|
|
2833
|
+
* the number of Julian centuries since J2000.0
|
|
2834
|
+
* @return the Geometric Mean Longitude of the Sun in degrees
|
|
2835
|
+
*/
|
|
2836
|
+
static getSunGeometricMeanLongitude(julianCenturies) {
|
|
2837
|
+
let longitude = 280.46646 + julianCenturies * (36000.76983 + 0.0003032 * julianCenturies);
|
|
2838
|
+
while (longitude > 360) {
|
|
2839
|
+
longitude -= 360;
|
|
2840
|
+
}
|
|
2841
|
+
while (longitude < 0) {
|
|
2842
|
+
longitude += 360;
|
|
2843
|
+
}
|
|
2844
|
+
return longitude; // in degrees
|
|
2845
|
+
}
|
|
2846
|
+
/**
|
|
2847
|
+
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_anomaly">Mean Anomaly</a> of the Sun.
|
|
2848
|
+
* @private
|
|
2849
|
+
* @param julianCenturies
|
|
2850
|
+
* the number of Julian centuries since J2000.0
|
|
2851
|
+
* @return the Geometric Mean Anomaly of the Sun in degrees
|
|
2852
|
+
*/
|
|
2853
|
+
static getSunGeometricMeanAnomaly(julianCenturies) {
|
|
2854
|
+
return (357.52911 + julianCenturies * (35999.05029 - 0.0001537 * julianCenturies)); // in degrees
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Eccentricity_%28orbit%29">eccentricity of earth's orbit</a>.
|
|
2858
|
+
* @private
|
|
2859
|
+
* @param julianCenturies
|
|
2860
|
+
* the number of Julian centuries since J2000.0
|
|
2861
|
+
* @return the unitless eccentricity
|
|
2862
|
+
*/
|
|
2863
|
+
static getEarthOrbitEccentricity(julianCenturies) {
|
|
2864
|
+
return (0.016708634 -
|
|
2865
|
+
julianCenturies * (0.000042037 + 0.0000001267 * julianCenturies)); // unitless
|
|
2866
|
+
}
|
|
2867
|
+
/**
|
|
2868
|
+
* Returns the <a href="http://en.wikipedia.org/wiki/Equation_of_the_center">equation of center</a> for the sun.
|
|
2869
|
+
* @private
|
|
2870
|
+
* @param julianCenturies
|
|
2871
|
+
* the number of Julian centuries since J2000.0
|
|
2872
|
+
* @return the equation of center for the sun in degrees
|
|
2873
|
+
*/
|
|
2874
|
+
static getSunEquationOfCenter(julianCenturies) {
|
|
2875
|
+
const m = NOAACalculator.getSunGeometricMeanAnomaly(julianCenturies);
|
|
2876
|
+
const mrad = degreesToRadians(m);
|
|
2877
|
+
const sinm = Math.sin(mrad);
|
|
2878
|
+
const sin2m = Math.sin(mrad + mrad);
|
|
2879
|
+
const sin3m = Math.sin(mrad + mrad + mrad);
|
|
2880
|
+
return (sinm *
|
|
2881
|
+
(1.914602 - julianCenturies * (0.004817 + 0.000014 * julianCenturies)) +
|
|
2882
|
+
sin2m * (0.019993 - 0.000101 * julianCenturies) +
|
|
2883
|
+
sin3m * 0.000289); // in degrees
|
|
2884
|
+
}
|
|
2885
|
+
/**
|
|
2886
|
+
* Return the true longitude of the sun
|
|
2887
|
+
* @private
|
|
2888
|
+
* @param julianCenturies
|
|
2889
|
+
* the number of Julian centuries since J2000.0
|
|
2890
|
+
* @return the sun's true longitude in degrees
|
|
2891
|
+
*/
|
|
2892
|
+
static getSunTrueLongitude(julianCenturies) {
|
|
2893
|
+
const sunLongitude = NOAACalculator.getSunGeometricMeanLongitude(julianCenturies);
|
|
2894
|
+
const center = NOAACalculator.getSunEquationOfCenter(julianCenturies);
|
|
2895
|
+
return sunLongitude + center; // in degrees
|
|
2896
|
+
}
|
|
2897
|
+
/**
|
|
2898
|
+
* Return the apparent longitude of the sun
|
|
2899
|
+
* @private
|
|
2900
|
+
* @param julianCenturies
|
|
2901
|
+
* the number of Julian centuries since J2000.0
|
|
2902
|
+
* @return sun's apparent longitude in degrees
|
|
2903
|
+
*/
|
|
2904
|
+
static getSunApparentLongitude(julianCenturies) {
|
|
2905
|
+
const sunTrueLongitude = NOAACalculator.getSunTrueLongitude(julianCenturies);
|
|
2906
|
+
const omega = 125.04 - 1934.136 * julianCenturies;
|
|
2907
|
+
const lambda = sunTrueLongitude - 0.00569 - 0.00478 * Math.sin(degreesToRadians(omega));
|
|
2908
|
+
return lambda; // in degrees
|
|
2909
|
+
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Returns the mean <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial tilt).
|
|
2912
|
+
* @private
|
|
2913
|
+
* @param julianCenturies
|
|
2914
|
+
* the number of Julian centuries since J2000.0
|
|
2915
|
+
* @return the mean obliquity in degrees
|
|
2916
|
+
*/
|
|
2917
|
+
static getMeanObliquityOfEcliptic(julianCenturies) {
|
|
2918
|
+
const seconds = 21.448 -
|
|
2919
|
+
julianCenturies *
|
|
2920
|
+
(46.815 + julianCenturies * (0.00059 - julianCenturies * 0.001813));
|
|
2921
|
+
return 23 + (26 + seconds / 60) / 60; // in degrees
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Returns the corrected <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial
|
|
2925
|
+
* tilt).
|
|
2926
|
+
* @private
|
|
2927
|
+
* @param julianCenturies
|
|
2928
|
+
* the number of Julian centuries since J2000.0
|
|
2929
|
+
* @return the corrected obliquity in degrees
|
|
2930
|
+
*/
|
|
2931
|
+
static getObliquityCorrection(julianCenturies) {
|
|
2932
|
+
const obliquityOfEcliptic = NOAACalculator.getMeanObliquityOfEcliptic(julianCenturies);
|
|
2933
|
+
const omega = 125.04 - 1934.136 * julianCenturies;
|
|
2934
|
+
return obliquityOfEcliptic + 0.00256 * Math.cos(degreesToRadians(omega)); // in degrees
|
|
2935
|
+
}
|
|
2936
|
+
/**
|
|
2937
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Declination">declination</a> of the sun.
|
|
2938
|
+
* @private
|
|
2939
|
+
* @param julianCenturies
|
|
2940
|
+
* the number of Julian centuries since J2000.0
|
|
2941
|
+
* @return
|
|
2942
|
+
* the sun's declination in degrees
|
|
2943
|
+
*/
|
|
2944
|
+
static getSunDeclination(julianCenturies) {
|
|
2945
|
+
const obliquityCorrection = NOAACalculator.getObliquityCorrection(julianCenturies);
|
|
2946
|
+
const lambda = NOAACalculator.getSunApparentLongitude(julianCenturies);
|
|
2947
|
+
const sint = Math.sin(degreesToRadians(obliquityCorrection)) *
|
|
2948
|
+
Math.sin(degreesToRadians(lambda));
|
|
2949
|
+
const theta = radiansToDegrees(Math.asin(sint));
|
|
2950
|
+
return theta; // in degrees
|
|
2951
|
+
}
|
|
2952
|
+
/**
|
|
2953
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Equation_of_time">Equation of Time</a> - the difference between
|
|
2954
|
+
* true solar time and mean solar time
|
|
2955
|
+
* @private
|
|
2956
|
+
* @param julianCenturies
|
|
2957
|
+
* the number of Julian centuries since J2000.0
|
|
2958
|
+
* @return equation of time in minutes of time
|
|
2959
|
+
*/
|
|
2960
|
+
static getEquationOfTime(julianCenturies) {
|
|
2961
|
+
const epsilon = NOAACalculator.getObliquityCorrection(julianCenturies);
|
|
2962
|
+
const geomMeanLongSun = NOAACalculator.getSunGeometricMeanLongitude(julianCenturies);
|
|
2963
|
+
const eccentricityEarthOrbit = NOAACalculator.getEarthOrbitEccentricity(julianCenturies);
|
|
2964
|
+
const geomMeanAnomalySun = NOAACalculator.getSunGeometricMeanAnomaly(julianCenturies);
|
|
2965
|
+
let y = Math.tan(degreesToRadians(epsilon) / 2);
|
|
2966
|
+
y *= y;
|
|
2967
|
+
const sin2l0 = Math.sin(2 * degreesToRadians(geomMeanLongSun));
|
|
2968
|
+
const sinm = Math.sin(degreesToRadians(geomMeanAnomalySun));
|
|
2969
|
+
const cos2l0 = Math.cos(2 * degreesToRadians(geomMeanLongSun));
|
|
2970
|
+
const sin4l0 = Math.sin(4 * degreesToRadians(geomMeanLongSun));
|
|
2971
|
+
const sin2m = Math.sin(2 * degreesToRadians(geomMeanAnomalySun));
|
|
2972
|
+
const equationOfTime = y * sin2l0 -
|
|
2973
|
+
2 * eccentricityEarthOrbit * sinm +
|
|
2974
|
+
4 * eccentricityEarthOrbit * y * sinm * cos2l0 -
|
|
2975
|
+
0.5 * y * y * sin4l0 -
|
|
2976
|
+
1.25 * eccentricityEarthOrbit * eccentricityEarthOrbit * sin2m;
|
|
2977
|
+
return radiansToDegrees(equationOfTime) * 4; // in minutes of time
|
|
2978
|
+
}
|
|
2979
|
+
/**
|
|
2980
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunrise for the
|
|
2981
|
+
* latitude.
|
|
2982
|
+
* @private
|
|
2983
|
+
* @param {number} lat
|
|
2984
|
+
* , the latitude of observer in degrees
|
|
2985
|
+
* @param solarDec
|
|
2986
|
+
* the declination angle of sun in degrees
|
|
2987
|
+
* @param {number} zenith
|
|
2988
|
+
* the zenith
|
|
2989
|
+
* @return hour angle of sunrise in radians
|
|
2990
|
+
*/
|
|
2991
|
+
static getSunHourAngleAtSunrise(lat, solarDec, zenith) {
|
|
2992
|
+
const latRad = degreesToRadians(lat);
|
|
2993
|
+
const sdRad = degreesToRadians(solarDec);
|
|
2994
|
+
return Math.acos(Math.cos(degreesToRadians(zenith)) /
|
|
2995
|
+
(Math.cos(latRad) * Math.cos(sdRad)) -
|
|
2996
|
+
Math.tan(latRad) * Math.tan(sdRad)); // in radians
|
|
2997
|
+
}
|
|
2998
|
+
/**
|
|
2999
|
+
* Returns the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunset for the
|
|
3000
|
+
* latitude. TODO: use - {@link #getSunHourAngleAtSunrise(double, double, double)} implementation to avoid
|
|
3001
|
+
* duplication of code.
|
|
3002
|
+
* @private
|
|
3003
|
+
* @param {number} lat
|
|
3004
|
+
* the latitude of observer in degrees
|
|
3005
|
+
* @param solarDec
|
|
3006
|
+
* the declination angle of sun in degrees
|
|
3007
|
+
* @param {number} zenith
|
|
3008
|
+
* the zenith
|
|
3009
|
+
* @return the hour angle of sunset in radians
|
|
3010
|
+
*/
|
|
3011
|
+
static getSunHourAngleAtSunset(lat, solarDec, zenith) {
|
|
3012
|
+
const latRad = degreesToRadians(lat);
|
|
3013
|
+
const sdRad = degreesToRadians(solarDec);
|
|
3014
|
+
const hourAngle = Math.acos(Math.cos(degreesToRadians(zenith)) /
|
|
3015
|
+
(Math.cos(latRad) * Math.cos(sdRad)) -
|
|
3016
|
+
Math.tan(latRad) * Math.tan(sdRad));
|
|
3017
|
+
return -hourAngle; // in radians
|
|
3018
|
+
}
|
|
3019
|
+
/**
|
|
3020
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Elevation</a> for the
|
|
3021
|
+
* horizontal coordinate system at the given location at the given time. Can be negative if the sun is below the
|
|
3022
|
+
* horizon. Not corrected for altitude.
|
|
3023
|
+
*
|
|
3024
|
+
* @param {Temporal.ZonedDateTime} date
|
|
3025
|
+
* time of calculation
|
|
3026
|
+
* @param {number} lat
|
|
3027
|
+
* latitude of location for calculation
|
|
3028
|
+
* @param {number} lon
|
|
3029
|
+
* longitude of location for calculation
|
|
3030
|
+
* @return {number} solar elevation in degrees - horizon is 0 degrees, civil twilight is -6 degrees
|
|
3031
|
+
*/
|
|
3032
|
+
static getSolarElevation(date, lat, lon) {
|
|
3033
|
+
const julianDay = NOAACalculator.getJulianDay(date.toPlainDate());
|
|
3034
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3035
|
+
const equationOfTime = NOAACalculator.getEquationOfTime(julianCenturies);
|
|
3036
|
+
let longitude = date.hour + 12 + (date.minute + equationOfTime + date.second / 60) / 60;
|
|
3037
|
+
longitude = -((longitude * 360) / 24) % 360;
|
|
3038
|
+
const hourAngleRad = degreesToRadians(lon - longitude);
|
|
3039
|
+
const declination = NOAACalculator.getSunDeclination(julianCenturies);
|
|
3040
|
+
const decRad = degreesToRadians(declination);
|
|
3041
|
+
const latRad = degreesToRadians(lat);
|
|
3042
|
+
return radiansToDegrees(Math.asin(Math.sin(latRad) * Math.sin(decRad) +
|
|
3043
|
+
Math.cos(latRad) * Math.cos(decRad) * Math.cos(hourAngleRad)));
|
|
3044
|
+
}
|
|
3045
|
+
/**
|
|
3046
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Azimuth</a> for the
|
|
3047
|
+
* horizontal coordinate system at the given location at the given time. Not corrected for altitude. True south is 0
|
|
3048
|
+
* degrees.
|
|
3049
|
+
*
|
|
3050
|
+
* @param {Temporal.ZonedDateTime} date
|
|
3051
|
+
* time of calculation
|
|
3052
|
+
* @param {number} latitude
|
|
3053
|
+
* latitude of location for calculation
|
|
3054
|
+
* @param {number} lon
|
|
3055
|
+
* longitude of location for calculation
|
|
3056
|
+
* @return {number}
|
|
3057
|
+
*/
|
|
3058
|
+
static getSolarAzimuth(date, latitude, lon) {
|
|
3059
|
+
const julianDay = NOAACalculator.getJulianDay(date.toPlainDate());
|
|
3060
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3061
|
+
const equationOfTime = NOAACalculator.getEquationOfTime(julianCenturies);
|
|
3062
|
+
let longitude = date.hour + 12 + (date.minute + equationOfTime + date.second / 60) / 60;
|
|
3063
|
+
longitude = -((longitude * 360) / 24) % 360;
|
|
3064
|
+
const hourAngleRad = degreesToRadians(lon - longitude);
|
|
3065
|
+
const declination = NOAACalculator.getSunDeclination(julianCenturies);
|
|
3066
|
+
const decRad = degreesToRadians(declination);
|
|
3067
|
+
const latRad = degreesToRadians(latitude);
|
|
3068
|
+
return (radiansToDegrees(Math.atan(Math.sin(hourAngleRad) /
|
|
3069
|
+
(Math.cos(hourAngleRad) * Math.sin(latRad) -
|
|
3070
|
+
Math.tan(decRad) * Math.cos(latRad)))) + 180);
|
|
3071
|
+
}
|
|
3072
|
+
/**
|
|
3073
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3074
|
+
* of sunrise for the given day at the given location on earth
|
|
3075
|
+
* @private
|
|
3076
|
+
* @param julianDay
|
|
3077
|
+
* the Julian day
|
|
3078
|
+
* @param {number} latitude
|
|
3079
|
+
* the latitude of observer in degrees
|
|
3080
|
+
* @param {number} longitude
|
|
3081
|
+
* the longitude of observer in degrees
|
|
3082
|
+
* @param {number} zenith
|
|
3083
|
+
* the zenith
|
|
3084
|
+
* @return the time in minutes from zero UTC
|
|
3085
|
+
*/
|
|
3086
|
+
static getSunriseUTC(julianDay, latitude, longitude, zenith) {
|
|
3087
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3088
|
+
// Find the time of solar noon at the location, and use that declination. This is better than start of the
|
|
3089
|
+
// Julian day
|
|
3090
|
+
const noonmin = NOAACalculator.getSolarNoonUTC(julianCenturies, longitude);
|
|
3091
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay + noonmin / 1440);
|
|
3092
|
+
// First pass to approximate sunrise (using solar noon)
|
|
3093
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3094
|
+
let solarDec = NOAACalculator.getSunDeclination(tnoon);
|
|
3095
|
+
let hourAngle = NOAACalculator.getSunHourAngleAtSunrise(latitude, solarDec, zenith);
|
|
3096
|
+
let delta = longitude - radiansToDegrees(hourAngle);
|
|
3097
|
+
let timeDiff = 4 * delta; // in minutes of time
|
|
3098
|
+
let timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3099
|
+
// Second pass includes fractional Julian Day in gamma calc
|
|
3100
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3101
|
+
timeUTC / 1440);
|
|
3102
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3103
|
+
solarDec = NOAACalculator.getSunDeclination(newt);
|
|
3104
|
+
hourAngle = NOAACalculator.getSunHourAngleAtSunrise(latitude, solarDec, zenith);
|
|
3105
|
+
delta = longitude - radiansToDegrees(hourAngle);
|
|
3106
|
+
timeDiff = 4 * delta;
|
|
3107
|
+
timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3108
|
+
return timeUTC;
|
|
3109
|
+
}
|
|
3110
|
+
/**
|
|
3111
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3112
|
+
* of <a href="http://en.wikipedia.org/wiki/Noon#Solar_noon">solar noon</a> for the given day at the given location
|
|
3113
|
+
* on earth.
|
|
3114
|
+
* @private
|
|
3115
|
+
* @param julianCenturies
|
|
3116
|
+
* the number of Julian centuries since J2000.0
|
|
3117
|
+
* @param {number} longitude
|
|
3118
|
+
* the longitude of observer in degrees
|
|
3119
|
+
* @return the time in minutes from zero UTC
|
|
3120
|
+
*/
|
|
3121
|
+
static getSolarNoonUTC(julianCenturies, longitude) {
|
|
3122
|
+
// First pass uses approximate solar noon to calculate eqtime
|
|
3123
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3124
|
+
longitude / 360);
|
|
3125
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3126
|
+
const solNoonUTC = 720 + longitude * 4 - eqTime; // min
|
|
3127
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) -
|
|
3128
|
+
0.5 +
|
|
3129
|
+
solNoonUTC / 1440);
|
|
3130
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3131
|
+
return 720 + longitude * 4 - eqTime; // min
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
|
|
3135
|
+
* of sunset for the given day at the given location on earth
|
|
3136
|
+
* @private
|
|
3137
|
+
* @param julianDay
|
|
3138
|
+
* the Julian day
|
|
3139
|
+
* @param {number} latitude
|
|
3140
|
+
* the latitude of observer in degrees
|
|
3141
|
+
* @param {number} longitude
|
|
3142
|
+
* : longitude of observer in degrees
|
|
3143
|
+
* @param {number} zenith
|
|
3144
|
+
* the zenith
|
|
3145
|
+
* @return the time in minutes from zero Universal Coordinated Time (UTC)
|
|
3146
|
+
*/
|
|
3147
|
+
static getSunsetUTC(julianDay, latitude, longitude, zenith) {
|
|
3148
|
+
const julianCenturies = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay);
|
|
3149
|
+
// Find the time of solar noon at the location, and use that declination. This is better than start of the
|
|
3150
|
+
// Julian day
|
|
3151
|
+
const noonmin = NOAACalculator.getSolarNoonUTC(julianCenturies, longitude);
|
|
3152
|
+
const tnoon = NOAACalculator.getJulianCenturiesFromJulianDay(julianDay + noonmin / 1440);
|
|
3153
|
+
// First calculates sunrise and approx length of day
|
|
3154
|
+
let eqTime = NOAACalculator.getEquationOfTime(tnoon);
|
|
3155
|
+
let solarDec = NOAACalculator.getSunDeclination(tnoon);
|
|
3156
|
+
let hourAngle = NOAACalculator.getSunHourAngleAtSunset(latitude, solarDec, zenith);
|
|
3157
|
+
let delta = longitude - radiansToDegrees(hourAngle);
|
|
3158
|
+
let timeDiff = 4 * delta;
|
|
3159
|
+
let timeUTC = 720 + timeDiff - eqTime;
|
|
3160
|
+
// Second pass includes fractional Julian Day in gamma calc
|
|
3161
|
+
const newt = NOAACalculator.getJulianCenturiesFromJulianDay(NOAACalculator.getJulianDayFromJulianCenturies(julianCenturies) +
|
|
3162
|
+
timeUTC / 1440);
|
|
3163
|
+
eqTime = NOAACalculator.getEquationOfTime(newt);
|
|
3164
|
+
solarDec = NOAACalculator.getSunDeclination(newt);
|
|
3165
|
+
hourAngle = NOAACalculator.getSunHourAngleAtSunset(latitude, solarDec, zenith);
|
|
3166
|
+
delta = longitude - radiansToDegrees(hourAngle);
|
|
3167
|
+
timeDiff = 4 * delta;
|
|
3168
|
+
timeUTC = 720 + timeDiff - eqTime; // in minutes
|
|
3169
|
+
return timeUTC;
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
/**
|
|
3173
|
+
* The zenith of astronomical sunrise and sunset. The sun is 90° from the vertical 0°
|
|
3174
|
+
* @private
|
|
3175
|
+
*/
|
|
3176
|
+
NOAACalculator.GEOMETRIC_ZENITH = 90;
|
|
3177
|
+
/**
|
|
3178
|
+
* Default value for Sun's zenith and true rise/set Zenith (used in this class and subclasses) is the angle that the
|
|
3179
|
+
* center of the Sun makes to a line perpendicular to the Earth's surface. If the Sun were a point and the Earth
|
|
3180
|
+
* were without an atmosphere, true sunset and sunrise would correspond to a 90° zenith. Because the Sun is not
|
|
3181
|
+
* a point, and because the atmosphere refracts light, this 90° zenith does not, in fact, correspond to true
|
|
3182
|
+
* sunset or sunrise, instead the center of the Sun's disk must lie just below the horizon for the upper edge to be
|
|
3183
|
+
* obscured. This means that a zenith of just above 90° must be used. The Sun subtends an angle of 16 minutes of
|
|
3184
|
+
* arc (this can be changed via the {@link #setSunRadius(double)} method , and atmospheric refraction accounts for
|
|
3185
|
+
* 34 minutes or so (this can be changed via the {@link #setRefraction(double)} method), giving a total of 50
|
|
3186
|
+
* arcminutes. The total value for ZENITH is 90+(5/6) or 90.8333333° for true sunrise/sunset.
|
|
3187
|
+
*/
|
|
3188
|
+
// const ZENITH: number = GEOMETRIC_ZENITH + 5.0 / 6.0;
|
|
3189
|
+
/** Sun's zenith at civil twilight (96°). */
|
|
3190
|
+
NOAACalculator.CIVIL_ZENITH = 96;
|
|
3191
|
+
/** Sun's zenith at nautical twilight (102°). */
|
|
3192
|
+
NOAACalculator.NAUTICAL_ZENITH = 102;
|
|
3193
|
+
/** Sun's zenith at astronomical twilight (108°). */
|
|
3194
|
+
NOAACalculator.ASTRONOMICAL_ZENITH = 108;
|
|
3195
|
+
/**
|
|
3196
|
+
* The <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> of January 1, 2000
|
|
3197
|
+
* @private
|
|
3198
|
+
*/
|
|
3199
|
+
NOAACalculator.JULIAN_DAY_JAN_1_2000 = 2451545;
|
|
3200
|
+
/**
|
|
3201
|
+
* Julian days per century
|
|
3202
|
+
* @private
|
|
3203
|
+
*/
|
|
3204
|
+
NOAACalculator.JULIAN_DAYS_PER_CENTURY = 36525;
|
|
3205
|
+
|
|
3206
|
+
/*
|
|
3207
|
+
Hebcal - A Jewish Calendar Generator
|
|
3208
|
+
Copyright (c) 1994-2020 Danny Sadinoff
|
|
3209
|
+
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
3210
|
+
|
|
3211
|
+
https://github.com/hebcal/hebcal-es6
|
|
3212
|
+
|
|
3213
|
+
This program is free software; you can redistribute it and/or
|
|
3214
|
+
modify it under the terms of the GNU General Public License
|
|
3215
|
+
as published by the Free Software Foundation; either version 2
|
|
3216
|
+
of the License, or (at your option) any later version.
|
|
3217
|
+
|
|
3218
|
+
This program is distributed in the hope that it will be useful,
|
|
3219
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
3220
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
3221
|
+
GNU General Public License for more details.
|
|
3222
|
+
|
|
3223
|
+
You should have received a copy of the GNU General Public License
|
|
3224
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
3225
|
+
*/
|
|
3226
|
+
const classicCities0 = [['Ashdod', 'IL', 31.79213, 34.64966, 'Asia/Jerusalem', 27], ['Atlanta', 'US', 33.749, -84.38798, 'America/New_York', 336], ['Austin', 'US', 30.26715, -97.74306, 'America/Chicago', 165], ['Baghdad', 'IQ', 33.34058, 44.40088, 'Asia/Baghdad', 41], ['Beer Sheva', 'IL', 31.25181, 34.7913, 'Asia/Jerusalem', 285], ['Berlin', 'DE', 52.52437, 13.41053, 'Europe/Berlin', 43], ['Baltimore', 'US', 39.29038, -76.61219, 'America/New_York', 35], ['Bogota', 'CO', 4.60971, -74.08175, 'America/Bogota', 2582], ['Boston', 'US', 42.35843, -71.05977, 'America/New_York', 38], ['Budapest', 'HU', 47.49801, 19.03991, 'Europe/Budapest', 104], ['Buenos Aires', 'AR', -34.61315, -58.37723, 'America/Argentina/Buenos_Aires', 31], ['Buffalo', 'US', 42.88645, -78.87837, 'America/New_York', 191], ['Chicago', 'US', 41.85003, -87.65005, 'America/Chicago', 180], ['Cincinnati', 'US', 39.162, -84.45689, 'America/New_York', 267], ['Cleveland', 'US', 41.4995, -81.69541, 'America/New_York', 204], ['Dallas', 'US', 32.78306, -96.80667, 'America/Chicago', 139], ['Denver', 'US', 39.73915, -104.9847, 'America/Denver', 1636], ['Detroit', 'US', 42.33143, -83.04575, 'America/Detroit', 192], ['Eilat', 'IL', 29.55805, 34.94821, 'Asia/Jerusalem', 63], ['Gibraltar', 'GI', 36.14474, -5.35257, 'Europe/Gibraltar', 11], ['Haifa', 'IL', 32.81841, 34.9885, 'Asia/Jerusalem', 40], ['Hawaii', 'US', 21.30694, -157.85833, 'Pacific/Honolulu', 18], ['Helsinki', 'FI', 60.16952, 24.93545, 'Europe/Helsinki', 26], ['Houston', 'US', 29.76328, -95.36327, 'America/Chicago', 30], ['Jerusalem', 'IL', 31.76904, 35.21633, 'Asia/Jerusalem', 786], ['Johannesburg', 'ZA', -26.20227, 28.04363, 'Africa/Johannesburg', 1767], ['Kiev', 'UA', 50.45466, 30.5238, 'Europe/Kiev', 187], ['La Paz', 'BO', -16.5, -68.15, 'America/La_Paz', 3782], ['Livingston', 'US', 40.79593, -74.31487, 'America/New_York', 98], ['Las Vegas', 'US', 36.17497, -115.13722, 'America/Los_Angeles', 613], ['London', 'GB', 51.50853, -0.12574, 'Europe/London', 25], ['Los Angeles', 'US', 34.05223, -118.24368, 'America/Los_Angeles', 96], ['Marseilles', 'FR', 43.29695, 5.38107, 'Europe/Paris', 28], ['Miami', 'US', 25.77427, -80.19366, 'America/New_York', 25], ['Minneapolis', 'US', 44.97997, -93.26384, 'America/Chicago', 262], ['Melbourne', 'AU', -37.814, 144.96332, 'Australia/Melbourne', 25], ['Mexico City', 'MX', 19.42847, -99.12766, 'America/Mexico_City', 2240], ['Montreal', 'CA', 45.50884, -73.58781, 'America/Toronto', 216], ['Moscow', 'RU', 55.75222, 37.61556, 'Europe/Moscow', 144], ['New York', 'US', 40.71427, -74.00597, 'America/New_York', 57], ['Omaha', 'US', 41.25861, -95.93779, 'America/Chicago', 315], ['Ottawa', 'CA', 45.41117, -75.69812, 'America/Toronto', 71], ['Panama City', 'PA', 8.9936, -79.51973, 'America/Panama', 17], ['Paris', 'FR', 48.85341, 2.3488, 'Europe/Paris', 42], ['Pawtucket', 'US', 41.87871, -71.38256, 'America/New_York', 0],
|
|
3227
|
+
// -11
|
|
3228
|
+
['Petach Tikvah', 'IL', 32.08707, 34.88747, 'Asia/Jerusalem', 54], ['Philadelphia', 'US', 39.95233, -75.16379, 'America/New_York', 8], ['Phoenix', 'US', 33.44838, -112.07404, 'America/Phoenix', 366], ['Pittsburgh', 'US', 40.44062, -79.99589, 'America/New_York', 239], ['Providence', 'US', 41.82399, -71.41283, 'America/New_York', 0],
|
|
3229
|
+
// -15
|
|
3230
|
+
['Portland', 'US', 45.52345, -122.67621, 'America/Los_Angeles', 15], ['Saint Louis', 'US', 38.62727, -90.19789, 'America/Chicago', 149], ['Saint Petersburg', 'RU', 59.93863, 30.31413, 'Europe/Moscow', 11], ['San Diego', 'US', 32.71533, -117.15726, 'America/Los_Angeles', 20], ['San Francisco', 'US', 37.77493, -122.41942, 'America/Los_Angeles', 28], ['Sao Paulo', 'BR', -23.5475, -46.63611, 'America/Sao_Paulo', 769], ['Seattle', 'US', 47.60621, -122.33207, 'America/Los_Angeles', 56], ['Sydney', 'AU', -33.86785, 151.20732, 'Australia/Sydney', 58], ['Tel Aviv', 'IL', 32.08088, 34.78057, 'Asia/Jerusalem', 15], ['Tiberias', 'IL', 32.79221, 35.53124, 'Asia/Jerusalem', 0],
|
|
3231
|
+
// -140
|
|
3232
|
+
['Toronto', 'CA', 43.70011, -79.4163, 'America/Toronto', 175], ['Vancouver', 'CA', 49.24966, -123.11934, 'America/Vancouver', 70], ['White Plains', 'US', 41.03399, -73.76291, 'America/New_York', 82], ['Washington DC', 'US', 38.89511, -77.03637, 'America/New_York', 6], ['Worcester', 'US', 42.26259, -71.80229, 'America/New_York', 164]];
|
|
3233
|
+
const classicCities = new Map();
|
|
3234
|
+
|
|
3235
|
+
// Zip-Codes.com TimeZone IDs
|
|
3236
|
+
const ZIPCODES_TZ_MAP = {
|
|
3237
|
+
'0': 'UTC',
|
|
3238
|
+
'4': 'America/Puerto_Rico',
|
|
3239
|
+
// Atlantic (GMT -04:00)
|
|
3240
|
+
'5': 'America/New_York',
|
|
3241
|
+
// Eastern (GMT -05:00)
|
|
3242
|
+
'6': 'America/Chicago',
|
|
3243
|
+
// Central (GMT -06:00)
|
|
3244
|
+
'7': 'America/Denver',
|
|
3245
|
+
// Mountain (GMT -07:00)
|
|
3246
|
+
'8': 'America/Los_Angeles',
|
|
3247
|
+
// Pacific (GMT -08:00)
|
|
3248
|
+
'9': 'America/Anchorage',
|
|
3249
|
+
// Alaska (GMT -09:00)
|
|
3250
|
+
'10': 'Pacific/Honolulu',
|
|
3251
|
+
// Hawaii-Aleutian Islands (GMT -10:00)
|
|
3252
|
+
'11': 'Pacific/Pago_Pago',
|
|
3253
|
+
// American Samoa (GMT -11:00)
|
|
3254
|
+
'13': 'Pacific/Funafuti',
|
|
3255
|
+
// Marshall Islands (GMT +12:00)
|
|
3256
|
+
'14': 'Pacific/Guam',
|
|
3257
|
+
// Guam (GMT +10:00)
|
|
3258
|
+
'15': 'Pacific/Palau',
|
|
3259
|
+
// Palau (GMT +9:00)
|
|
3260
|
+
'16': 'Pacific/Chuuk' // Micronesia (GMT +11:00)
|
|
3261
|
+
};
|
|
3262
|
+
|
|
3263
|
+
/** @private */
|
|
3264
|
+
const timeFormatCache = new Map();
|
|
3265
|
+
|
|
3266
|
+
/**
|
|
3267
|
+
* Gets a 24-hour time formatter (e.g. 07:41 or 20:03) from cache
|
|
3268
|
+
* or makes a new one if needed
|
|
3269
|
+
* @private
|
|
3270
|
+
* @param {string} tzid
|
|
3271
|
+
* @return {Intl.DateTimeFormat}
|
|
3272
|
+
*/
|
|
3273
|
+
function getFormatter$1(tzid) {
|
|
3274
|
+
const fmt = timeFormatCache.get(tzid);
|
|
3275
|
+
if (fmt) return fmt;
|
|
3276
|
+
const f = new Intl.DateTimeFormat('en-US', {
|
|
3277
|
+
timeZone: tzid,
|
|
3278
|
+
hour: 'numeric',
|
|
3279
|
+
minute: 'numeric',
|
|
3280
|
+
hour12: false
|
|
3281
|
+
});
|
|
3282
|
+
timeFormatCache.set(tzid, f);
|
|
3283
|
+
return f;
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
/** Class representing Location */
|
|
3287
|
+
class Location extends GeoLocation {
|
|
3288
|
+
/**
|
|
3289
|
+
* Initialize a Location instance
|
|
3290
|
+
* @param {number} latitude - Latitude as a decimal, valid range -90 thru +90 (e.g. 41.85003)
|
|
3291
|
+
* @param {number} longitude - Longitude as a decimal, valid range -180 thru +180 (e.g. -87.65005)
|
|
3292
|
+
* @param {boolean} il - in Israel (true) or Diaspora (false)
|
|
3293
|
+
* @param {string} tzid - Olson timezone ID, e.g. "America/Chicago"
|
|
3294
|
+
* @param {string} cityName - optional descriptive city name
|
|
3295
|
+
* @param {string} countryCode - ISO 3166 alpha-2 country code (e.g. "FR")
|
|
3296
|
+
* @param {string} [geoid] - optional string or numeric geographic ID
|
|
3297
|
+
* @param {number} [elevation] - in meters (default `0`)
|
|
3298
|
+
*/
|
|
3299
|
+
constructor(latitude, longitude, il, tzid, cityName, countryCode, geoid, elevation) {
|
|
3300
|
+
const lat = typeof latitude === 'number' ? latitude : parseFloat(latitude);
|
|
3301
|
+
if (isNaN(lat) || lat < -90 || lat > 90) {
|
|
3302
|
+
throw new RangeError(`Latitude ${latitude} out of range [-90,90]`);
|
|
3303
|
+
}
|
|
3304
|
+
const long = typeof longitude === 'number' ? longitude : parseFloat(longitude);
|
|
3305
|
+
if (isNaN(long) || long < -180 || long > 180) {
|
|
3306
|
+
throw new RangeError(`Longitude ${longitude} out of range [-180,180]`);
|
|
3307
|
+
}
|
|
3308
|
+
const elev = typeof elevation === 'number' && elevation > 0 ? elevation : 0;
|
|
3309
|
+
super(cityName, lat, long, elev, tzid);
|
|
3310
|
+
this.il = Boolean(il);
|
|
3311
|
+
this.cc = countryCode;
|
|
3312
|
+
this.geoid = geoid;
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3315
|
+
/** @return {boolean} */
|
|
3316
|
+
getIsrael() {
|
|
3317
|
+
return this.il;
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
/** @return {string} */
|
|
3321
|
+
getName() {
|
|
3322
|
+
return this.getLocationName();
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3325
|
+
/**
|
|
3326
|
+
* Returns the location name, up to the first comma
|
|
3327
|
+
* @return {string}
|
|
3328
|
+
*/
|
|
3329
|
+
getShortName() {
|
|
3330
|
+
const name = this.getLocationName();
|
|
3331
|
+
if (!name) return name;
|
|
3332
|
+
const comma = name.indexOf(', ');
|
|
3333
|
+
if (comma === -1) return name;
|
|
3334
|
+
if (this.cc === 'US' && name[comma + 2] === 'D') {
|
|
3335
|
+
if (name[comma + 3] === 'C') {
|
|
3336
|
+
return name.substring(0, comma + 4);
|
|
3337
|
+
} else if (name[comma + 3] === '.' && name[comma + 4] === 'C') {
|
|
3338
|
+
return name.substring(0, comma + 6);
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
return name.substring(0, comma);
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
/** @return {string} */
|
|
3345
|
+
getCountryCode() {
|
|
3346
|
+
return this.cc;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
/** @return {string} */
|
|
3350
|
+
getTzid() {
|
|
3351
|
+
return this.getTimeZone();
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
/**
|
|
3355
|
+
* Gets a 24-hour time formatter (e.g. 07:41 or 20:03) for this location
|
|
3356
|
+
* @return {Intl.DateTimeFormat}
|
|
3357
|
+
*/
|
|
3358
|
+
getTimeFormatter() {
|
|
3359
|
+
return getFormatter$1(this.getTimeZone());
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
/** @return {string} */
|
|
3363
|
+
getGeoId() {
|
|
3364
|
+
return this.geoid;
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
/**
|
|
3368
|
+
* Creates a location object from one of 60 "classic" Hebcal city names.
|
|
3369
|
+
* The following city names are supported:
|
|
3370
|
+
* 'Ashdod', 'Atlanta', 'Austin', 'Baghdad', 'Beer Sheva',
|
|
3371
|
+
* 'Berlin', 'Baltimore', 'Bogota', 'Boston', 'Budapest',
|
|
3372
|
+
* 'Buenos Aires', 'Buffalo', 'Chicago', 'Cincinnati', 'Cleveland',
|
|
3373
|
+
* 'Dallas', 'Denver', 'Detroit', 'Eilat', 'Gibraltar', 'Haifa',
|
|
3374
|
+
* 'Hawaii', 'Helsinki', 'Houston', 'Jerusalem', 'Johannesburg',
|
|
3375
|
+
* 'Kiev', 'La Paz', 'Livingston', 'Las Vegas', 'London', 'Los Angeles',
|
|
3376
|
+
* 'Marseilles', 'Miami', 'Minneapolis', 'Melbourne', 'Mexico City',
|
|
3377
|
+
* 'Montreal', 'Moscow', 'New York', 'Omaha', 'Ottawa', 'Panama City',
|
|
3378
|
+
* 'Paris', 'Pawtucket', 'Petach Tikvah', 'Philadelphia', 'Phoenix',
|
|
3379
|
+
* 'Pittsburgh', 'Providence', 'Portland', 'Saint Louis', 'Saint Petersburg',
|
|
3380
|
+
* 'San Diego', 'San Francisco', 'Sao Paulo', 'Seattle', 'Sydney',
|
|
3381
|
+
* 'Tel Aviv', 'Tiberias', 'Toronto', 'Vancouver', 'White Plains',
|
|
3382
|
+
* 'Washington DC', 'Worcester'
|
|
3383
|
+
* @param {string} name
|
|
3384
|
+
* @return {Location}
|
|
3385
|
+
*/
|
|
3386
|
+
static lookup(name) {
|
|
3387
|
+
return classicCities.get(name.toLowerCase());
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
/** @return {string} */
|
|
3391
|
+
toString() {
|
|
3392
|
+
return JSON.stringify(this);
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
/**
|
|
3396
|
+
* Converts legacy Hebcal timezone to a standard Olson tzid.
|
|
3397
|
+
* @param {number} tz integer, GMT offset in hours
|
|
3398
|
+
* @param {string} dst 'none', 'eu', 'usa', or 'israel'
|
|
3399
|
+
* @return {string}
|
|
3400
|
+
*/
|
|
3401
|
+
static legacyTzToTzid(tz, dst) {
|
|
3402
|
+
tz = +tz;
|
|
3403
|
+
if (dst == 'none') {
|
|
3404
|
+
if (tz == 0) {
|
|
3405
|
+
return 'UTC';
|
|
3406
|
+
} else {
|
|
3407
|
+
const plus = tz > 0 ? '+' : '';
|
|
3408
|
+
return `Etc/GMT${plus}${tz}`;
|
|
3409
|
+
}
|
|
3410
|
+
} else if (tz == 2 && dst == 'israel') {
|
|
3411
|
+
return 'Asia/Jerusalem';
|
|
3412
|
+
} else if (dst == 'eu') {
|
|
3413
|
+
switch (tz) {
|
|
3414
|
+
case -2:
|
|
3415
|
+
return 'Atlantic/Cape_Verde';
|
|
3416
|
+
case -1:
|
|
3417
|
+
return 'Atlantic/Azores';
|
|
3418
|
+
case 0:
|
|
3419
|
+
return 'Europe/London';
|
|
3420
|
+
case 1:
|
|
3421
|
+
return 'Europe/Paris';
|
|
3422
|
+
case 2:
|
|
3423
|
+
return 'Europe/Athens';
|
|
3424
|
+
}
|
|
3425
|
+
} else if (dst == 'usa') {
|
|
3426
|
+
return ZIPCODES_TZ_MAP[String(tz * -1)];
|
|
3427
|
+
}
|
|
3428
|
+
return undefined;
|
|
3429
|
+
}
|
|
3430
|
+
|
|
3431
|
+
/**
|
|
3432
|
+
* Converts timezone info from Zip-Codes.com to a standard Olson tzid.
|
|
3433
|
+
* @example
|
|
3434
|
+
* Location.getUsaTzid('AZ', 7, 'Y') // 'America/Denver'
|
|
3435
|
+
* @param {string} state two-letter all-caps US state abbreviation like 'CA'
|
|
3436
|
+
* @param {number} tz positive number, 5=America/New_York, 8=America/Los_Angeles
|
|
3437
|
+
* @param {string} dst single char 'Y' or 'N'
|
|
3438
|
+
* @return {string}
|
|
3439
|
+
*/
|
|
3440
|
+
static getUsaTzid(state, tz, dst) {
|
|
3441
|
+
if (tz == 10 && state == 'AK') {
|
|
3442
|
+
return 'America/Adak';
|
|
3443
|
+
} else if (tz == 7 && state == 'AZ') {
|
|
3444
|
+
return dst == 'Y' ? 'America/Denver' : 'America/Phoenix';
|
|
3445
|
+
} else {
|
|
3446
|
+
return ZIPCODES_TZ_MAP[tz];
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
/**
|
|
3451
|
+
* Adds a location name for `Location.lookup()` only if the name isn't
|
|
3452
|
+
* already being used. Returns `false` if the name is already taken
|
|
3453
|
+
* and `true` if successfully added.
|
|
3454
|
+
* @param {string} cityName
|
|
3455
|
+
* @param {Location} location
|
|
3456
|
+
* @return {boolean}
|
|
3457
|
+
*/
|
|
3458
|
+
static addLocation(cityName, location) {
|
|
3459
|
+
const name = cityName.toLowerCase();
|
|
3460
|
+
if (classicCities.has(name)) {
|
|
3461
|
+
return false;
|
|
3462
|
+
}
|
|
3463
|
+
classicCities.set(name, location);
|
|
3464
|
+
return true;
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
classicCities0.forEach(city => {
|
|
3468
|
+
const location = new Location(city[2], city[3], city[1] == 'IL', city[4], city[0], city[1], undefined, city[5]);
|
|
3469
|
+
Location.addLocation(location.getName(), location);
|
|
3470
|
+
});
|
|
3471
|
+
|
|
3472
|
+
const _formatters = new Map();
|
|
3473
|
+
|
|
3474
|
+
/**
|
|
3475
|
+
* @private
|
|
3476
|
+
* @param {string} tzid
|
|
3477
|
+
* @return {Intl.DateTimeFormat}
|
|
3478
|
+
*/
|
|
3479
|
+
function getFormatter(tzid) {
|
|
3480
|
+
const fmt = _formatters.get(tzid);
|
|
3481
|
+
if (fmt) return fmt;
|
|
3482
|
+
const f = new Intl.DateTimeFormat('en-US', {
|
|
3483
|
+
year: 'numeric',
|
|
3484
|
+
month: '2-digit',
|
|
3485
|
+
day: '2-digit',
|
|
3486
|
+
hour: '2-digit',
|
|
3487
|
+
minute: '2-digit',
|
|
3488
|
+
second: '2-digit',
|
|
3489
|
+
hour12: false,
|
|
3490
|
+
timeZone: tzid
|
|
3491
|
+
});
|
|
3492
|
+
_formatters.set(tzid, f);
|
|
3493
|
+
return f;
|
|
3494
|
+
}
|
|
3495
|
+
const dateFormatRegex = /^(\d+).(\d+).(\d+),?\s+(\d+).(\d+).(\d+)/;
|
|
3496
|
+
|
|
3497
|
+
/**
|
|
3498
|
+
* @private
|
|
3499
|
+
* @param {string} tzid
|
|
3500
|
+
* @param {Date} date
|
|
3501
|
+
* @return {string}
|
|
3502
|
+
*/
|
|
3503
|
+
function getPseudoISO(tzid, date) {
|
|
3504
|
+
const str = getFormatter(tzid).format(date);
|
|
3505
|
+
const m = dateFormatRegex.exec(str);
|
|
3506
|
+
let hour = m[4];
|
|
3507
|
+
if (hour == '24') hour = '00';
|
|
3508
|
+
m[3] = pad4(m[3]);
|
|
3509
|
+
return `${m[3]}-${m[1]}-${m[2]}T${hour}:${m[5]}:${m[6]}Z`;
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
/**
|
|
3513
|
+
* @private
|
|
3514
|
+
* @param {string} tzid
|
|
3515
|
+
* @param {Date} date
|
|
3516
|
+
* @return {number}
|
|
3517
|
+
*/
|
|
3518
|
+
function getTimezoneOffset(tzid, date) {
|
|
3519
|
+
const utcStr = getPseudoISO('UTC', date);
|
|
3520
|
+
const localStr = getPseudoISO(tzid, date);
|
|
3521
|
+
const diffMs = new Date(utcStr).getTime() - new Date(localStr).getTime();
|
|
3522
|
+
return Math.ceil(diffMs / 1000 / 60);
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
/**
|
|
3526
|
+
* @private
|
|
3527
|
+
* @param {number} number
|
|
3528
|
+
* @return {string}
|
|
3529
|
+
*/
|
|
3530
|
+
function pad4(number) {
|
|
2394
3531
|
if (number < 0) {
|
|
2395
3532
|
return '-00' + pad4(-number);
|
|
2396
3533
|
} else if (number < 10) {
|
|
@@ -2416,25 +3553,18 @@ function pad2(number) {
|
|
|
2416
3553
|
}
|
|
2417
3554
|
|
|
2418
3555
|
/**
|
|
2419
|
-
* @
|
|
2420
|
-
* @
|
|
2421
|
-
* @
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
* @property {Date} sunset
|
|
2432
|
-
* @property {Date} sunsetStart
|
|
2433
|
-
* @property {Date} alotHaShachar
|
|
2434
|
-
* @property {Date} misheyakir
|
|
2435
|
-
* @property {Date} misheyakirMachmir
|
|
2436
|
-
* @property {Date} tzeit
|
|
2437
|
-
*/
|
|
3556
|
+
* @private
|
|
3557
|
+
* @param {Temporal.ZonedDateTime} zdt
|
|
3558
|
+
* @return {Date}
|
|
3559
|
+
*/
|
|
3560
|
+
function zdtToDate(zdt) {
|
|
3561
|
+
if (zdt === null) {
|
|
3562
|
+
return new Date(NaN);
|
|
3563
|
+
}
|
|
3564
|
+
const res = new Date(zdt.epochMilliseconds);
|
|
3565
|
+
res.setMilliseconds(0);
|
|
3566
|
+
return res;
|
|
3567
|
+
}
|
|
2438
3568
|
|
|
2439
3569
|
/**
|
|
2440
3570
|
* Calculate halachic times (zmanim / זְמַנִּים) for a given day and location.
|
|
@@ -2452,62 +3582,33 @@ function pad2(number) {
|
|
|
2452
3582
|
* https://gml.noaa.gov/grad/solcalc/calcdetails.html
|
|
2453
3583
|
*
|
|
2454
3584
|
* @example
|
|
2455
|
-
* const {Zmanim} = require('@hebcal/core');
|
|
3585
|
+
* const {GeoLocation, Zmanim} = require('@hebcal/core');
|
|
2456
3586
|
* const latitude = 41.822232;
|
|
2457
3587
|
* const longitude = -71.448292;
|
|
3588
|
+
* const tzid = 'America/New_York';
|
|
2458
3589
|
* const friday = new Date(2023, 8, 8);
|
|
2459
|
-
* const
|
|
3590
|
+
* const gloc = new GeoLocation(null, latitude, longitude, 0, tzid);
|
|
3591
|
+
* const zmanim = new Zmanim(gloc, friday);
|
|
2460
3592
|
* const candleLighting = zmanim.sunsetOffset(-18, true);
|
|
2461
|
-
* const timeStr = Zmanim.formatISOWithTimeZone(
|
|
3593
|
+
* const timeStr = Zmanim.formatISOWithTimeZone(tzid, candleLighting);
|
|
2462
3594
|
*/
|
|
2463
3595
|
class Zmanim {
|
|
2464
3596
|
/**
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
* @param {number} longitude
|
|
2470
|
-
*/
|
|
2471
|
-
constructor(date, latitude, longitude) {
|
|
2472
|
-
if (typeof latitude !== 'number') throw new TypeError('Invalid latitude');
|
|
2473
|
-
if (typeof longitude !== 'number') throw new TypeError('Invalid longitude');
|
|
2474
|
-
if (latitude < -90 || latitude > 90) {
|
|
2475
|
-
throw new RangeError(`Latitude ${latitude} out of range [-90,90]`);
|
|
2476
|
-
}
|
|
2477
|
-
if (longitude < -180 || longitude > 180) {
|
|
2478
|
-
throw new RangeError(`Longitude ${longitude} out of range [-180,180]`);
|
|
2479
|
-
}
|
|
2480
|
-
const dt = isDate(date) ? date : HDate.isHDate(date) ? date.greg() : throwTypeError(`invalid date: ${date}`);
|
|
2481
|
-
this.date = dt;
|
|
2482
|
-
this.solarCalc = new SolarCalc(this.date, latitude, longitude);
|
|
2483
|
-
this.sun = this.solarCalc.sun;
|
|
2484
|
-
this.latitude = latitude;
|
|
2485
|
-
this.longitude = longitude;
|
|
2486
|
-
}
|
|
2487
|
-
/**
|
|
2488
|
-
* @deprecated
|
|
2489
|
-
* @return {ZmanimTimesResult}
|
|
3597
|
+
* Initialize a Zmanim instance.
|
|
3598
|
+
* @param {GeoLocation} gloc GeoLocation including latitude, longitude, and timezone
|
|
3599
|
+
* @param {Date|HDate} date Regular or Hebrew Date. If `date` is a regular `Date`,
|
|
3600
|
+
* hours, minutes, seconds and milliseconds are ignored.
|
|
2490
3601
|
*/
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
nauticalDusk: this.solarCalc.nauticalDusk,
|
|
2502
|
-
nightEnd: this.solarCalc.nightEnd,
|
|
2503
|
-
night: this.solarCalc.nightStart,
|
|
2504
|
-
goldenHourEnd: this.solarCalc.goldenHourEnd,
|
|
2505
|
-
goldenHour: this.solarCalc.goldenHourStart,
|
|
2506
|
-
alotHaShachar: this.alotHaShachar(),
|
|
2507
|
-
misheyakir: this.misheyakir(),
|
|
2508
|
-
misheyakirMachmir: this.misheyakirMachmir(),
|
|
2509
|
-
tzeit: this.tzeit()
|
|
2510
|
-
};
|
|
3602
|
+
constructor(gloc, date) {
|
|
3603
|
+
const dt = greg.isDate(date) ? date : HDate.isHDate(date) ? date.greg() : throwTypeError(`invalid date: ${date}`);
|
|
3604
|
+
this.date = dt;
|
|
3605
|
+
this.gloc = gloc;
|
|
3606
|
+
const plainDate = s.PlainDate.from({
|
|
3607
|
+
year: dt.getFullYear(),
|
|
3608
|
+
month: dt.getMonth() + 1,
|
|
3609
|
+
day: dt.getDate()
|
|
3610
|
+
});
|
|
3611
|
+
this.noaa = new NOAACalculator(gloc, plainDate);
|
|
2511
3612
|
}
|
|
2512
3613
|
/**
|
|
2513
3614
|
* Convenience function to get the time when sun is above or below the horizon
|
|
@@ -2517,637 +3618,309 @@ class Zmanim {
|
|
|
2517
3618
|
* @return {Date}
|
|
2518
3619
|
*/
|
|
2519
3620
|
timeAtAngle(angle, rising) {
|
|
2520
|
-
|
|
3621
|
+
const offsetZenith = 90 + angle;
|
|
3622
|
+
const zdt = rising ? this.noaa.getSunriseOffsetByDegrees(offsetZenith) : this.noaa.getSunsetOffsetByDegrees(offsetZenith);
|
|
3623
|
+
return zdtToDate(zdt);
|
|
2521
3624
|
}
|
|
2522
3625
|
/**
|
|
2523
3626
|
* Upper edge of the Sun appears over the eastern horizon in the morning (0.833° above horizon)
|
|
2524
3627
|
* @return {Date}
|
|
2525
3628
|
*/
|
|
2526
3629
|
sunrise() {
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
/**
|
|
2530
|
-
* When the upper edge of the Sun disappears below the horizon (0.833° below horizon)
|
|
2531
|
-
* @return {Date}
|
|
2532
|
-
*/
|
|
2533
|
-
sunset() {
|
|
2534
|
-
return this.sun.timeAtAngle(0.833333, false);
|
|
2535
|
-
}
|
|
2536
|
-
/**
|
|
2537
|
-
* Civil dawn; Sun is 6° below the horizon in the morning
|
|
2538
|
-
* @return {Date}
|
|
2539
|
-
*/
|
|
2540
|
-
dawn() {
|
|
2541
|
-
return this.solarCalc.dawn;
|
|
2542
|
-
}
|
|
2543
|
-
/**
|
|
2544
|
-
* Civil dusk; Sun is 6° below the horizon in the evening
|
|
2545
|
-
* @return {Date}
|
|
2546
|
-
*/
|
|
2547
|
-
dusk() {
|
|
2548
|
-
return this.solarCalc.dusk;
|
|
2549
|
-
}
|
|
2550
|
-
/** @return {number} */
|
|
2551
|
-
hour() {
|
|
2552
|
-
return (this.sunset() - this.sunrise()) / 12; // ms in hour
|
|
2553
|
-
}
|
|
2554
|
-
/** @return {number} */
|
|
2555
|
-
hourMins() {
|
|
2556
|
-
// hour in ms / (1000 ms in s * 60 s in m) = mins in halachic hour
|
|
2557
|
-
return this.hour() / (1000 * 60);
|
|
2558
|
-
}
|
|
2559
|
-
/** @return {Date} */
|
|
2560
|
-
gregEve() {
|
|
2561
|
-
const prev = new Date(this.date);
|
|
2562
|
-
prev.setDate(prev.getDate() - 1);
|
|
2563
|
-
const zman = new Zmanim(prev, this.latitude, this.longitude);
|
|
2564
|
-
return zman.sunset();
|
|
2565
|
-
}
|
|
2566
|
-
/** @return {number} */
|
|
2567
|
-
nightHour() {
|
|
2568
|
-
return (this.sunrise() - this.gregEve()) / 12; // ms in hour
|
|
2569
|
-
}
|
|
2570
|
-
/** @return {number} */
|
|
2571
|
-
nightHourMins() {
|
|
2572
|
-
// hour in ms / (1000 ms in s * 60 s in m) = mins in halachic hour
|
|
2573
|
-
return this.nightHour() / (1000 * 60);
|
|
2574
|
-
}
|
|
2575
|
-
/**
|
|
2576
|
-
* @param {number} hours
|
|
2577
|
-
* @return {Date}
|
|
2578
|
-
*/
|
|
2579
|
-
hourOffset(hours) {
|
|
2580
|
-
return new Date(this.sunrise().getTime() + this.hour() * hours);
|
|
2581
|
-
}
|
|
2582
|
-
/**
|
|
2583
|
-
* Midday – Chatzot; Sunrise plus 6 halachic hours
|
|
2584
|
-
* @return {Date}
|
|
2585
|
-
*/
|
|
2586
|
-
chatzot() {
|
|
2587
|
-
return this.hourOffset(6);
|
|
2588
|
-
}
|
|
2589
|
-
/**
|
|
2590
|
-
* Midnight – Chatzot; Sunset plus 6 halachic hours
|
|
2591
|
-
* @return {Date}
|
|
2592
|
-
*/
|
|
2593
|
-
chatzotNight() {
|
|
2594
|
-
return new Date(this.sunrise().getTime() - this.nightHour() * 6);
|
|
2595
|
-
}
|
|
2596
|
-
/**
|
|
2597
|
-
* Dawn – Alot haShachar; Sun is 16.1° below the horizon in the morning
|
|
2598
|
-
* @return {Date}
|
|
2599
|
-
*/
|
|
2600
|
-
alotHaShachar() {
|
|
2601
|
-
return this.sun.timeAtAngle(16.1, true);
|
|
2602
|
-
}
|
|
2603
|
-
/**
|
|
2604
|
-
* Earliest talis & tefillin – Misheyakir; Sun is 11.5° below the horizon in the morning
|
|
2605
|
-
* @return {Date}
|
|
2606
|
-
*/
|
|
2607
|
-
misheyakir() {
|
|
2608
|
-
return this.sun.timeAtAngle(11.5, true);
|
|
2609
|
-
}
|
|
2610
|
-
/**
|
|
2611
|
-
* Earliest talis & tefillin – Misheyakir Machmir; Sun is 10.2° below the horizon in the morning
|
|
2612
|
-
* @return {Date}
|
|
2613
|
-
*/
|
|
2614
|
-
misheyakirMachmir() {
|
|
2615
|
-
return this.sun.timeAtAngle(10.2, true);
|
|
3630
|
+
const zdt = this.noaa.getSunrise();
|
|
3631
|
+
return zdtToDate(zdt);
|
|
2616
3632
|
}
|
|
2617
3633
|
/**
|
|
2618
|
-
*
|
|
2619
|
-
* @return {Date}
|
|
2620
|
-
*/
|
|
2621
|
-
sofZmanShma() {
|
|
2622
|
-
// Gra
|
|
2623
|
-
return this.hourOffset(3);
|
|
2624
|
-
}
|
|
2625
|
-
/**
|
|
2626
|
-
* Latest Shacharit (Gra); Sunrise plus 4 halachic hours, according to the Gra
|
|
2627
|
-
* @return {Date}
|
|
2628
|
-
*/
|
|
2629
|
-
sofZmanTfilla() {
|
|
2630
|
-
// Gra
|
|
2631
|
-
return this.hourOffset(4);
|
|
2632
|
-
}
|
|
2633
|
-
/**
|
|
2634
|
-
* Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham
|
|
2635
|
-
* @return {Date}
|
|
2636
|
-
*/
|
|
2637
|
-
sofZmanShmaMGA() {
|
|
2638
|
-
// Magen Avraham
|
|
2639
|
-
const alot72 = this.sunriseOffset(-72, false);
|
|
2640
|
-
const tzeit72 = this.sunsetOffset(72, false);
|
|
2641
|
-
const temporalHour = (tzeit72 - alot72) / 12; // ms in hour
|
|
2642
|
-
return new Date(alot72.getTime() + 3 * temporalHour);
|
|
2643
|
-
}
|
|
2644
|
-
/**
|
|
2645
|
-
* Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham
|
|
3634
|
+
* Upper edge of the Sun appears over the eastern horizon in the morning (0.833° above horizon)
|
|
2646
3635
|
* @return {Date}
|
|
2647
3636
|
*/
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
const tzeit72 = this.sunsetOffset(72, false);
|
|
2652
|
-
const temporalHour = (tzeit72 - alot72) / 12; // ms in hour
|
|
2653
|
-
return new Date(alot72.getTime() + 4 * temporalHour);
|
|
3637
|
+
seaLevelSunrise() {
|
|
3638
|
+
const zdt = this.noaa.getSeaLevelSunrise();
|
|
3639
|
+
return zdtToDate(zdt);
|
|
2654
3640
|
}
|
|
2655
3641
|
/**
|
|
2656
|
-
*
|
|
3642
|
+
* When the upper edge of the Sun disappears below the horizon (0.833° below horizon)
|
|
2657
3643
|
* @return {Date}
|
|
2658
3644
|
*/
|
|
2659
|
-
|
|
2660
|
-
|
|
3645
|
+
sunset() {
|
|
3646
|
+
const zdt = this.noaa.getSunset();
|
|
3647
|
+
return zdtToDate(zdt);
|
|
2661
3648
|
}
|
|
2662
3649
|
/**
|
|
2663
|
-
*
|
|
3650
|
+
* When the upper edge of the Sun disappears below the horizon (0.833° below horizon)
|
|
2664
3651
|
* @return {Date}
|
|
2665
3652
|
*/
|
|
2666
|
-
|
|
2667
|
-
|
|
3653
|
+
seaLevelSunset() {
|
|
3654
|
+
const zdt = this.noaa.getSeaLevelSunset();
|
|
3655
|
+
return zdtToDate(zdt);
|
|
2668
3656
|
}
|
|
2669
3657
|
/**
|
|
2670
|
-
*
|
|
3658
|
+
* Civil dawn; Sun is 6° below the horizon in the morning
|
|
2671
3659
|
* @return {Date}
|
|
2672
3660
|
*/
|
|
2673
|
-
|
|
2674
|
-
|
|
3661
|
+
dawn() {
|
|
3662
|
+
const zdt = this.noaa.getBeginCivilTwilight();
|
|
3663
|
+
return zdtToDate(zdt);
|
|
2675
3664
|
}
|
|
2676
3665
|
/**
|
|
2677
|
-
*
|
|
2678
|
-
* Default is 8.5 degrees for 3 small stars, use 7.083 degrees for 3 medium-sized stars.
|
|
3666
|
+
* Civil dusk; Sun is 6° below the horizon in the evening
|
|
2679
3667
|
* @return {Date}
|
|
2680
3668
|
*/
|
|
2681
|
-
|
|
2682
|
-
|
|
3669
|
+
dusk() {
|
|
3670
|
+
const zdt = this.noaa.getEndCivilTwilight();
|
|
3671
|
+
return zdtToDate(zdt);
|
|
3672
|
+
}
|
|
3673
|
+
/** @return {Date} */
|
|
3674
|
+
gregEve() {
|
|
3675
|
+
const prev = new Date(this.date);
|
|
3676
|
+
prev.setDate(prev.getDate() - 1);
|
|
3677
|
+
const zman = new Zmanim(this.gloc, prev);
|
|
3678
|
+
return zman.sunset();
|
|
2683
3679
|
}
|
|
2684
3680
|
/**
|
|
2685
|
-
*
|
|
2686
|
-
* @return {
|
|
3681
|
+
* @private
|
|
3682
|
+
* @return {number}
|
|
2687
3683
|
*/
|
|
2688
|
-
|
|
2689
|
-
return this.sunrise();
|
|
3684
|
+
nightHour() {
|
|
3685
|
+
return (this.sunrise() - this.gregEve()) / 12; // ms in hour
|
|
2690
3686
|
}
|
|
2691
3687
|
/**
|
|
2692
|
-
*
|
|
3688
|
+
* Midday – Chatzot; Sunrise plus 6 halachic hours
|
|
2693
3689
|
* @return {Date}
|
|
2694
3690
|
*/
|
|
2695
|
-
|
|
2696
|
-
|
|
3691
|
+
chatzot() {
|
|
3692
|
+
const zdt = this.noaa.getSunTransit();
|
|
3693
|
+
return zdtToDate(zdt);
|
|
2697
3694
|
}
|
|
2698
|
-
|
|
2699
3695
|
/**
|
|
2700
|
-
*
|
|
2701
|
-
* @
|
|
2702
|
-
* @param {Intl.DateTimeFormat} timeFormat
|
|
2703
|
-
* @return {string}
|
|
3696
|
+
* Midnight – Chatzot; Sunset plus 6 halachic hours
|
|
3697
|
+
* @return {Date}
|
|
2704
3698
|
*/
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
const hm = time.split(':');
|
|
2708
|
-
if (hm[0] === '24') {
|
|
2709
|
-
return '00:' + hm[1];
|
|
2710
|
-
}
|
|
2711
|
-
return time;
|
|
3699
|
+
chatzotNight() {
|
|
3700
|
+
return new Date(this.sunrise().getTime() - this.nightHour() * 6);
|
|
2712
3701
|
}
|
|
2713
|
-
|
|
2714
3702
|
/**
|
|
2715
|
-
*
|
|
2716
|
-
* @param {Date} dt
|
|
3703
|
+
* Dawn – Alot haShachar; Sun is 16.1° below the horizon in the morning
|
|
2717
3704
|
* @return {Date}
|
|
2718
3705
|
*/
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
if (isNaN(millis)) {
|
|
2722
|
-
return dt;
|
|
2723
|
-
}
|
|
2724
|
-
// Round up to next minute if needed
|
|
2725
|
-
const millisOnly = dt.getMilliseconds();
|
|
2726
|
-
const seconds = dt.getSeconds();
|
|
2727
|
-
if (seconds === 0 && millisOnly === 0) {
|
|
2728
|
-
return dt;
|
|
2729
|
-
}
|
|
2730
|
-
const secAndMillis = seconds * 1000 + millisOnly;
|
|
2731
|
-
const delta = secAndMillis >= 30000 ? 60000 - secAndMillis : -1 * secAndMillis;
|
|
2732
|
-
return new Date(millis + delta);
|
|
3706
|
+
alotHaShachar() {
|
|
3707
|
+
return this.timeAtAngle(16.1, true);
|
|
2733
3708
|
}
|
|
2734
|
-
|
|
2735
3709
|
/**
|
|
2736
|
-
*
|
|
2737
|
-
* @
|
|
2738
|
-
* @param {Date} date
|
|
2739
|
-
* @return {string}
|
|
3710
|
+
* Earliest talis & tefillin – Misheyakir; Sun is 11.5° below the horizon in the morning
|
|
3711
|
+
* @return {Date}
|
|
2740
3712
|
*/
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
const offsetAbs = Math.abs(offset);
|
|
2744
|
-
const hours = Math.floor(offsetAbs / 60);
|
|
2745
|
-
const minutes = offsetAbs % 60;
|
|
2746
|
-
return (offset < 0 ? '+' : '-') + pad2(hours) + ':' + pad2(minutes);
|
|
3713
|
+
misheyakir() {
|
|
3714
|
+
return this.timeAtAngle(11.5, true);
|
|
2747
3715
|
}
|
|
2748
|
-
|
|
2749
3716
|
/**
|
|
2750
|
-
*
|
|
2751
|
-
* @
|
|
2752
|
-
* @param {Date} date
|
|
2753
|
-
* @return {string}
|
|
3717
|
+
* Earliest talis & tefillin – Misheyakir Machmir; Sun is 10.2° below the horizon in the morning
|
|
3718
|
+
* @return {Date}
|
|
2754
3719
|
*/
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
return null;
|
|
2758
|
-
}
|
|
2759
|
-
return getPseudoISO(tzid, date).substring(0, 19) + Zmanim.timeZoneOffset(tzid, date);
|
|
3720
|
+
misheyakirMachmir() {
|
|
3721
|
+
return this.timeAtAngle(10.2, true);
|
|
2760
3722
|
}
|
|
2761
|
-
|
|
2762
3723
|
/**
|
|
2763
|
-
*
|
|
2764
|
-
* @
|
|
2765
|
-
* @param {
|
|
3724
|
+
* Utility method for using elevation-aware sunrise/sunset
|
|
3725
|
+
* @private
|
|
3726
|
+
* @param {number} hours
|
|
2766
3727
|
* @return {Date}
|
|
2767
3728
|
*/
|
|
2768
|
-
|
|
2769
|
-
const
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
if (offset > 0 && sunrise.getSeconds() >= 30) {
|
|
2776
|
-
offset++;
|
|
2777
|
-
}
|
|
2778
|
-
sunrise.setSeconds(0, 0);
|
|
2779
|
-
}
|
|
2780
|
-
return new Date(sunrise.getTime() + offset * 60 * 1000);
|
|
3729
|
+
getShaahZmanisBasedZman(hours) {
|
|
3730
|
+
const startOfDay = this.noaa.getSunrise();
|
|
3731
|
+
const endOfDay = this.noaa.getSunset();
|
|
3732
|
+
const temporalHour = this.noaa.getTemporalHour(startOfDay, endOfDay);
|
|
3733
|
+
const offset = Math.round(temporalHour * hours);
|
|
3734
|
+
const zdt = NOAACalculator.getTimeOffset(startOfDay, offset);
|
|
3735
|
+
return zdtToDate(zdt);
|
|
2781
3736
|
}
|
|
2782
|
-
|
|
2783
3737
|
/**
|
|
2784
|
-
*
|
|
2785
|
-
* @param {number} offset minutes
|
|
2786
|
-
* @param {boolean} roundMinute round time to nearest minute (default true)
|
|
3738
|
+
* Latest Shema (Gra); Sunrise plus 3 halachic hours, according to the Gra
|
|
2787
3739
|
* @return {Date}
|
|
2788
3740
|
*/
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
return sunset;
|
|
2793
|
-
}
|
|
2794
|
-
if (roundMinute) {
|
|
2795
|
-
// For Havdalah only, round up to next minute if needed
|
|
2796
|
-
if (offset > 0 && sunset.getSeconds() >= 30) {
|
|
2797
|
-
offset++;
|
|
2798
|
-
}
|
|
2799
|
-
sunset.setSeconds(0, 0);
|
|
2800
|
-
}
|
|
2801
|
-
return new Date(sunset.getTime() + offset * 60 * 1000);
|
|
3741
|
+
sofZmanShma() {
|
|
3742
|
+
// Gra
|
|
3743
|
+
return this.getShaahZmanisBasedZman(3);
|
|
2802
3744
|
}
|
|
2803
|
-
|
|
2804
3745
|
/**
|
|
2805
|
-
*
|
|
2806
|
-
* @
|
|
2807
|
-
* @param {number} offset
|
|
2808
|
-
* @param {Intl.DateTimeFormat} timeFormat
|
|
2809
|
-
* @return {Object[]}
|
|
3746
|
+
* Latest Shacharit (Gra); Sunrise plus 4 halachic hours, according to the Gra
|
|
3747
|
+
* @return {Date}
|
|
2810
3748
|
*/
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
// `No sunset for ${location} on ${hd}`
|
|
2815
|
-
return [undefined, undefined];
|
|
2816
|
-
}
|
|
2817
|
-
const time = Zmanim.formatTime(dt, timeFormat);
|
|
2818
|
-
return [dt, time];
|
|
3749
|
+
sofZmanTfilla() {
|
|
3750
|
+
// Gra
|
|
3751
|
+
return this.getShaahZmanisBasedZman(4);
|
|
2819
3752
|
}
|
|
2820
|
-
|
|
2821
3753
|
/**
|
|
2822
|
-
*
|
|
2823
|
-
* @
|
|
2824
|
-
* @param {number} angle degrees for solar depression.
|
|
2825
|
-
* Default is 8.5 degrees for 3 small stars, use 7.083 degrees for 3 medium-sized stars.
|
|
2826
|
-
* @param {Intl.DateTimeFormat} timeFormat
|
|
2827
|
-
* @return {Object[]}
|
|
3754
|
+
* Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham
|
|
3755
|
+
* @return {Date}
|
|
2828
3756
|
*/
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
const timeStr = Zmanim.formatTime(time, timeFormat);
|
|
2836
|
-
return [time, timeStr];
|
|
3757
|
+
sofZmanShmaMGA() {
|
|
3758
|
+
// Magen Avraham
|
|
3759
|
+
const alot72 = this.sunriseOffset(-72, false);
|
|
3760
|
+
const tzeit72 = this.sunsetOffset(72, false);
|
|
3761
|
+
const temporalHour = (tzeit72 - alot72) / 12; // ms in hour
|
|
3762
|
+
return new Date(alot72.getTime() + 3 * temporalHour);
|
|
2837
3763
|
}
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
/*
|
|
2841
|
-
Hebcal - A Jewish Calendar Generator
|
|
2842
|
-
Copyright (c) 1994-2020 Danny Sadinoff
|
|
2843
|
-
Portions copyright Eyal Schachter and Michael J. Radwin
|
|
2844
|
-
|
|
2845
|
-
https://github.com/hebcal/hebcal-es6
|
|
2846
|
-
|
|
2847
|
-
This program is free software; you can redistribute it and/or
|
|
2848
|
-
modify it under the terms of the GNU General Public License
|
|
2849
|
-
as published by the Free Software Foundation; either version 2
|
|
2850
|
-
of the License, or (at your option) any later version.
|
|
2851
|
-
|
|
2852
|
-
This program is distributed in the hope that it will be useful,
|
|
2853
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
2854
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
2855
|
-
GNU General Public License for more details.
|
|
2856
|
-
|
|
2857
|
-
You should have received a copy of the GNU General Public License
|
|
2858
|
-
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
2859
|
-
*/
|
|
2860
|
-
|
|
2861
|
-
const classicCities0 = [['Ashdod', 'IL', 31.79213, 34.64966, 'Asia/Jerusalem'], ['Atlanta', 'US', 33.749, -84.38798, 'America/New_York'], ['Austin', 'US', 30.26715, -97.74306, 'America/Chicago'], ['Baghdad', 'IQ', 33.34058, 44.40088, 'Asia/Baghdad'], ['Beer Sheva', 'IL', 31.25181, 34.7913, 'Asia/Jerusalem'], ['Berlin', 'DE', 52.52437, 13.41053, 'Europe/Berlin'], ['Baltimore', 'US', 39.29038, -76.61219, 'America/New_York'], ['Bogota', 'CO', 4.60971, -74.08175, 'America/Bogota'], ['Boston', 'US', 42.35843, -71.05977, 'America/New_York'], ['Budapest', 'HU', 47.49801, 19.03991, 'Europe/Budapest'], ['Buenos Aires', 'AR', -34.61315, -58.37723, 'America/Argentina/Buenos_Aires'], ['Buffalo', 'US', 42.88645, -78.87837, 'America/New_York'], ['Chicago', 'US', 41.85003, -87.65005, 'America/Chicago'], ['Cincinnati', 'US', 39.162, -84.45689, 'America/New_York'], ['Cleveland', 'US', 41.4995, -81.69541, 'America/New_York'], ['Dallas', 'US', 32.78306, -96.80667, 'America/Chicago'], ['Denver', 'US', 39.73915, -104.9847, 'America/Denver'], ['Detroit', 'US', 42.33143, -83.04575, 'America/Detroit'], ['Eilat', 'IL', 29.55805, 34.94821, 'Asia/Jerusalem'], ['Gibraltar', 'GI', 36.14474, -5.35257, 'Europe/Gibraltar'], ['Haifa', 'IL', 32.81841, 34.9885, 'Asia/Jerusalem'], ['Hawaii', 'US', 21.30694, -157.85833, 'Pacific/Honolulu'], ['Helsinki', 'FI', 60.16952, 24.93545, 'Europe/Helsinki'], ['Houston', 'US', 29.76328, -95.36327, 'America/Chicago'], ['Jerusalem', 'IL', 31.76904, 35.21633, 'Asia/Jerusalem'], ['Johannesburg', 'ZA', -26.20227, 28.04363, 'Africa/Johannesburg'], ['Kiev', 'UA', 50.45466, 30.5238, 'Europe/Kiev'], ['La Paz', 'BO', -16.5, -68.15, 'America/La_Paz'], ['Livingston', 'US', 40.79593, -74.31487, 'America/New_York'], ['Las Vegas', 'US', 36.17497, -115.13722, 'America/Los_Angeles'], ['London', 'GB', 51.50853, -0.12574, 'Europe/London'], ['Los Angeles', 'US', 34.05223, -118.24368, 'America/Los_Angeles'], ['Marseilles', 'FR', 43.29695, 5.38107, 'Europe/Paris'], ['Miami', 'US', 25.77427, -80.19366, 'America/New_York'], ['Minneapolis', 'US', 44.97997, -93.26384, 'America/Chicago'], ['Melbourne', 'AU', -37.814, 144.96332, 'Australia/Melbourne'], ['Mexico City', 'MX', 19.42847, -99.12766, 'America/Mexico_City'], ['Montreal', 'CA', 45.50884, -73.58781, 'America/Toronto'], ['Moscow', 'RU', 55.75222, 37.61556, 'Europe/Moscow'], ['New York', 'US', 40.71427, -74.00597, 'America/New_York'], ['Omaha', 'US', 41.25861, -95.93779, 'America/Chicago'], ['Ottawa', 'CA', 45.41117, -75.69812, 'America/Toronto'], ['Panama City', 'PA', 8.9936, -79.51973, 'America/Panama'], ['Paris', 'FR', 48.85341, 2.3488, 'Europe/Paris'], ['Pawtucket', 'US', 41.87871, -71.38256, 'America/New_York'], ['Petach Tikvah', 'IL', 32.08707, 34.88747, 'Asia/Jerusalem'], ['Philadelphia', 'US', 39.95233, -75.16379, 'America/New_York'], ['Phoenix', 'US', 33.44838, -112.07404, 'America/Phoenix'], ['Pittsburgh', 'US', 40.44062, -79.99589, 'America/New_York'], ['Providence', 'US', 41.82399, -71.41283, 'America/New_York'], ['Portland', 'US', 45.52345, -122.67621, 'America/Los_Angeles'], ['Saint Louis', 'US', 38.62727, -90.19789, 'America/Chicago'], ['Saint Petersburg', 'RU', 59.93863, 30.31413, 'Europe/Moscow'], ['San Diego', 'US', 32.71533, -117.15726, 'America/Los_Angeles'], ['San Francisco', 'US', 37.77493, -122.41942, 'America/Los_Angeles'], ['Sao Paulo', 'BR', -23.5475, -46.63611, 'America/Sao_Paulo'], ['Seattle', 'US', 47.60621, -122.33207, 'America/Los_Angeles'], ['Sydney', 'AU', -33.86785, 151.20732, 'Australia/Sydney'], ['Tel Aviv', 'IL', 32.08088, 34.78057, 'Asia/Jerusalem'], ['Tiberias', 'IL', 32.79221, 35.53124, 'Asia/Jerusalem'], ['Toronto', 'CA', 43.70011, -79.4163, 'America/Toronto'], ['Vancouver', 'CA', 49.24966, -123.11934, 'America/Vancouver'], ['White Plains', 'US', 41.03399, -73.76291, 'America/New_York'], ['Washington DC', 'US', 38.89511, -77.03637, 'America/New_York'], ['Worcester', 'US', 42.26259, -71.80229, 'America/New_York']];
|
|
2862
|
-
const classicCities = Object.create(null);
|
|
2863
|
-
|
|
2864
|
-
// Zip-Codes.com TimeZone IDs
|
|
2865
|
-
const ZIPCODES_TZ_MAP = {
|
|
2866
|
-
'0': 'UTC',
|
|
2867
|
-
'4': 'America/Puerto_Rico',
|
|
2868
|
-
// Atlantic (GMT -04:00)
|
|
2869
|
-
'5': 'America/New_York',
|
|
2870
|
-
// Eastern (GMT -05:00)
|
|
2871
|
-
'6': 'America/Chicago',
|
|
2872
|
-
// Central (GMT -06:00)
|
|
2873
|
-
'7': 'America/Denver',
|
|
2874
|
-
// Mountain (GMT -07:00)
|
|
2875
|
-
'8': 'America/Los_Angeles',
|
|
2876
|
-
// Pacific (GMT -08:00)
|
|
2877
|
-
'9': 'America/Anchorage',
|
|
2878
|
-
// Alaska (GMT -09:00)
|
|
2879
|
-
'10': 'Pacific/Honolulu',
|
|
2880
|
-
// Hawaii-Aleutian Islands (GMT -10:00)
|
|
2881
|
-
'11': 'Pacific/Pago_Pago',
|
|
2882
|
-
// American Samoa (GMT -11:00)
|
|
2883
|
-
'13': 'Pacific/Funafuti',
|
|
2884
|
-
// Marshall Islands (GMT +12:00)
|
|
2885
|
-
'14': 'Pacific/Guam',
|
|
2886
|
-
// Guam (GMT +10:00)
|
|
2887
|
-
'15': 'Pacific/Palau',
|
|
2888
|
-
// Palau (GMT +9:00)
|
|
2889
|
-
'16': 'Pacific/Chuuk' // Micronesia (GMT +11:00)
|
|
2890
|
-
};
|
|
2891
|
-
|
|
2892
|
-
/** @private */
|
|
2893
|
-
const timeFormatCache = Object.create(null);
|
|
2894
|
-
|
|
2895
|
-
/**
|
|
2896
|
-
* Gets a 24-hour time formatter (e.g. 07:41 or 20:03) from cache
|
|
2897
|
-
* or makes a new one if needed
|
|
2898
|
-
* @private
|
|
2899
|
-
* @param {string} tzid
|
|
2900
|
-
* @return {Intl.DateTimeFormat}
|
|
2901
|
-
*/
|
|
2902
|
-
function getFormatter(tzid) {
|
|
2903
|
-
const fmt = timeFormatCache[tzid];
|
|
2904
|
-
if (fmt) return fmt;
|
|
2905
|
-
const f = new Intl.DateTimeFormat('en-US', {
|
|
2906
|
-
timeZone: tzid,
|
|
2907
|
-
hour: 'numeric',
|
|
2908
|
-
minute: 'numeric',
|
|
2909
|
-
hour12: false
|
|
2910
|
-
});
|
|
2911
|
-
timeFormatCache[tzid] = f;
|
|
2912
|
-
return f;
|
|
2913
|
-
}
|
|
2914
|
-
|
|
2915
|
-
/** Class representing Location */
|
|
2916
|
-
class Location {
|
|
2917
3764
|
/**
|
|
2918
|
-
*
|
|
2919
|
-
* @
|
|
2920
|
-
* @param {number} longitude - Longitude as a decimal, valid range -180 thru +180 (e.g. -87.65005)
|
|
2921
|
-
* @param {boolean} il - in Israel (true) or Diaspora (false)
|
|
2922
|
-
* @param {string} tzid - Olson timezone ID, e.g. "America/Chicago"
|
|
2923
|
-
* @param {string} cityName - optional descriptive city name
|
|
2924
|
-
* @param {string} countryCode - ISO 3166 alpha-2 country code (e.g. "FR")
|
|
2925
|
-
* @param {string} geoid - optional string or numeric geographic ID
|
|
3765
|
+
* Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham
|
|
3766
|
+
* @return {Date}
|
|
2926
3767
|
*/
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
if (isNaN(long) || long < -180 || long > 180) {
|
|
2934
|
-
throw new RangeError(`Longitude ${longitude} out of range [-180,180]`);
|
|
2935
|
-
}
|
|
2936
|
-
this.latitude = lat;
|
|
2937
|
-
this.longitude = long;
|
|
2938
|
-
this.il = Boolean(il);
|
|
2939
|
-
this.tzid = tzid;
|
|
2940
|
-
this.name = cityName;
|
|
2941
|
-
this.cc = countryCode;
|
|
2942
|
-
this.geoid = geoid;
|
|
2943
|
-
}
|
|
2944
|
-
|
|
2945
|
-
/** @return {number} */
|
|
2946
|
-
getLatitude() {
|
|
2947
|
-
return this.latitude;
|
|
2948
|
-
}
|
|
2949
|
-
|
|
2950
|
-
/** @return {number} */
|
|
2951
|
-
getLongitude() {
|
|
2952
|
-
return this.longitude;
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
/** @return {boolean} */
|
|
2956
|
-
getIsrael() {
|
|
2957
|
-
return this.il;
|
|
2958
|
-
}
|
|
2959
|
-
|
|
2960
|
-
/** @return {string} */
|
|
2961
|
-
getName() {
|
|
2962
|
-
return this.name;
|
|
3768
|
+
sofZmanTfillaMGA() {
|
|
3769
|
+
// Magen Avraham
|
|
3770
|
+
const alot72 = this.sunriseOffset(-72, false);
|
|
3771
|
+
const tzeit72 = this.sunsetOffset(72, false);
|
|
3772
|
+
const temporalHour = (tzeit72 - alot72) / 12; // ms in hour
|
|
3773
|
+
return new Date(alot72.getTime() + 4 * temporalHour);
|
|
2963
3774
|
}
|
|
2964
|
-
|
|
2965
3775
|
/**
|
|
2966
|
-
*
|
|
2967
|
-
* @return {
|
|
3776
|
+
* Earliest Mincha – Mincha Gedola; Sunrise plus 6.5 halachic hours
|
|
3777
|
+
* @return {Date}
|
|
2968
3778
|
*/
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
if (!name) return name;
|
|
2972
|
-
const comma = name.indexOf(', ');
|
|
2973
|
-
if (comma === -1) return name;
|
|
2974
|
-
if (this.cc === 'US' && name[comma + 2] === 'D') {
|
|
2975
|
-
if (name[comma + 3] === 'C') {
|
|
2976
|
-
return name.substring(0, comma + 4);
|
|
2977
|
-
} else if (name[comma + 3] === '.' && name[comma + 4] === 'C') {
|
|
2978
|
-
return name.substring(0, comma + 6);
|
|
2979
|
-
}
|
|
2980
|
-
}
|
|
2981
|
-
return name.substring(0, comma);
|
|
2982
|
-
}
|
|
2983
|
-
|
|
2984
|
-
/** @return {string} */
|
|
2985
|
-
getCountryCode() {
|
|
2986
|
-
return this.cc;
|
|
3779
|
+
minchaGedola() {
|
|
3780
|
+
return this.getShaahZmanisBasedZman(6.5);
|
|
2987
3781
|
}
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3782
|
+
/**
|
|
3783
|
+
* Preferable earliest time to recite Minchah – Mincha Ketana; Sunrise plus 9.5 halachic hours
|
|
3784
|
+
* @return {Date}
|
|
3785
|
+
*/
|
|
3786
|
+
minchaKetana() {
|
|
3787
|
+
return this.getShaahZmanisBasedZman(9.5);
|
|
2992
3788
|
}
|
|
2993
|
-
|
|
2994
3789
|
/**
|
|
2995
|
-
*
|
|
2996
|
-
* @return {
|
|
3790
|
+
* Plag haMincha; Sunrise plus 10.75 halachic hours
|
|
3791
|
+
* @return {Date}
|
|
2997
3792
|
*/
|
|
2998
|
-
|
|
2999
|
-
return
|
|
3793
|
+
plagHaMincha() {
|
|
3794
|
+
return this.getShaahZmanisBasedZman(10.75);
|
|
3000
3795
|
}
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3796
|
+
/**
|
|
3797
|
+
* @param {number} [angle=8.5] optional time for solar depression.
|
|
3798
|
+
* Default is 8.5 degrees for 3 small stars, use 7.083 degrees for 3 medium-sized stars.
|
|
3799
|
+
* @return {Date}
|
|
3800
|
+
*/
|
|
3801
|
+
tzeit(angle = 8.5) {
|
|
3802
|
+
return this.timeAtAngle(angle, false);
|
|
3005
3803
|
}
|
|
3006
|
-
|
|
3007
3804
|
/**
|
|
3008
|
-
*
|
|
3009
|
-
*
|
|
3010
|
-
* 'Ashdod', 'Atlanta', 'Austin', 'Baghdad', 'Beer Sheva',
|
|
3011
|
-
* 'Berlin', 'Baltimore', 'Bogota', 'Boston', 'Budapest',
|
|
3012
|
-
* 'Buenos Aires', 'Buffalo', 'Chicago', 'Cincinnati', 'Cleveland',
|
|
3013
|
-
* 'Dallas', 'Denver', 'Detroit', 'Eilat', 'Gibraltar', 'Haifa',
|
|
3014
|
-
* 'Hawaii', 'Helsinki', 'Houston', 'Jerusalem', 'Johannesburg',
|
|
3015
|
-
* 'Kiev', 'La Paz', 'Livingston', 'Las Vegas', 'London', 'Los Angeles',
|
|
3016
|
-
* 'Marseilles', 'Miami', 'Minneapolis', 'Melbourne', 'Mexico City',
|
|
3017
|
-
* 'Montreal', 'Moscow', 'New York', 'Omaha', 'Ottawa', 'Panama City',
|
|
3018
|
-
* 'Paris', 'Pawtucket', 'Petach Tikvah', 'Philadelphia', 'Phoenix',
|
|
3019
|
-
* 'Pittsburgh', 'Providence', 'Portland', 'Saint Louis', 'Saint Petersburg',
|
|
3020
|
-
* 'San Diego', 'San Francisco', 'Sao Paulo', 'Seattle', 'Sydney',
|
|
3021
|
-
* 'Tel Aviv', 'Tiberias', 'Toronto', 'Vancouver', 'White Plains',
|
|
3022
|
-
* 'Washington DC', 'Worcester'
|
|
3023
|
-
* @param {string} name
|
|
3024
|
-
* @return {Location}
|
|
3805
|
+
* Alias for sunrise
|
|
3806
|
+
* @return {Date}
|
|
3025
3807
|
*/
|
|
3026
|
-
|
|
3027
|
-
return
|
|
3808
|
+
neitzHaChama() {
|
|
3809
|
+
return this.sunrise();
|
|
3028
3810
|
}
|
|
3029
|
-
|
|
3030
3811
|
/**
|
|
3031
|
-
*
|
|
3032
|
-
* @param {Date|HDate} hdate
|
|
3812
|
+
* Alias for sunset
|
|
3033
3813
|
* @return {Date}
|
|
3034
3814
|
*/
|
|
3035
|
-
|
|
3036
|
-
return
|
|
3815
|
+
shkiah() {
|
|
3816
|
+
return this.sunset();
|
|
3037
3817
|
}
|
|
3038
3818
|
|
|
3039
3819
|
/**
|
|
3040
|
-
*
|
|
3041
|
-
* @param {Date
|
|
3042
|
-
* @param {
|
|
3043
|
-
* @return {
|
|
3820
|
+
* Uses timeFormat to return a date like '20:34'
|
|
3821
|
+
* @param {Date} dt
|
|
3822
|
+
* @param {Intl.DateTimeFormat} timeFormat
|
|
3823
|
+
* @return {string}
|
|
3044
3824
|
*/
|
|
3045
|
-
|
|
3046
|
-
|
|
3825
|
+
static formatTime(dt, timeFormat) {
|
|
3826
|
+
const time = timeFormat.format(dt);
|
|
3827
|
+
const hm = time.split(':');
|
|
3828
|
+
if (hm[0] === '24') {
|
|
3829
|
+
return '00:' + hm[1];
|
|
3830
|
+
}
|
|
3831
|
+
return time;
|
|
3047
3832
|
}
|
|
3048
3833
|
|
|
3049
|
-
/**
|
|
3050
|
-
|
|
3051
|
-
|
|
3834
|
+
/**
|
|
3835
|
+
* Discards seconds, rounding to nearest minute.
|
|
3836
|
+
* @param {Date} dt
|
|
3837
|
+
* @return {Date}
|
|
3838
|
+
*/
|
|
3839
|
+
static roundTime(dt) {
|
|
3840
|
+
const millis = dt.getTime();
|
|
3841
|
+
if (isNaN(millis)) {
|
|
3842
|
+
return dt;
|
|
3843
|
+
}
|
|
3844
|
+
// Round up to next minute if needed
|
|
3845
|
+
const millisOnly = dt.getMilliseconds();
|
|
3846
|
+
const seconds = dt.getSeconds();
|
|
3847
|
+
if (seconds === 0 && millisOnly === 0) {
|
|
3848
|
+
return dt;
|
|
3849
|
+
}
|
|
3850
|
+
const secAndMillis = seconds * 1000 + millisOnly;
|
|
3851
|
+
const delta = secAndMillis >= 30000 ? 60000 - secAndMillis : -1 * secAndMillis;
|
|
3852
|
+
return new Date(millis + delta);
|
|
3052
3853
|
}
|
|
3053
3854
|
|
|
3054
3855
|
/**
|
|
3055
|
-
*
|
|
3056
|
-
* @param {
|
|
3057
|
-
* @param {
|
|
3856
|
+
* Get offset string (like "+05:00" or "-08:00") from tzid (like "Europe/Moscow")
|
|
3857
|
+
* @param {string} tzid
|
|
3858
|
+
* @param {Date} date
|
|
3058
3859
|
* @return {string}
|
|
3059
3860
|
*/
|
|
3060
|
-
static
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
const plus = tz > 0 ? '+' : '';
|
|
3067
|
-
return `Etc/GMT${plus}${tz}`;
|
|
3068
|
-
}
|
|
3069
|
-
} else if (tz == 2 && dst == 'israel') {
|
|
3070
|
-
return 'Asia/Jerusalem';
|
|
3071
|
-
} else if (dst == 'eu') {
|
|
3072
|
-
switch (tz) {
|
|
3073
|
-
case -2:
|
|
3074
|
-
return 'Atlantic/Cape_Verde';
|
|
3075
|
-
case -1:
|
|
3076
|
-
return 'Atlantic/Azores';
|
|
3077
|
-
case 0:
|
|
3078
|
-
return 'Europe/London';
|
|
3079
|
-
case 1:
|
|
3080
|
-
return 'Europe/Paris';
|
|
3081
|
-
case 2:
|
|
3082
|
-
return 'Europe/Athens';
|
|
3083
|
-
}
|
|
3084
|
-
} else if (dst == 'usa') {
|
|
3085
|
-
return ZIPCODES_TZ_MAP[String(tz * -1)];
|
|
3086
|
-
}
|
|
3087
|
-
return undefined;
|
|
3861
|
+
static timeZoneOffset(tzid, date) {
|
|
3862
|
+
const offset = getTimezoneOffset(tzid, date);
|
|
3863
|
+
const offsetAbs = Math.abs(offset);
|
|
3864
|
+
const hours = Math.floor(offsetAbs / 60);
|
|
3865
|
+
const minutes = offsetAbs % 60;
|
|
3866
|
+
return (offset < 0 ? '+' : '-') + pad2(hours) + ':' + pad2(minutes);
|
|
3088
3867
|
}
|
|
3089
3868
|
|
|
3090
3869
|
/**
|
|
3091
|
-
*
|
|
3092
|
-
* @
|
|
3093
|
-
*
|
|
3094
|
-
* @param {string} state two-letter all-caps US state abbreviation like 'CA'
|
|
3095
|
-
* @param {number} tz positive number, 5=America/New_York, 8=America/Los_Angeles
|
|
3096
|
-
* @param {string} dst single char 'Y' or 'N'
|
|
3870
|
+
* Returns a string like "2022-04-01T13:06:00-11:00"
|
|
3871
|
+
* @param {string} tzid
|
|
3872
|
+
* @param {Date} date
|
|
3097
3873
|
* @return {string}
|
|
3098
3874
|
*/
|
|
3099
|
-
static
|
|
3100
|
-
if (
|
|
3101
|
-
return
|
|
3102
|
-
} else if (tz == 7 && state == 'AZ') {
|
|
3103
|
-
return dst == 'Y' ? 'America/Denver' : 'America/Phoenix';
|
|
3104
|
-
} else {
|
|
3105
|
-
return ZIPCODES_TZ_MAP[tz];
|
|
3875
|
+
static formatISOWithTimeZone(tzid, date) {
|
|
3876
|
+
if (isNaN(date.getTime())) {
|
|
3877
|
+
return null;
|
|
3106
3878
|
}
|
|
3879
|
+
return getPseudoISO(tzid, date).substring(0, 19) + Zmanim.timeZoneOffset(tzid, date);
|
|
3107
3880
|
}
|
|
3108
3881
|
|
|
3109
3882
|
/**
|
|
3110
|
-
*
|
|
3111
|
-
* @
|
|
3112
|
-
* @param {
|
|
3113
|
-
* @
|
|
3114
|
-
* @param {string} countryName full country name, e.g. 'Israel' or 'United States'
|
|
3115
|
-
* @return {string}
|
|
3883
|
+
* Returns sunrise + `offset` minutes (either positive or negative).
|
|
3884
|
+
* @param {number} offset minutes
|
|
3885
|
+
* @param {boolean} roundMinute round time to nearest minute (default true)
|
|
3886
|
+
* @return {Date}
|
|
3116
3887
|
*/
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
if (
|
|
3120
|
-
|
|
3121
|
-
if (countryName != 'Israel' && admin1 && admin1.indexOf(cityName) != 0) {
|
|
3122
|
-
cityDescr += ', ' + admin1;
|
|
3888
|
+
sunriseOffset(offset, roundMinute = true) {
|
|
3889
|
+
const sunrise = this.seaLevelSunrise();
|
|
3890
|
+
if (isNaN(sunrise.getTime())) {
|
|
3891
|
+
return sunrise;
|
|
3123
3892
|
}
|
|
3124
|
-
if (
|
|
3125
|
-
|
|
3893
|
+
if (roundMinute) {
|
|
3894
|
+
// For positive offsets only, round up to next minute if needed
|
|
3895
|
+
if (offset > 0 && sunrise.getSeconds() >= 30) {
|
|
3896
|
+
offset++;
|
|
3897
|
+
}
|
|
3898
|
+
sunrise.setSeconds(0, 0);
|
|
3126
3899
|
}
|
|
3127
|
-
return
|
|
3900
|
+
return new Date(sunrise.getTime() + offset * 60 * 1000);
|
|
3128
3901
|
}
|
|
3129
3902
|
|
|
3130
3903
|
/**
|
|
3131
|
-
*
|
|
3132
|
-
*
|
|
3133
|
-
*
|
|
3134
|
-
* @
|
|
3135
|
-
* @param {Location} location
|
|
3136
|
-
* @return {boolean}
|
|
3904
|
+
* Returns sunset + `offset` minutes (either positive or negative).
|
|
3905
|
+
* @param {number} offset minutes
|
|
3906
|
+
* @param {boolean} roundMinute round time to nearest minute (default true)
|
|
3907
|
+
* @return {Date}
|
|
3137
3908
|
*/
|
|
3138
|
-
|
|
3139
|
-
const
|
|
3140
|
-
if (
|
|
3141
|
-
return
|
|
3909
|
+
sunsetOffset(offset, roundMinute = true) {
|
|
3910
|
+
const sunset = this.seaLevelSunset();
|
|
3911
|
+
if (isNaN(sunset.getTime())) {
|
|
3912
|
+
return sunset;
|
|
3142
3913
|
}
|
|
3143
|
-
|
|
3144
|
-
|
|
3914
|
+
if (roundMinute) {
|
|
3915
|
+
// For Havdalah only, round up to next minute if needed
|
|
3916
|
+
if (offset > 0 && sunset.getSeconds() >= 30) {
|
|
3917
|
+
offset++;
|
|
3918
|
+
}
|
|
3919
|
+
sunset.setSeconds(0, 0);
|
|
3920
|
+
}
|
|
3921
|
+
return new Date(sunset.getTime() + offset * 60 * 1000);
|
|
3145
3922
|
}
|
|
3146
3923
|
}
|
|
3147
|
-
classicCities0.forEach(city => {
|
|
3148
|
-
const location = new Location(city[2], city[3], city[1] == 'IL', city[4], city[0], city[1]);
|
|
3149
|
-
Location.addLocation(location.getName(), location);
|
|
3150
|
-
});
|
|
3151
3924
|
|
|
3152
3925
|
/* eslint-disable max-len */
|
|
3153
3926
|
const days = {
|
|
@@ -3184,7 +3957,7 @@ function makeCandleEvent(e, hd, dow, location, options) {
|
|
|
3184
3957
|
}
|
|
3185
3958
|
// if offset is 0 or undefined, we'll use tzeit time
|
|
3186
3959
|
const offset = useHavdalahOffset ? options.havdalahMins : options.candleLightingMins;
|
|
3187
|
-
const zmanim = new Zmanim(
|
|
3960
|
+
const zmanim = new Zmanim(location, hd);
|
|
3188
3961
|
const time = offset ? zmanim.sunsetOffset(offset, true) : zmanim.tzeit(options.havdalahDeg);
|
|
3189
3962
|
if (isNaN(time.getTime())) {
|
|
3190
3963
|
return null; // no sunset
|
|
@@ -3327,7 +4100,7 @@ function makeFastStartEnd(ev, options) {
|
|
|
3327
4100
|
const dt = hd.greg();
|
|
3328
4101
|
const location = options.location;
|
|
3329
4102
|
const fastEndDeg = options.fastEndDeg;
|
|
3330
|
-
const zmanim = new Zmanim(
|
|
4103
|
+
const zmanim = new Zmanim(location, dt);
|
|
3331
4104
|
if (desc === 'Erev Tish\'a B\'Av') {
|
|
3332
4105
|
const sunset = zmanim.sunset();
|
|
3333
4106
|
ev.startEvent = makeTimedEvent(hd, sunset, 'Fast begins', ev, location);
|
|
@@ -3368,7 +4141,7 @@ function makeTimedEvent(hd, time, desc, ev, location) {
|
|
|
3368
4141
|
* @return {TimedEvent}
|
|
3369
4142
|
*/
|
|
3370
4143
|
function makeWeekdayChanukahCandleLighting(ev, hd, location) {
|
|
3371
|
-
const zmanim = new Zmanim(
|
|
4144
|
+
const zmanim = new Zmanim(location, hd.greg());
|
|
3372
4145
|
const candleLightingTime = zmanim.dusk();
|
|
3373
4146
|
// const candleLightingTime = zmanim.tzeit(4.6667);
|
|
3374
4147
|
return makeTimedEvent(hd, candleLightingTime, ev.getDesc(), ev, location);
|
|
@@ -3826,7 +4599,7 @@ class Sedra {
|
|
|
3826
4599
|
|
|
3827
4600
|
return new HDate(this.firstSaturday + idx * 7);
|
|
3828
4601
|
} else if (typeof parsha === 'string') {
|
|
3829
|
-
const num = parsha2id
|
|
4602
|
+
const num = parsha2id.get(parsha);
|
|
3830
4603
|
if (typeof num === 'number') {
|
|
3831
4604
|
return this.find(num);
|
|
3832
4605
|
} else if (parsha.indexOf('-') !== -1) {
|
|
@@ -3845,8 +4618,8 @@ class Sedra {
|
|
|
3845
4618
|
} else if (Array.isArray(parsha) && parsha.length === 2 && typeof parsha[0] === 'string' && typeof parsha[1] === 'string') {
|
|
3846
4619
|
const p1 = parsha[0];
|
|
3847
4620
|
const p2 = parsha[1];
|
|
3848
|
-
const num1 = parsha2id
|
|
3849
|
-
const num2 = parsha2id
|
|
4621
|
+
const num1 = parsha2id.get(p1);
|
|
4622
|
+
const num2 = parsha2id.get(p2);
|
|
3850
4623
|
if (num2 === num1 + 1) {
|
|
3851
4624
|
return this.find(-num1);
|
|
3852
4625
|
} else {
|
|
@@ -3925,10 +4698,10 @@ class Sedra {
|
|
|
3925
4698
|
* @type {string[]}
|
|
3926
4699
|
*/
|
|
3927
4700
|
const parshiot = ['Bereshit', 'Noach', 'Lech-Lecha', 'Vayera', 'Chayei Sara', 'Toldot', 'Vayetzei', 'Vayishlach', 'Vayeshev', 'Miketz', 'Vayigash', 'Vayechi', 'Shemot', 'Vaera', 'Bo', 'Beshalach', 'Yitro', 'Mishpatim', 'Terumah', 'Tetzaveh', 'Ki Tisa', 'Vayakhel', 'Pekudei', 'Vayikra', 'Tzav', 'Shmini', 'Tazria', 'Metzora', 'Achrei Mot', 'Kedoshim', 'Emor', 'Behar', 'Bechukotai', 'Bamidbar', 'Nasso', 'Beha\'alotcha', 'Sh\'lach', 'Korach', 'Chukat', 'Balak', 'Pinchas', 'Matot', 'Masei', 'Devarim', 'Vaetchanan', 'Eikev', 'Re\'eh', 'Shoftim', 'Ki Teitzei', 'Ki Tavo', 'Nitzavim', 'Vayeilech', 'Ha\'azinu'];
|
|
3928
|
-
const parsha2id =
|
|
4701
|
+
const parsha2id = new Map();
|
|
3929
4702
|
for (let id = 0; id < parshiot.length; id++) {
|
|
3930
4703
|
const name = parshiot[id];
|
|
3931
|
-
parsha2id
|
|
4704
|
+
parsha2id.set(name, id);
|
|
3932
4705
|
}
|
|
3933
4706
|
|
|
3934
4707
|
/**
|
|
@@ -4146,7 +4919,7 @@ const SUN$1 = 0;
|
|
|
4146
4919
|
const TUE$1 = 2;
|
|
4147
4920
|
const FRI$2 = 5;
|
|
4148
4921
|
const SAT$2 = 6;
|
|
4149
|
-
const NISAN$
|
|
4922
|
+
const NISAN$2 = months.NISAN;
|
|
4150
4923
|
const IYYAR = months.IYYAR;
|
|
4151
4924
|
|
|
4152
4925
|
/**
|
|
@@ -4164,11 +4937,11 @@ function dateYomHaShoah(year) {
|
|
|
4164
4937
|
if (year < 5711) {
|
|
4165
4938
|
return null;
|
|
4166
4939
|
}
|
|
4167
|
-
let nisan27dt = new HDate(27, NISAN$
|
|
4940
|
+
let nisan27dt = new HDate(27, NISAN$2, year);
|
|
4168
4941
|
if (nisan27dt.getDay() === FRI$2) {
|
|
4169
|
-
nisan27dt = new HDate(26, NISAN$
|
|
4942
|
+
nisan27dt = new HDate(26, NISAN$2, year);
|
|
4170
4943
|
} else if (nisan27dt.getDay() === SUN$1) {
|
|
4171
|
-
nisan27dt = new HDate(28, NISAN$
|
|
4944
|
+
nisan27dt = new HDate(28, NISAN$2, year);
|
|
4172
4945
|
}
|
|
4173
4946
|
return nisan27dt;
|
|
4174
4947
|
}
|
|
@@ -4184,7 +4957,7 @@ function dateYomHaZikaron(year) {
|
|
|
4184
4957
|
return null;
|
|
4185
4958
|
}
|
|
4186
4959
|
let day;
|
|
4187
|
-
const pesach = new HDate(15, NISAN$
|
|
4960
|
+
const pesach = new HDate(15, NISAN$2, year);
|
|
4188
4961
|
const pdow = pesach.getDay();
|
|
4189
4962
|
if (pdow === SUN$1) {
|
|
4190
4963
|
day = 2;
|
|
@@ -4835,7 +5608,7 @@ const TUE = 2;
|
|
|
4835
5608
|
const THU = 4;
|
|
4836
5609
|
const FRI$1 = 5;
|
|
4837
5610
|
const SAT$1 = 6;
|
|
4838
|
-
const NISAN$
|
|
5611
|
+
const NISAN$1 = months.NISAN;
|
|
4839
5612
|
// const IYYAR = months.IYYAR;
|
|
4840
5613
|
// const SIVAN = months.SIVAN;
|
|
4841
5614
|
const TAMUZ = months.TAMUZ;
|
|
@@ -4843,10 +5616,10 @@ const AV = months.AV;
|
|
|
4843
5616
|
const ELUL$1 = months.ELUL;
|
|
4844
5617
|
const TISHREI$1 = months.TISHREI;
|
|
4845
5618
|
// const CHESHVAN = months.CHESHVAN;
|
|
4846
|
-
const KISLEV
|
|
4847
|
-
const TEVET
|
|
5619
|
+
const KISLEV = months.KISLEV;
|
|
5620
|
+
const TEVET = months.TEVET;
|
|
4848
5621
|
// const SHVAT = months.SHVAT;
|
|
4849
|
-
const ADAR_I
|
|
5622
|
+
const ADAR_I = months.ADAR_I;
|
|
4850
5623
|
// const ADAR_II = months.ADAR_II;
|
|
4851
5624
|
|
|
4852
5625
|
const CHAG = flags.CHAG;
|
|
@@ -4918,7 +5691,7 @@ const emojiIsraelFlag = {
|
|
|
4918
5691
|
emoji: '🇮🇱'
|
|
4919
5692
|
};
|
|
4920
5693
|
const chanukahEmoji = '🕎';
|
|
4921
|
-
const yearCache =
|
|
5694
|
+
const yearCache = new Map();
|
|
4922
5695
|
const KEYCAP_DIGITS = ['0️⃣', '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣'];
|
|
4923
5696
|
|
|
4924
5697
|
/**
|
|
@@ -4935,12 +5708,12 @@ function getHolidaysForYear_(year) {
|
|
|
4935
5708
|
} else if (year < 1 || year > 32658) {
|
|
4936
5709
|
throw new RangeError(`Hebrew year ${year} out of range 1-32658`);
|
|
4937
5710
|
}
|
|
4938
|
-
const cached = yearCache
|
|
5711
|
+
const cached = yearCache.get(year);
|
|
4939
5712
|
if (cached) {
|
|
4940
5713
|
return cached;
|
|
4941
5714
|
}
|
|
4942
5715
|
const RH = new HDate(1, TISHREI$1, year);
|
|
4943
|
-
const pesach = new HDate(15, NISAN$
|
|
5716
|
+
const pesach = new HDate(15, NISAN$1, year);
|
|
4944
5717
|
const h = new SimpleMap();
|
|
4945
5718
|
// eslint-disable-next-line require-jsdoc
|
|
4946
5719
|
function add(...events) {
|
|
@@ -4974,27 +5747,27 @@ function getHolidaysForYear_(year) {
|
|
|
4974
5747
|
add(new HolidayEvent(new HDate(3 + (RH.getDay() == THU), TISHREI$1, year), 'Tzom Gedaliah', MINOR_FAST$1));
|
|
4975
5748
|
// first SAT after RH
|
|
4976
5749
|
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, 7 + RH.abs())), 'Shabbat Shuva', SPECIAL_SHABBAT$1));
|
|
4977
|
-
const rchTevet = HDate.shortKislev(year) ? new HDate(1, TEVET
|
|
5750
|
+
const rchTevet = HDate.shortKislev(year) ? new HDate(1, TEVET, year) : new HDate(30, KISLEV, year);
|
|
4978
5751
|
add(new HolidayEvent(rchTevet, 'Chag HaBanot', MINOR_HOLIDAY$1));
|
|
4979
5752
|
// yes, we know Kislev 30-32 are wrong
|
|
4980
5753
|
// HDate() corrects the month automatically
|
|
4981
5754
|
for (let candles = 2; candles <= 8; candles++) {
|
|
4982
|
-
const hd = new HDate(23 + candles, KISLEV
|
|
5755
|
+
const hd = new HDate(23 + candles, KISLEV, year);
|
|
4983
5756
|
add(new HolidayEvent(hd, `Chanukah: ${candles} Candles`, MINOR_HOLIDAY$1 | CHANUKAH_CANDLES$1, {
|
|
4984
5757
|
chanukahDay: candles - 1,
|
|
4985
5758
|
emoji: chanukahEmoji + KEYCAP_DIGITS[candles]
|
|
4986
5759
|
}));
|
|
4987
5760
|
}
|
|
4988
|
-
add(new HolidayEvent(new HDate(32, KISLEV
|
|
5761
|
+
add(new HolidayEvent(new HDate(32, KISLEV, year), 'Chanukah: 8th Day', MINOR_HOLIDAY$1, {
|
|
4989
5762
|
chanukahDay: 8,
|
|
4990
5763
|
emoji: chanukahEmoji
|
|
4991
5764
|
}));
|
|
4992
|
-
add(new AsaraBTevetEvent(new HDate(10, TEVET
|
|
5765
|
+
add(new AsaraBTevetEvent(new HDate(10, TEVET, year), 'Asara B\'Tevet', MINOR_FAST$1));
|
|
4993
5766
|
const pesachAbs = pesach.abs();
|
|
4994
5767
|
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 43)), 'Shabbat Shekalim', SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 30)), 'Shabbat Zachor', SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(pesachAbs - (pesach.getDay() == TUE ? 33 : 31)), 'Ta\'anit Esther', MINOR_FAST$1));
|
|
4995
5768
|
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 14) - 7), 'Shabbat Parah', SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 14)), 'Shabbat HaChodesh', SPECIAL_SHABBAT$1), new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, pesachAbs - 1)), 'Shabbat HaGadol', SPECIAL_SHABBAT$1), new HolidayEvent(
|
|
4996
5769
|
// if the fast falls on Shabbat, move to Thursday
|
|
4997
|
-
pesach.prev().getDay() == SAT$1 ? pesach.onOrBefore(THU) : new HDate(14, NISAN$
|
|
5770
|
+
pesach.prev().getDay() == SAT$1 ? pesach.onOrBefore(THU) : new HDate(14, NISAN$1, year), 'Ta\'anit Bechorot', MINOR_FAST$1));
|
|
4998
5771
|
add(new HolidayEvent(new HDate(HDate.dayOnOrBefore(SAT$1, new HDate(1, TISHREI$1, year + 1).abs() - 4)), 'Leil Selichot', MINOR_HOLIDAY$1, {
|
|
4999
5772
|
emoji: '🕍'
|
|
5000
5773
|
}));
|
|
@@ -5002,10 +5775,10 @@ function getHolidaysForYear_(year) {
|
|
|
5002
5775
|
add(new HolidayEvent(new HDate(16, months.ADAR_II, year), 'Purim Meshulash', MINOR_HOLIDAY$1));
|
|
5003
5776
|
}
|
|
5004
5777
|
if (HDate.isLeapYear(year)) {
|
|
5005
|
-
add(new HolidayEvent(new HDate(14, ADAR_I
|
|
5778
|
+
add(new HolidayEvent(new HDate(14, ADAR_I, year), 'Purim Katan', MINOR_HOLIDAY$1, {
|
|
5006
5779
|
emoji: '🎭️'
|
|
5007
5780
|
}));
|
|
5008
|
-
add(new HolidayEvent(new HDate(15, ADAR_I
|
|
5781
|
+
add(new HolidayEvent(new HDate(15, ADAR_I, year), 'Shushan Purim Katan', MINOR_HOLIDAY$1, {
|
|
5009
5782
|
emoji: '🎭️'
|
|
5010
5783
|
}));
|
|
5011
5784
|
}
|
|
@@ -5060,7 +5833,7 @@ function getHolidaysForYear_(year) {
|
|
|
5060
5833
|
const monthsInYear = HDate.monthsInYear(year);
|
|
5061
5834
|
for (let month = 1; month <= monthsInYear; month++) {
|
|
5062
5835
|
const monthName = HDate.getMonthName(month, year);
|
|
5063
|
-
if ((month == NISAN$
|
|
5836
|
+
if ((month == NISAN$1 ? HDate.daysInMonth(HDate.monthsInYear(year - 1), year - 1) : HDate.daysInMonth(month - 1, year)) == 30) {
|
|
5064
5837
|
add(new RoshChodeshEvent(new HDate(1, month, year), monthName));
|
|
5065
5838
|
add(new RoshChodeshEvent(new HDate(30, month - 1, year), monthName));
|
|
5066
5839
|
} else if (month !== TISHREI$1) {
|
|
@@ -5106,7 +5879,7 @@ function getHolidaysForYear_(year) {
|
|
|
5106
5879
|
emoji: '☀️'
|
|
5107
5880
|
}));
|
|
5108
5881
|
}
|
|
5109
|
-
yearCache
|
|
5882
|
+
yearCache.set(year, h);
|
|
5110
5883
|
return h;
|
|
5111
5884
|
}
|
|
5112
5885
|
|
|
@@ -5124,7 +5897,7 @@ function getHolidaysForYear_(year) {
|
|
|
5124
5897
|
*/
|
|
5125
5898
|
function getBirkatHaChama(year) {
|
|
5126
5899
|
const leap = HDate.isLeapYear(year);
|
|
5127
|
-
const startMonth = leap ? months.ADAR_II : NISAN$
|
|
5900
|
+
const startMonth = leap ? months.ADAR_II : NISAN$1;
|
|
5128
5901
|
const startDay = leap ? 20 : 1;
|
|
5129
5902
|
const baseRd = HDate.hebrew2abs(year, startMonth, startDay);
|
|
5130
5903
|
for (let day = 0; day <= 40; day++) {
|
|
@@ -5138,7 +5911,7 @@ function getBirkatHaChama(year) {
|
|
|
5138
5911
|
}
|
|
5139
5912
|
|
|
5140
5913
|
/** @private */
|
|
5141
|
-
const cals =
|
|
5914
|
+
const cals = new Map();
|
|
5142
5915
|
|
|
5143
5916
|
/**
|
|
5144
5917
|
* Plug-ins for daily learning calendars such as Daf Yomi, Mishna Yomi, Nach Yomi, etc.
|
|
@@ -5155,7 +5928,7 @@ class DailyLearning {
|
|
|
5155
5928
|
if (typeof calendar !== 'function') {
|
|
5156
5929
|
throw new TypeError(`Invalid calendar function: ${calendar}`);
|
|
5157
5930
|
}
|
|
5158
|
-
cals
|
|
5931
|
+
cals.set(name, calendar);
|
|
5159
5932
|
}
|
|
5160
5933
|
|
|
5161
5934
|
/**
|
|
@@ -5166,7 +5939,7 @@ class DailyLearning {
|
|
|
5166
5939
|
* @return {Event}
|
|
5167
5940
|
*/
|
|
5168
5941
|
static lookup(name, hd) {
|
|
5169
|
-
const fn = cals
|
|
5942
|
+
const fn = cals.get(name);
|
|
5170
5943
|
if (typeof fn === 'function') {
|
|
5171
5944
|
return fn(hd);
|
|
5172
5945
|
}
|
|
@@ -5174,95 +5947,7 @@ class DailyLearning {
|
|
|
5174
5947
|
}
|
|
5175
5948
|
}
|
|
5176
5949
|
|
|
5177
|
-
const
|
|
5178
|
-
const CHESHVAN = months.CHESHVAN;
|
|
5179
|
-
const KISLEV = months.KISLEV;
|
|
5180
|
-
const TEVET = months.TEVET;
|
|
5181
|
-
const SHVAT = months.SHVAT;
|
|
5182
|
-
const ADAR_I = months.ADAR_I;
|
|
5183
|
-
const ADAR_II = months.ADAR_II;
|
|
5184
|
-
|
|
5185
|
-
/**
|
|
5186
|
-
* @private
|
|
5187
|
-
* @param {number} hyear Hebrew year
|
|
5188
|
-
* @param {Date|HDate} gdate Gregorian or Hebrew date of death
|
|
5189
|
-
* @return {HDate} anniversary occurring in hyear
|
|
5190
|
-
*/
|
|
5191
|
-
function getYahrzeit_(hyear, gdate) {
|
|
5192
|
-
const orig = HDate.isHDate(gdate) ? gdate : new HDate(gdate);
|
|
5193
|
-
let hDeath = {
|
|
5194
|
-
yy: orig.getFullYear(),
|
|
5195
|
-
mm: orig.getMonth(),
|
|
5196
|
-
dd: orig.getDate()
|
|
5197
|
-
};
|
|
5198
|
-
if (hyear <= hDeath.yy) {
|
|
5199
|
-
// `Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy}`
|
|
5200
|
-
return undefined;
|
|
5201
|
-
}
|
|
5202
|
-
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hDeath.yy + 1)) {
|
|
5203
|
-
// If it's Heshvan 30 it depends on the first anniversary;
|
|
5204
|
-
// if that was not Heshvan 30, use the day before Kislev 1.
|
|
5205
|
-
hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV, 1) - 1);
|
|
5206
|
-
} else if (hDeath.mm == KISLEV && hDeath.dd == 30 && shortKislev(hDeath.yy + 1)) {
|
|
5207
|
-
// If it's Kislev 30 it depends on the first anniversary;
|
|
5208
|
-
// if that was not Kislev 30, use the day before Teveth 1.
|
|
5209
|
-
hDeath = abs2hebrew(hebrew2abs(hyear, TEVET, 1) - 1);
|
|
5210
|
-
} else if (hDeath.mm == ADAR_II) {
|
|
5211
|
-
// If it's Adar II, use the same day in last month of year (Adar or Adar II).
|
|
5212
|
-
hDeath.mm = monthsInYear(hyear);
|
|
5213
|
-
} else if (hDeath.mm == ADAR_I && hDeath.dd == 30 && !isLeapYear(hyear)) {
|
|
5214
|
-
// If it's the 30th in Adar I and year is not a leap year
|
|
5215
|
-
// (so Adar has only 29 days), use the last day in Shevat.
|
|
5216
|
-
hDeath.dd = 30;
|
|
5217
|
-
hDeath.mm = SHVAT;
|
|
5218
|
-
}
|
|
5219
|
-
// In all other cases, use the normal anniversary of the date of death.
|
|
5220
|
-
|
|
5221
|
-
// advance day to rosh chodesh if needed
|
|
5222
|
-
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hyear)) {
|
|
5223
|
-
hDeath.mm = KISLEV;
|
|
5224
|
-
hDeath.dd = 1;
|
|
5225
|
-
} else if (hDeath.mm == KISLEV && hDeath.dd == 30 && shortKislev(hyear)) {
|
|
5226
|
-
hDeath.mm = TEVET;
|
|
5227
|
-
hDeath.dd = 1;
|
|
5228
|
-
}
|
|
5229
|
-
return new HDate(hDeath.dd, hDeath.mm, hyear);
|
|
5230
|
-
}
|
|
5231
|
-
|
|
5232
|
-
/**
|
|
5233
|
-
* @private
|
|
5234
|
-
* @param {number} hyear Hebrew year
|
|
5235
|
-
* @param {Date|HDate} gdate Gregorian or Hebrew date of event
|
|
5236
|
-
* @return {HDate} anniversary occurring in `hyear`
|
|
5237
|
-
*/
|
|
5238
|
-
function getBirthdayOrAnniversary_(hyear, gdate) {
|
|
5239
|
-
const orig = HDate.isHDate(gdate) ? gdate : new HDate(gdate);
|
|
5240
|
-
const origYear = orig.getFullYear();
|
|
5241
|
-
if (hyear === origYear) {
|
|
5242
|
-
return orig;
|
|
5243
|
-
} else if (hyear < origYear) {
|
|
5244
|
-
// `Hebrew year ${hyear} occurs on or before original date in ${origYear}`
|
|
5245
|
-
return undefined;
|
|
5246
|
-
}
|
|
5247
|
-
const isOrigLeap = isLeapYear(origYear);
|
|
5248
|
-
let month = orig.getMonth();
|
|
5249
|
-
let day = orig.getDate();
|
|
5250
|
-
if (month == ADAR_I && !isOrigLeap || month == ADAR_II && isOrigLeap) {
|
|
5251
|
-
month = monthsInYear(hyear);
|
|
5252
|
-
} else if (month == CHESHVAN && day == 30 && !longCheshvan(hyear)) {
|
|
5253
|
-
month = KISLEV;
|
|
5254
|
-
day = 1;
|
|
5255
|
-
} else if (month == KISLEV && day == 30 && shortKislev(hyear)) {
|
|
5256
|
-
month = TEVET;
|
|
5257
|
-
day = 1;
|
|
5258
|
-
} else if (month == ADAR_I && day == 30 && isOrigLeap && !isLeapYear(hyear)) {
|
|
5259
|
-
month = NISAN$1;
|
|
5260
|
-
day = 1;
|
|
5261
|
-
}
|
|
5262
|
-
return new HDate(day, month, hyear);
|
|
5263
|
-
}
|
|
5264
|
-
|
|
5265
|
-
const version="4.5.1";
|
|
5950
|
+
const version="5.0.0-rc1";
|
|
5266
5951
|
|
|
5267
5952
|
const headers$1={"plural-forms":"nplurals=2; plural=(n > 1);"};const contexts$1={"":{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"],Tevet:["Teves"],"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"]}};var poAshkenazi = {headers:headers$1,contexts:contexts$1};
|
|
5268
5953
|
|
|
@@ -5339,7 +6024,7 @@ function range(start, end) {
|
|
|
5339
6024
|
}
|
|
5340
6025
|
return arr;
|
|
5341
6026
|
}
|
|
5342
|
-
const cache =
|
|
6027
|
+
const cache = new Map();
|
|
5343
6028
|
const NONE = {
|
|
5344
6029
|
shacharit: false,
|
|
5345
6030
|
mincha: false,
|
|
@@ -5366,7 +6051,11 @@ function tachanun_(hdate, il) {
|
|
|
5366
6051
|
function tachanun0(hdate, il, checkNext) {
|
|
5367
6052
|
const year = hdate.getFullYear();
|
|
5368
6053
|
const key = `${year}-${il ? 1 : 0}`;
|
|
5369
|
-
const
|
|
6054
|
+
const cached = cache.get(key);
|
|
6055
|
+
const dates = cached || tachanunYear(year, il);
|
|
6056
|
+
if (!cached) {
|
|
6057
|
+
cache.set(key, dates);
|
|
6058
|
+
}
|
|
5370
6059
|
const abs = hdate.abs();
|
|
5371
6060
|
if (dates.none.indexOf(abs) > -1) {
|
|
5372
6061
|
return NONE;
|
|
@@ -5514,7 +6203,7 @@ const MINOR_HOLIDAY = flags.MINOR_HOLIDAY;
|
|
|
5514
6203
|
const EREV = flags.EREV;
|
|
5515
6204
|
const CHOL_HAMOED = flags.CHOL_HAMOED;
|
|
5516
6205
|
const YOM_KIPPUR_KATAN = flags.YOM_KIPPUR_KATAN;
|
|
5517
|
-
const unrecognizedAlreadyWarned =
|
|
6206
|
+
const unrecognizedAlreadyWarned = new Set();
|
|
5518
6207
|
const RECOGNIZED_OPTIONS = {
|
|
5519
6208
|
location: 1,
|
|
5520
6209
|
year: 1,
|
|
@@ -5556,9 +6245,9 @@ const RECOGNIZED_OPTIONS = {
|
|
|
5556
6245
|
*/
|
|
5557
6246
|
function warnUnrecognizedOptions(options) {
|
|
5558
6247
|
Object.keys(options).forEach(k => {
|
|
5559
|
-
if (typeof RECOGNIZED_OPTIONS[k] === 'undefined' && !unrecognizedAlreadyWarned
|
|
6248
|
+
if (typeof RECOGNIZED_OPTIONS[k] === 'undefined' && !unrecognizedAlreadyWarned.has(k)) {
|
|
5560
6249
|
console.warn(`Ignoring unrecognized HebrewCalendar option: ${k}`);
|
|
5561
|
-
unrecognizedAlreadyWarned
|
|
6250
|
+
unrecognizedAlreadyWarned.add(k);
|
|
5562
6251
|
}
|
|
5563
6252
|
});
|
|
5564
6253
|
}
|
|
@@ -5723,7 +6412,7 @@ function checkCandleOptions(options) {
|
|
|
5723
6412
|
*/
|
|
5724
6413
|
function getAbs(d) {
|
|
5725
6414
|
if (typeof d == 'number') return d;
|
|
5726
|
-
if (isDate(d)) return greg2abs(d);
|
|
6415
|
+
if (greg.isDate(d)) return greg.greg2abs(d);
|
|
5727
6416
|
if (HDate.isHDate(d)) return d.abs();
|
|
5728
6417
|
throw new TypeError(`Invalid date type: ${d}`);
|
|
5729
6418
|
}
|
|
@@ -5773,17 +6462,17 @@ function getStartAndEnd(options) {
|
|
|
5773
6462
|
if (theYear < 100) {
|
|
5774
6463
|
startGreg.setFullYear(theYear);
|
|
5775
6464
|
}
|
|
5776
|
-
const startAbs = greg2abs(startGreg);
|
|
6465
|
+
const startAbs = greg.greg2abs(startGreg);
|
|
5777
6466
|
let endAbs;
|
|
5778
6467
|
if (options.month) {
|
|
5779
|
-
endAbs = startAbs + daysInMonth
|
|
6468
|
+
endAbs = startAbs + greg.daysInMonth(theMonth, theYear) - 1;
|
|
5780
6469
|
} else {
|
|
5781
6470
|
const endYear = theYear + numYears;
|
|
5782
6471
|
const endGreg = new Date(endYear, 0, 1);
|
|
5783
6472
|
if (endYear < 100) {
|
|
5784
6473
|
endGreg.setFullYear(endYear);
|
|
5785
6474
|
}
|
|
5786
|
-
endAbs = greg2abs(endGreg) - 1;
|
|
6475
|
+
endAbs = greg.greg2abs(endGreg) - 1;
|
|
5787
6476
|
}
|
|
5788
6477
|
return [startAbs, endAbs];
|
|
5789
6478
|
}
|
|
@@ -5927,7 +6616,7 @@ function observedInIsrael(ev) {
|
|
|
5927
6616
|
function observedInDiaspora(ev) {
|
|
5928
6617
|
return ev.observedInDiaspora();
|
|
5929
6618
|
}
|
|
5930
|
-
const yearArrayCache =
|
|
6619
|
+
const yearArrayCache = new Map();
|
|
5931
6620
|
|
|
5932
6621
|
/**
|
|
5933
6622
|
* HebrewCalendar is the main interface to the `@hebcal/core` library.
|
|
@@ -6072,7 +6761,7 @@ class HebrewCalendar {
|
|
|
6072
6761
|
warnUnrecognizedOptions(options);
|
|
6073
6762
|
const startAbs = startAndEnd[0];
|
|
6074
6763
|
const endAbs = startAndEnd[1];
|
|
6075
|
-
const startGreg = abs2greg(startAbs);
|
|
6764
|
+
const startGreg = greg.abs2greg(startAbs);
|
|
6076
6765
|
if (startGreg.getFullYear() < 100) {
|
|
6077
6766
|
options.candlelighting = false;
|
|
6078
6767
|
}
|
|
@@ -6120,7 +6809,7 @@ class HebrewCalendar {
|
|
|
6120
6809
|
const omer = abs - beginOmer + 1;
|
|
6121
6810
|
const omerEv = new OmerEvent(hd, omer);
|
|
6122
6811
|
if (options.candlelighting) {
|
|
6123
|
-
const zmanim = new Zmanim(
|
|
6812
|
+
const zmanim = new Zmanim(location, hd.prev());
|
|
6124
6813
|
const tzeit = zmanim.tzeit(7.0833);
|
|
6125
6814
|
if (!isNaN(tzeit.getTime())) {
|
|
6126
6815
|
omerEv.alarm = tzeit;
|
|
@@ -6185,7 +6874,8 @@ class HebrewCalendar {
|
|
|
6185
6874
|
* @return {HDate} anniversary occurring in `hyear`
|
|
6186
6875
|
*/
|
|
6187
6876
|
static getBirthdayOrAnniversary(hyear, gdate) {
|
|
6188
|
-
|
|
6877
|
+
const dt = getBirthdayOrAnniversary(hyear, gdate);
|
|
6878
|
+
return new HDate(dt);
|
|
6189
6879
|
}
|
|
6190
6880
|
|
|
6191
6881
|
/**
|
|
@@ -6223,7 +6913,8 @@ class HebrewCalendar {
|
|
|
6223
6913
|
* @return {HDate} anniversary occurring in hyear
|
|
6224
6914
|
*/
|
|
6225
6915
|
static getYahrzeit(hyear, gdate) {
|
|
6226
|
-
|
|
6916
|
+
const dt = getYahrzeit(hyear, gdate);
|
|
6917
|
+
return new HDate(dt);
|
|
6227
6918
|
}
|
|
6228
6919
|
|
|
6229
6920
|
/**
|
|
@@ -6246,7 +6937,7 @@ class HebrewCalendar {
|
|
|
6246
6937
|
*/
|
|
6247
6938
|
static getHolidaysForYearArray(year, il) {
|
|
6248
6939
|
const cacheKey = `${year}-${il ? 1 : 0}`;
|
|
6249
|
-
let events = yearArrayCache
|
|
6940
|
+
let events = yearArrayCache.get(cacheKey);
|
|
6250
6941
|
if (events) {
|
|
6251
6942
|
return events;
|
|
6252
6943
|
}
|
|
@@ -6263,7 +6954,7 @@ class HebrewCalendar {
|
|
|
6263
6954
|
events = events.concat(filtered);
|
|
6264
6955
|
}
|
|
6265
6956
|
}
|
|
6266
|
-
yearArrayCache
|
|
6957
|
+
yearArrayCache.set(cacheKey, events);
|
|
6267
6958
|
return events;
|
|
6268
6959
|
}
|
|
6269
6960
|
|
|
@@ -6449,6 +7140,7 @@ exports.AsaraBTevetEvent = AsaraBTevetEvent;
|
|
|
6449
7140
|
exports.CandleLightingEvent = CandleLightingEvent;
|
|
6450
7141
|
exports.DailyLearning = DailyLearning;
|
|
6451
7142
|
exports.Event = Event;
|
|
7143
|
+
exports.GeoLocation = GeoLocation;
|
|
6452
7144
|
exports.HDate = HDate;
|
|
6453
7145
|
exports.HavdalahEvent = HavdalahEvent;
|
|
6454
7146
|
exports.HebrewCalendar = HebrewCalendar;
|
|
@@ -6459,18 +7151,17 @@ exports.Location = Location;
|
|
|
6459
7151
|
exports.MevarchimChodeshEvent = MevarchimChodeshEvent;
|
|
6460
7152
|
exports.Molad = Molad;
|
|
6461
7153
|
exports.MoladEvent = MoladEvent;
|
|
7154
|
+
exports.NOAACalculator = NOAACalculator;
|
|
6462
7155
|
exports.OmerEvent = OmerEvent;
|
|
6463
7156
|
exports.ParshaEvent = ParshaEvent;
|
|
6464
7157
|
exports.RoshChodeshEvent = RoshChodeshEvent;
|
|
6465
7158
|
exports.RoshHashanaEvent = RoshHashanaEvent;
|
|
6466
7159
|
exports.Sedra = Sedra;
|
|
6467
|
-
exports.SolarCalc = SolarCalc;
|
|
6468
7160
|
exports.TimedEvent = TimedEvent;
|
|
6469
7161
|
exports.Zmanim = Zmanim;
|
|
6470
7162
|
exports.flags = flags;
|
|
6471
7163
|
exports.gematriya = gematriya;
|
|
6472
7164
|
exports.gematriyaStrToNum = gematriyaStrToNum;
|
|
6473
|
-
exports.greg = greg;
|
|
6474
7165
|
exports.months = months;
|
|
6475
7166
|
exports.parshiot = parshiot;
|
|
6476
7167
|
exports.version = version;
|