@hebcal/core 4.5.1 → 5.0.0-rc2

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