@hebcal/core 4.5.1 → 5.0.0-rc1

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