@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.
@@ -1,1864 +0,0 @@
1
- /*! @hebcal/core v4.5.1 */
2
- var hebcal = (function (exports) {
3
- 'use strict';
4
-
5
- const GERESH = '׳';
6
- const GERSHAYIM = '״';
7
- const heb2num = {
8
- 'א': 1,
9
- 'ב': 2,
10
- 'ג': 3,
11
- 'ד': 4,
12
- 'ה': 5,
13
- 'ו': 6,
14
- 'ז': 7,
15
- 'ח': 8,
16
- 'ט': 9,
17
- 'י': 10,
18
- 'כ': 20,
19
- 'ל': 30,
20
- 'מ': 40,
21
- 'נ': 50,
22
- 'ס': 60,
23
- 'ע': 70,
24
- 'פ': 80,
25
- 'צ': 90,
26
- 'ק': 100,
27
- 'ר': 200,
28
- 'ש': 300,
29
- 'ת': 400
30
- };
31
- const num2heb = {};
32
- Object.keys(heb2num).forEach(key => {
33
- const val = heb2num[key];
34
- num2heb[val] = key;
35
- });
36
-
37
- /**
38
- * @private
39
- * @param {number} num
40
- * @return {number[]}
41
- */
42
- function num2digits(num) {
43
- const digits = [];
44
- while (num > 0) {
45
- if (num === 15 || num === 16) {
46
- digits.push(9);
47
- digits.push(num - 9);
48
- break;
49
- }
50
- let incr = 100;
51
- let i;
52
- for (i = 400; i > num; i -= incr) {
53
- if (i === incr) {
54
- incr = incr / 10;
55
- }
56
- }
57
- digits.push(i);
58
- num -= i;
59
- }
60
- return digits;
61
- }
62
-
63
- /**
64
- * Converts a numerical value to a string of Hebrew letters.
65
- *
66
- * When specifying years of the Hebrew calendar in the present millennium,
67
- * we omit the thousands (which is presently 5 [ה]).
68
- * @example
69
- * gematriya(5774) // 'תשע״ד' - cropped to 774
70
- * gematriya(25) // 'כ״ה'
71
- * gematriya(60) // 'ס׳'
72
- * gematriya(3761) // 'ג׳תשס״א'
73
- * gematriya(1123) // 'א׳קכ״ג'
74
- * @param {number} number
75
- * @return {string}
76
- */
77
- function gematriya(number) {
78
- const num = parseInt(number, 10);
79
- if (!num) {
80
- throw new TypeError(`invalid parameter to gematriya ${number}`);
81
- }
82
- let str = '';
83
- const thousands = Math.floor(num / 1000);
84
- if (thousands > 0 && thousands !== 5) {
85
- const tdigits = num2digits(thousands);
86
- for (const tdig of tdigits) {
87
- str += num2heb[tdig];
88
- }
89
- str += GERESH;
90
- }
91
- const digits = num2digits(num % 1000);
92
- if (digits.length == 1) {
93
- return str + num2heb[digits[0]] + GERESH;
94
- }
95
- for (let i = 0; i < digits.length; i++) {
96
- if (i + 1 === digits.length) {
97
- str += GERSHAYIM;
98
- }
99
- str += num2heb[digits[i]];
100
- }
101
- return str;
102
- }
103
-
104
- /**
105
- * Converts a string of Hebrew letters to a numerical value.
106
- *
107
- * Only considers the value of Hebrew letters `א` through `ת`.
108
- * Ignores final Hebrew letters such as `ך` (kaf sofit) or `ם` (mem sofit)
109
- * and vowels (nekudot).
110
- *
111
- * @param {string} str
112
- * @return {number}
113
- */
114
- function gematriyaStrToNum(str) {
115
- let num = 0;
116
- const gereshIdx = str.indexOf(GERESH);
117
- if (gereshIdx !== -1 && gereshIdx !== str.length - 1) {
118
- const thousands = str.substring(0, gereshIdx);
119
- num += gematriyaStrToNum(thousands) * 1000;
120
- str = str.substring(gereshIdx);
121
- }
122
- for (const ch of str) {
123
- const n = heb2num[ch];
124
- if (typeof n === 'number') {
125
- num += n;
126
- }
127
- }
128
- return num;
129
- }
130
-
131
- /*
132
- * More minimal greg routines
133
- */
134
-
135
- /** @private */
136
- const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
137
- /** @private */
138
- const monthLengths = [lengths, lengths.slice()];
139
- monthLengths[1][2] = 29;
140
-
141
- /**
142
- * @private
143
- * @param {number} x
144
- * @param {number} y
145
- * @return {number}
146
- */
147
- function mod(x, y) {
148
- return x - y * Math.floor(x / y);
149
- }
150
-
151
- /**
152
- * @private
153
- * @param {number} x
154
- * @param {number} y
155
- * @return {number}
156
- */
157
- function quotient(x, y) {
158
- return Math.floor(x / y);
159
- }
160
-
161
- /**
162
- * Returns true if the Gregorian year is a leap year
163
- * @private
164
- * @param {number} year Gregorian year
165
- * @return {boolean}
166
- */
167
- function isLeapYear$1(year) {
168
- return !(year % 4) && (!!(year % 100) || !(year % 400));
169
- }
170
-
171
- /**
172
- * Number of days in the Gregorian month for given year
173
- * @private
174
- * @param {number} month Gregorian month (1=January, 12=December)
175
- * @param {number} year Gregorian year
176
- * @return {number}
177
- */
178
- function daysInMonth$1(month, year) {
179
- // 1 based months
180
- return monthLengths[+isLeapYear$1(year)][month];
181
- }
182
-
183
- /**
184
- * Returns true if the object is a Javascript Date
185
- * @private
186
- * @param {Object} obj
187
- * @return {boolean}
188
- */
189
- function isDate(obj) {
190
- return typeof obj === 'object' && Date.prototype === obj.__proto__;
191
- }
192
-
193
- /*
194
- const ABS_14SEP1752 = 639797;
195
- const ABS_2SEP1752 = 639785;
196
- */
197
-
198
- /**
199
- * Converts Gregorian date to absolute R.D. (Rata Die) days
200
- * @private
201
- * @param {Date} date Gregorian date
202
- * @return {number}
203
- */
204
- function greg2abs(date) {
205
- if (!isDate(date)) {
206
- throw new TypeError(`Argument not a Date: ${date}`);
207
- }
208
- const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
209
- /*
210
- if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
211
- throw new RangeError(`Invalid Date: ${date}`);
212
- }
213
- */
214
- return abs;
215
- }
216
-
217
- /**
218
- * @private
219
- * @param {number} abs - R.D. number of days
220
- * @return {number}
221
- */
222
- function yearFromFixed(abs) {
223
- const l0 = abs - 1;
224
- const n400 = quotient(l0, 146097);
225
- const d1 = mod(l0, 146097);
226
- const n100 = quotient(d1, 36524);
227
- const d2 = mod(d1, 36524);
228
- const n4 = quotient(d2, 1461);
229
- const d3 = mod(d2, 1461);
230
- const n1 = quotient(d3, 365);
231
- const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
232
- return n100 != 4 && n1 != 4 ? year + 1 : year;
233
- }
234
-
235
- /**
236
- * @private
237
- * @param {number} year
238
- * @param {number} month (1-12)
239
- * @param {number} day (1-31)
240
- * @return {number}
241
- */
242
- function toFixed(year, month, day) {
243
- const py = year - 1;
244
- 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;
245
- }
246
-
247
- /**
248
- * Converts from Rata Die (R.D. number) to Gregorian date.
249
- * See the footnote on page 384 of ``Calendrical Calculations, Part II:
250
- * Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
251
- * Clamen, Software--Practice and Experience, Volume 23, Number 4
252
- * (April, 1993), pages 383-404 for an explanation.
253
- * @private
254
- * @param {number} abs - R.D. number of days
255
- * @return {Date}
256
- */
257
- function abs2greg(abs) {
258
- if (typeof abs !== 'number') {
259
- throw new TypeError(`Argument not a Number: ${abs}`);
260
- }
261
- abs = Math.trunc(abs);
262
- /*
263
- if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
264
- throw new RangeError(`Invalid Date: ${abs}`);
265
- }
266
- */
267
- const year = yearFromFixed(abs);
268
- const priorDays = abs - toFixed(year, 1, 1);
269
- const correction = abs < toFixed(year, 3, 1) ? 0 : isLeapYear$1(year) ? 1 : 2;
270
- const month = quotient(12 * (priorDays + correction) + 373, 367);
271
- const day = abs - toFixed(year, month, 1) + 1;
272
- const dt = new Date(year, month - 1, day);
273
- if (year < 100 && year >= 0) {
274
- dt.setFullYear(year);
275
- }
276
- return dt;
277
- }
278
-
279
- /*
280
- Hebcal - A Jewish Calendar Generator
281
- Copyright (c) 1994-2020 Danny Sadinoff
282
- Portions copyright Eyal Schachter and Michael J. Radwin
283
-
284
- https://github.com/hebcal/hebcal-es6
285
-
286
- This program is free software; you can redistribute it and/or
287
- modify it under the terms of the GNU General Public License
288
- as published by the Free Software Foundation; either version 2
289
- of the License, or (at your option) any later version.
290
-
291
- This program is distributed in the hope that it will be useful,
292
- but WITHOUT ANY WARRANTY; without even the implied warranty of
293
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
294
- GNU General Public License for more details.
295
-
296
- You should have received a copy of the GNU General Public License
297
- along with this program. If not, see <http://www.gnu.org/licenses/>.
298
- */
299
-
300
-
301
- /**
302
- * Gregorian date helper functions.
303
- */
304
- const greg = {
305
- /**
306
- * Long names of the Gregorian months (1='January', 12='December')
307
- * @readonly
308
- * @type {string[]}
309
- */
310
- monthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
311
- /**
312
- * Returns true if the Gregorian year is a leap year
313
- * @function
314
- * @param {number} year Gregorian year
315
- * @return {boolean}
316
- */
317
- isLeapYear: isLeapYear$1,
318
- /**
319
- * Number of days in the Gregorian month for given year
320
- * @function
321
- * @param {number} month Gregorian month (1=January, 12=December)
322
- * @param {number} year Gregorian year
323
- * @return {number}
324
- */
325
- daysInMonth: daysInMonth$1,
326
- /**
327
- * Returns true if the object is a Javascript Date
328
- * @function
329
- * @param {Object} obj
330
- * @return {boolean}
331
- */
332
- isDate: isDate,
333
- /**
334
- * Returns number of days since January 1 of that year
335
- * @deprecated
336
- * @param {Date} date Gregorian date
337
- * @return {number}
338
- */
339
- dayOfYear: function (date) {
340
- if (!isDate(date)) {
341
- throw new TypeError(`Argument not a Date: ${date}`);
342
- }
343
- const month = date.getMonth();
344
- let doy = date.getDate() + 31 * month;
345
- if (month > 1) {
346
- // FEB
347
- doy -= Math.floor((4 * (month + 1) + 23) / 10);
348
- if (isLeapYear$1(date.getFullYear())) {
349
- doy++;
350
- }
351
- }
352
- return doy;
353
- },
354
- /**
355
- * Converts Gregorian date to absolute R.D. (Rata Die) days
356
- * @function
357
- * @param {Date} date Gregorian date
358
- * @return {number}
359
- */
360
- greg2abs: greg2abs,
361
- /**
362
- * Converts from Rata Die (R.D. number) to Gregorian date.
363
- * See the footnote on page 384 of ``Calendrical Calculations, Part II:
364
- * Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
365
- * Clamen, Software--Practice and Experience, Volume 23, Number 4
366
- * (April, 1993), pages 383-404 for an explanation.
367
- * @function
368
- * @param {number} theDate - R.D. number of days
369
- * @return {Date}
370
- */
371
- abs2greg: abs2greg
372
- };
373
-
374
- const noopLocale = {
375
- headers: {
376
- 'plural-forms': 'nplurals=2; plural=(n!=1);'
377
- },
378
- contexts: {
379
- '': {}
380
- }
381
- };
382
- const alias = {
383
- 'h': 'he',
384
- 'a': 'ashkenazi',
385
- 's': 'en',
386
- '': 'en'
387
- };
388
-
389
- /** @private */
390
- const locales = Object.create(null);
391
- /** @private */
392
- let activeLocale = null;
393
- /** @private */
394
- let activeName = null;
395
-
396
- /**
397
- * A locale in Hebcal is used for translations/transliterations of
398
- * holidays. `@hebcal/core` supports four locales by default
399
- * * `en` - default, Sephardic transliterations (e.g. "Shabbat")
400
- * * `ashkenazi` - Ashkenazi transliterations (e.g. "Shabbos")
401
- * * `he` - Hebrew (e.g. "שַׁבָּת")
402
- * * `he-x-NoNikud` - Hebrew without nikud (e.g. "שבת")
403
- */
404
- class Locale {
405
- /**
406
- * Returns translation only if `locale` offers a non-empty translation for `id`.
407
- * Otherwise, returns `undefined`.
408
- * @param {string} id Message ID to translate
409
- * @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
410
- * @return {string}
411
- */
412
- static lookupTranslation(id, locale) {
413
- const locale0 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
414
- const loc = typeof locale == 'string' && locales[locale0] || activeLocale;
415
- const array = loc[id];
416
- if (array && array.length && array[0].length) {
417
- return array[0];
418
- }
419
- return undefined;
420
- }
421
-
422
- /**
423
- * By default, if no translation was found, returns `id`.
424
- * @param {string} id Message ID to translate
425
- * @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
426
- * @return {string}
427
- */
428
- static gettext(id, locale) {
429
- const text = this.lookupTranslation(id, locale);
430
- if (typeof text == 'undefined') {
431
- return id;
432
- }
433
- return text;
434
- }
435
-
436
- /**
437
- * Register locale translations.
438
- * @param {string} locale Locale name (i.e.: `'he'`, `'fr'`)
439
- * @param {LocaleData} data parsed data from a `.po` file.
440
- */
441
- static addLocale(locale, data) {
442
- if (typeof locale !== 'string') {
443
- throw new TypeError(`Invalid locale name: ${locale}`);
444
- }
445
- if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
446
- throw new TypeError(`Locale '${locale}' invalid compact format`);
447
- }
448
- locales[locale.toLowerCase()] = data.contexts[''];
449
- }
450
-
451
- /**
452
- * Adds a translation to `locale`, replacing any previous translation.
453
- * @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
454
- * @param {string} id Message ID to translate
455
- * @param {string} translation Translation text
456
- */
457
- static addTranslation(locale, id, translation) {
458
- if (typeof locale !== 'string') {
459
- throw new TypeError(`Invalid locale name: ${locale}`);
460
- }
461
- const locale0 = locale.toLowerCase();
462
- const loc = locales[locale0];
463
- if (!loc) {
464
- throw new TypeError(`Unknown locale: ${locale}`);
465
- }
466
- if (typeof id !== 'string' || id.length === 0) {
467
- throw new TypeError(`Invalid id: ${id}`);
468
- }
469
- const isArray = Array.isArray(translation);
470
- if (isArray) {
471
- const t0 = translation[0];
472
- if (typeof t0 !== 'string' || t0.length === 0) {
473
- throw new TypeError(`Invalid translation array: ${translation}`);
474
- }
475
- } else if (typeof translation !== 'string') {
476
- throw new TypeError(`Invalid translation: ${translation}`);
477
- }
478
- loc[id] = isArray ? translation : [translation];
479
- }
480
- /**
481
- * Adds multiple translations to `locale`, replacing any previous translations.
482
- * @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
483
- * @param {LocaleData} data parsed data from a `.po` file.
484
- */
485
- static addTranslations(locale, data) {
486
- if (typeof locale !== 'string') {
487
- throw new TypeError(`Invalid locale name: ${locale}`);
488
- }
489
- const locale0 = locale.toLowerCase();
490
- const loc = locales[locale0];
491
- if (!loc) {
492
- throw new TypeError(`Unknown locale: ${locale}`);
493
- }
494
- if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
495
- throw new TypeError(`Locale '${locale}' invalid compact format`);
496
- }
497
- const ctx = data.contexts[''];
498
- Object.keys(ctx).forEach(id => {
499
- loc[id] = ctx[id];
500
- });
501
- }
502
- /**
503
- * Activates a locale. Throws an error if the locale has not been previously added.
504
- * After setting the locale to be used, all strings marked for translations
505
- * will be represented by the corresponding translation in the specified locale.
506
- * @param {string} locale Locale name (i.e: `'he'`, `'fr'`)
507
- * @return {LocaleData}
508
- */
509
- static useLocale(locale) {
510
- const locale0 = locale.toLowerCase();
511
- const obj = locales[locale0];
512
- if (!obj) {
513
- throw new RangeError(`Locale '${locale}' not found`);
514
- }
515
- activeName = alias[locale0] || locale0;
516
- activeLocale = obj;
517
- return activeLocale;
518
- }
519
-
520
- /**
521
- * Returns the name of the active locale (i.e. 'he', 'ashkenazi', 'fr')
522
- * @return {string}
523
- */
524
- static getLocaleName() {
525
- return activeName;
526
- }
527
-
528
- /**
529
- * Returns the names of registered locales
530
- * @return {string[]}
531
- */
532
- static getLocaleNames() {
533
- return Object.keys(locales).sort((a, b) => a.localeCompare(b));
534
- }
535
-
536
- /**
537
- * @param {number} n
538
- * @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
539
- * @return {string}
540
- */
541
- static ordinal(n, locale) {
542
- const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
543
- const locale0 = locale1 || activeName;
544
- if (!locale0) {
545
- return this.getEnOrdinal(n);
546
- }
547
- switch (locale0) {
548
- case 'en':
549
- case 's':
550
- case 'a':
551
- case 'ashkenazi':
552
- case 'ashkenazi_litvish':
553
- case 'ashkenazi_poylish':
554
- case 'ashkenazi_standard':
555
- return this.getEnOrdinal(n);
556
- case 'es':
557
- return n + 'º';
558
- case 'h':
559
- case 'he':
560
- case 'he-x-nonikud':
561
- return String(n);
562
- default:
563
- return n + '.';
564
- }
565
- }
566
-
567
- /**
568
- * @private
569
- * @param {number} n
570
- * @return {string}
571
- */
572
- static getEnOrdinal(n) {
573
- const s = ['th', 'st', 'nd', 'rd'];
574
- const v = n % 100;
575
- return n + (s[(v - 20) % 10] || s[v] || s[0]);
576
- }
577
-
578
- /**
579
- * Removes nekudot from Hebrew string
580
- * @param {string} str
581
- * @return {string}
582
- */
583
- static hebrewStripNikkud(str) {
584
- return str.replace(/[\u0590-\u05bd]/g, '').replace(/[\u05bf-\u05c7]/g, '');
585
- }
586
- }
587
- Locale.addLocale('en', noopLocale);
588
- Locale.addLocale('s', noopLocale);
589
- Locale.addLocale('', noopLocale);
590
- Locale.useLocale('en');
591
-
592
- /*
593
- * More minimal HDate
594
- */
595
-
596
- const NISAN$1 = 1;
597
- const IYYAR = 2;
598
- // const SIVAN = 3;
599
- const TAMUZ = 4;
600
- // const AV = 5;
601
- const ELUL = 6;
602
- const TISHREI = 7;
603
- const CHESHVAN$1 = 8;
604
- const KISLEV$1 = 9;
605
- const TEVET$1 = 10;
606
- // const SHVAT = 11;
607
- const ADAR_I$1 = 12;
608
- const ADAR_II$1 = 13;
609
-
610
- /**
611
- * Hebrew months of the year (NISAN=1, TISHREI=7)
612
- * @readonly
613
- * @enum {number}
614
- */
615
- const months = {
616
- /** Nissan / ניסן */
617
- NISAN: 1,
618
- /** Iyyar / אייר */
619
- IYYAR: 2,
620
- /** Sivan / סיון */
621
- SIVAN: 3,
622
- /** Tamuz (sometimes Tammuz) / תמוז */
623
- TAMUZ: 4,
624
- /** Av / אב */
625
- AV: 5,
626
- /** Elul / אלול */
627
- ELUL: 6,
628
- /** Tishrei / תִּשְׁרֵי */
629
- TISHREI: 7,
630
- /** Cheshvan / חשון */
631
- CHESHVAN: 8,
632
- /** Kislev / כסלו */
633
- KISLEV: 9,
634
- /** Tevet / טבת */
635
- TEVET: 10,
636
- /** Sh'vat / שבט */
637
- SHVAT: 11,
638
- /** Adar or Adar Rishon / אדר */
639
- ADAR_I: 12,
640
- /** Adar Sheini (only on leap years) / אדר ב׳ */
641
- ADAR_II: 13
642
- };
643
- const monthNames0 = ['', 'Nisan', 'Iyyar', 'Sivan', 'Tamuz', 'Av', 'Elul', 'Tishrei', 'Cheshvan', 'Kislev', 'Tevet', 'Sh\'vat'];
644
-
645
- /**
646
- * Transliterations of Hebrew month names.
647
- * Regular years are index 0 and leap years are index 1.
648
- * @private
649
- */
650
- const monthNames = [monthNames0.concat(['Adar', 'Nisan']), monthNames0.concat(['Adar I', 'Adar II', 'Nisan'])];
651
- const edCache = Object.create(null);
652
- const EPOCH = -1373428;
653
- // Avg year length in the cycle (19 solar years with 235 lunar months)
654
- const AVG_HEBYEAR_DAYS = 365.24682220597794;
655
-
656
- /**
657
- * @private
658
- * @param {any} n
659
- * @param {string} name
660
- */
661
- function assertNumber(n, name) {
662
- if (typeof n !== 'number' || isNaN(n)) {
663
- throw new TypeError(`invalid parameter '${name}' not a number: ${n}`);
664
- }
665
- }
666
-
667
- /**
668
- * Converts Hebrew date to R.D. (Rata Die) fixed days.
669
- * R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian
670
- * Calendar.
671
- * @private
672
- * @param {number} year Hebrew year
673
- * @param {number} month Hebrew month
674
- * @param {number} day Hebrew date (1-30)
675
- * @return {number}
676
- */
677
- function hebrew2abs(year, month, day) {
678
- assertNumber(year, 'year');
679
- assertNumber(month, 'month');
680
- assertNumber(day, 'day');
681
- if (year < 1) {
682
- throw new RangeError(`hebrew2abs: invalid year ${year}`);
683
- }
684
- let tempabs = day;
685
- if (month < TISHREI) {
686
- for (let m = TISHREI; m <= monthsInYear(year); m++) {
687
- tempabs += daysInMonth(m, year);
688
- }
689
- for (let m = NISAN$1; m < month; m++) {
690
- tempabs += daysInMonth(m, year);
691
- }
692
- } else {
693
- for (let m = TISHREI; m < month; m++) {
694
- tempabs += daysInMonth(m, year);
695
- }
696
- }
697
- return EPOCH + elapsedDays(year) + tempabs - 1;
698
- }
699
-
700
- /**
701
- * @private
702
- * @param {number} year
703
- * @return {number}
704
- */
705
- function newYear(year) {
706
- return EPOCH + elapsedDays(year);
707
- }
708
-
709
- /**
710
- * Converts absolute R.D. days to Hebrew date
711
- * @private
712
- * @param {number} abs absolute R.D. days
713
- * @return {SimpleHebrewDate}
714
- */
715
- function abs2hebrew(abs) {
716
- assertNumber(abs, 'abs');
717
- abs = Math.trunc(abs);
718
- if (abs <= EPOCH) {
719
- throw new RangeError(`abs2hebrew: ${abs} is before epoch`);
720
- }
721
- // first, quickly approximate year
722
- let year = Math.floor((abs - EPOCH) / AVG_HEBYEAR_DAYS);
723
- while (newYear(year) <= abs) {
724
- ++year;
725
- }
726
- --year;
727
- let month = abs < hebrew2abs(year, 1, 1) ? 7 : 1;
728
- while (abs > hebrew2abs(year, month, daysInMonth(month, year))) {
729
- ++month;
730
- }
731
- const day = 1 + abs - hebrew2abs(year, month, 1);
732
- return {
733
- yy: year,
734
- mm: month,
735
- dd: day
736
- };
737
- }
738
-
739
- /**
740
- * Returns true if Hebrew year is a leap year
741
- * @private
742
- * @param {number} year Hebrew year
743
- * @return {boolean}
744
- */
745
- function isLeapYear(year) {
746
- return (1 + year * 7) % 19 < 7;
747
- }
748
-
749
- /**
750
- * Number of months in this Hebrew year (either 12 or 13 depending on leap year)
751
- * @private
752
- * @param {number} year Hebrew year
753
- * @return {number}
754
- */
755
- function monthsInYear(year) {
756
- return 12 + isLeapYear(year); // boolean is cast to 1 or 0
757
- }
758
-
759
- /**
760
- * Number of days in Hebrew month in a given year (29 or 30)
761
- * @private
762
- * @param {number} month Hebrew month (e.g. months.TISHREI)
763
- * @param {number} year Hebrew year
764
- * @return {number}
765
- */
766
- function daysInMonth(month, year) {
767
- switch (month) {
768
- case IYYAR:
769
- case TAMUZ:
770
- case ELUL:
771
- case TEVET$1:
772
- case ADAR_II$1:
773
- return 29;
774
- }
775
- if (month === ADAR_I$1 && !isLeapYear(year) || month === CHESHVAN$1 && !longCheshvan(year) || month === KISLEV$1 && shortKislev(year)) {
776
- return 29;
777
- } else {
778
- return 30;
779
- }
780
- }
781
-
782
- /**
783
- * Returns a transliterated string name of Hebrew month in year,
784
- * for example 'Elul' or 'Cheshvan'.
785
- * @private
786
- * @param {number} month Hebrew month (e.g. months.TISHREI)
787
- * @param {number} year Hebrew year
788
- * @return {string}
789
- */
790
- function getMonthName(month, year) {
791
- assertNumber(month, 'month');
792
- assertNumber(year, 'year');
793
- if (month < 1 || month > 14) {
794
- throw new TypeError(`bad month argument ${month}`);
795
- }
796
- return monthNames[+isLeapYear(year)][month];
797
- }
798
-
799
- /**
800
- * Days from sunday prior to start of Hebrew calendar to mean
801
- * conjunction of Tishrei in Hebrew YEAR
802
- * @private
803
- * @param {number} year Hebrew year
804
- * @return {number}
805
- */
806
- function elapsedDays(year) {
807
- const elapsed = edCache[year] = edCache[year] || elapsedDays0(year);
808
- return elapsed;
809
- }
810
-
811
- /**
812
- * Days from sunday prior to start of Hebrew calendar to mean
813
- * conjunction of Tishrei in Hebrew YEAR
814
- * @private
815
- * @param {number} year Hebrew year
816
- * @return {number}
817
- */
818
- function elapsedDays0(year) {
819
- const prevYear = year - 1;
820
- const mElapsed = 235 * Math.floor(prevYear / 19) +
821
- // Months in complete 19 year lunar (Metonic) cycles so far
822
- 12 * (prevYear % 19) +
823
- // Regular months in this cycle
824
- Math.floor((prevYear % 19 * 7 + 1) / 19); // Leap months this cycle
825
-
826
- const pElapsed = 204 + 793 * (mElapsed % 1080);
827
- const hElapsed = 5 + 12 * mElapsed + 793 * Math.floor(mElapsed / 1080) + Math.floor(pElapsed / 1080);
828
- const parts = pElapsed % 1080 + 1080 * (hElapsed % 24);
829
- const day = 1 + 29 * mElapsed + Math.floor(hElapsed / 24);
830
- const altDay = day + (parts >= 19440 || 2 === day % 7 && parts >= 9924 && !isLeapYear(year) || 1 === day % 7 && parts >= 16789 && isLeapYear(prevYear));
831
- return altDay + (altDay % 7 === 0 || altDay % 7 === 3 || altDay % 7 === 5);
832
- }
833
-
834
- /**
835
- * Number of days in the hebrew YEAR.
836
- * A common Hebrew calendar year can have a length of 353, 354 or 355 days
837
- * A leap Hebrew calendar year can have a length of 383, 384 or 385 days
838
- * @private
839
- * @param {number} year Hebrew year
840
- * @return {number}
841
- */
842
- function daysInYear(year) {
843
- return elapsedDays(year + 1) - elapsedDays(year);
844
- }
845
-
846
- /**
847
- * true if Cheshvan is long in Hebrew year
848
- * @private
849
- * @param {number} year Hebrew year
850
- * @return {boolean}
851
- */
852
- function longCheshvan(year) {
853
- return daysInYear(year) % 10 === 5;
854
- }
855
-
856
- /**
857
- * true if Kislev is short in Hebrew year
858
- * @private
859
- * @param {number} year Hebrew year
860
- * @return {boolean}
861
- */
862
- function shortKislev(year) {
863
- return daysInYear(year) % 10 === 3;
864
- }
865
-
866
- /**
867
- * @private
868
- * @param {string} msg
869
- */
870
- function throwTypeError(msg) {
871
- throw new TypeError(msg);
872
- }
873
-
874
- /*
875
- Hebcal - A Jewish Calendar Generator
876
- Copyright (c) 1994-2020 Danny Sadinoff
877
- Portions copyright Eyal Schachter and Michael J. Radwin
878
-
879
- https://github.com/hebcal/hebcal-es6
880
-
881
- This program is free software; you can redistribute it and/or
882
- modify it under the terms of the GNU General Public License
883
- as published by the Free Software Foundation; either version 2
884
- of the License, or (at your option) any later version.
885
-
886
- This program is distributed in the hope that it will be useful,
887
- but WITHOUT ANY WARRANTY; without even the implied warranty of
888
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
889
- GNU General Public License for more details.
890
-
891
- You should have received a copy of the GNU General Public License
892
- along with this program. If not, see <http://www.gnu.org/licenses/>.
893
- */
894
- const UNITS_DAY = 'day';
895
- const UNITS_WEEK = 'week';
896
- const UNITS_MONTH = 'month';
897
- const UNITS_YEAR = 'year';
898
- const UNITS_SINGLE = {
899
- d: UNITS_DAY,
900
- w: UNITS_WEEK,
901
- M: UNITS_MONTH,
902
- y: UNITS_YEAR
903
- };
904
- const UNITS_VALID = {
905
- day: UNITS_DAY,
906
- week: UNITS_WEEK,
907
- month: UNITS_MONTH,
908
- year: UNITS_YEAR
909
- };
910
-
911
- /**
912
- * A simple Hebrew date object with numeric fields `yy`, `mm`, and `dd`
913
- * @typedef {Object} SimpleHebrewDate
914
- * @property {number} yy Hebrew year
915
- * @property {number} mm Hebrew month of year (1=NISAN, 7=TISHREI)
916
- * @property {number} dd Day of month (1-30)
917
- * @private
918
- */
919
-
920
- /** Represents a Hebrew date */
921
- class HDate {
922
- /**
923
- * Create a Hebrew date. There are 3 basic forms for the `HDate()` constructor.
924
- *
925
- * 1. No parameters - represents the current Hebrew date at time of instantiation
926
- * 2. One parameter
927
- * * `Date` - represents the Hebrew date corresponding to the Gregorian date using
928
- * local time. Hours, minutes, seconds and milliseconds are ignored.
929
- * * `HDate` - clones a copy of the given Hebrew date
930
- * * `number` - Converts absolute R.D. days to Hebrew date.
931
- * R.D. 1 == the imaginary date January 1, 1 (Gregorian)
932
- * 3. Three parameters: Hebrew day, Hebrew month, Hebrew year. Hebrew day should
933
- * be a number between 1-30, Hebrew month can be a number or string, and
934
- * Hebrew year is always a number.
935
- * @example
936
- * import {HDate, months} from '@hebcal/core';
937
- *
938
- * const hd1 = new HDate();
939
- * const hd2 = new HDate(new Date(2008, 10, 13));
940
- * const hd3 = new HDate(15, 'Cheshvan', 5769);
941
- * const hd4 = new HDate(15, months.CHESHVAN, 5769);
942
- * const hd5 = new HDate(733359); // ==> 15 Cheshvan 5769
943
- * const monthName = 'אייר';
944
- * const hd6 = new HDate(5, monthName, 5773);
945
- * @param {number|Date|HDate} [day] - Day of month (1-30) if a `number`.
946
- * If a `Date` is specified, represents the Hebrew date corresponding to the
947
- * Gregorian date using local time.
948
- * If an `HDate` is specified, clones a copy of the given Hebrew date.
949
- * @param {number|string} [month] - Hebrew month of year (1=NISAN, 7=TISHREI)
950
- * @param {number} [year] - Hebrew year
951
- */
952
- constructor(day, month, year) {
953
- if (arguments.length == 2 || arguments.length > 3) {
954
- throw new TypeError('HDate constructor requires 0, 1 or 3 arguments');
955
- }
956
- if (arguments.length == 3) {
957
- // Hebrew day, Hebrew month, Hebrew year
958
- /**
959
- * @private
960
- * @type {number}
961
- */
962
- this.day = this.month = 1;
963
- /**
964
- * @private
965
- * @type {number}
966
- */
967
- year = parseInt(year, 10);
968
- if (isNaN(year)) {
969
- throw new TypeError(`HDate called with bad year argument: ${year}`);
970
- }
971
- this.year = year;
972
- this.setMonth(month); // will throw if we can't parse
973
- day = parseInt(day, 10);
974
- if (isNaN(day)) {
975
- throw new TypeError(`HDate called with bad day argument: ${day}`);
976
- }
977
- this.setDate(day);
978
- } else {
979
- // 0 arguments
980
- if (typeof day === 'undefined') {
981
- day = new Date();
982
- }
983
- // 1 argument
984
- const abs0 = typeof day === 'number' && !isNaN(day) ? day : isDate(day) ? greg2abs(day) : HDate.isHDate(day) ? {
985
- dd: day.day,
986
- mm: day.month,
987
- yy: day.year
988
- } : throwTypeError(`HDate called with bad argument: ${day}`);
989
- const isNumber = typeof abs0 === 'number';
990
- const d = isNumber ? abs2hebrew(abs0) : abs0;
991
- /**
992
- * @private
993
- * @type {number}
994
- */
995
- this.day = d.dd;
996
- /**
997
- * @private
998
- * @type {number}
999
- */
1000
- this.month = d.mm;
1001
- /**
1002
- * @private
1003
- * @type {number}
1004
- */
1005
- this.year = d.yy;
1006
- if (isNumber) {
1007
- /**
1008
- * @private
1009
- * @type {number}
1010
- */
1011
- this.abs0 = abs0;
1012
- }
1013
- }
1014
- }
1015
-
1016
- /**
1017
- * Gets the Hebrew year of this Hebrew date
1018
- * @return {number}
1019
- */
1020
- getFullYear() {
1021
- return this.year;
1022
- }
1023
-
1024
- /**
1025
- * Tests if this date occurs during a leap year
1026
- * @return {boolean}
1027
- */
1028
- isLeapYear() {
1029
- return isLeapYear(this.year);
1030
- }
1031
-
1032
- /**
1033
- * Gets the Hebrew month (1=NISAN, 7=TISHREI) of this Hebrew date
1034
- * @return {number}
1035
- */
1036
- getMonth() {
1037
- return this.month;
1038
- }
1039
-
1040
- /**
1041
- * The Tishrei-based month of the date. 1 is Tishrei, 7 is Nisan, 13 is Elul in a leap year
1042
- * @return {number}
1043
- */
1044
- getTishreiMonth() {
1045
- const nummonths = monthsInYear(this.getFullYear());
1046
- return (this.getMonth() + nummonths - 6) % nummonths || nummonths;
1047
- }
1048
-
1049
- /**
1050
- * Number of days in the month of this Hebrew date
1051
- * @return {number}
1052
- */
1053
- daysInMonth() {
1054
- return daysInMonth(this.getMonth(), this.getFullYear());
1055
- }
1056
-
1057
- /**
1058
- * Gets the day within the month (1-30)
1059
- * @return {number}
1060
- */
1061
- getDate() {
1062
- return this.day;
1063
- }
1064
-
1065
- /**
1066
- * Gets the day of the week. 0=Sunday, 6=Saturday
1067
- * @return {number}
1068
- */
1069
- getDay() {
1070
- return mod(this.abs(), 7);
1071
- }
1072
-
1073
- /**
1074
- * Sets the year of the date. Returns the object it was called upon.
1075
- * @private
1076
- * @deprecated
1077
- * @param {number} year
1078
- * @return {HDate}
1079
- */
1080
- setFullYear(year) {
1081
- this.year = year;
1082
- fix(this);
1083
- return this;
1084
- }
1085
-
1086
- /**
1087
- * Sets the day of the month of the date. Returns the object it was called upon
1088
- * @private
1089
- * @param {number|string} month A number, or Hebrew month name string
1090
- * @return {HDate}
1091
- */
1092
- setMonth(month) {
1093
- this.month = HDate.monthNum(month);
1094
- fix(this);
1095
- return this;
1096
- }
1097
-
1098
- /**
1099
- * @private
1100
- * @param {number} date
1101
- * @return {HDate}
1102
- */
1103
- setDate(date) {
1104
- this.day = date;
1105
- fix(this);
1106
- return this;
1107
- }
1108
-
1109
- /**
1110
- * Converts to Gregorian date
1111
- * @return {Date}
1112
- */
1113
- greg() {
1114
- return abs2greg(this.abs());
1115
- }
1116
-
1117
- /**
1118
- * Returns R.D. (Rata Die) fixed days.
1119
- * R.D. 1 == Monday, January 1, 1 (Gregorian)
1120
- * Note also that R.D. = Julian Date − 1,721,424.5
1121
- * https://en.wikipedia.org/wiki/Rata_Die#Dershowitz_and_Reingold
1122
- * @return {number}
1123
- */
1124
- abs() {
1125
- if (typeof this.abs0 !== 'number') {
1126
- this.abs0 = hebrew2abs(this.year, this.month, this.day);
1127
- }
1128
- return this.abs0;
1129
- }
1130
-
1131
- /**
1132
- * Converts Hebrew date to R.D. (Rata Die) fixed days.
1133
- * R.D. 1 is the imaginary date Monday, January 1, 1 on the Gregorian
1134
- * Calendar.
1135
- * @param {number} year Hebrew year
1136
- * @param {number} month Hebrew month
1137
- * @param {number} day Hebrew date (1-30)
1138
- * @return {number}
1139
- */
1140
- static hebrew2abs(year, month, day) {
1141
- return hebrew2abs(year, month, day);
1142
- }
1143
-
1144
- /**
1145
- * Converts absolute R.D. days to Hebrew date
1146
- * @private
1147
- * @param {number} abs absolute R.D. days
1148
- * @return {SimpleHebrewDate}
1149
- */
1150
- static abs2hebrew(abs) {
1151
- return abs2hebrew(abs);
1152
- }
1153
-
1154
- /**
1155
- * Returns a transliterated Hebrew month name, e.g. `'Elul'` or `'Cheshvan'`.
1156
- * @return {string}
1157
- */
1158
- getMonthName() {
1159
- return getMonthName(this.getMonth(), this.getFullYear());
1160
- }
1161
-
1162
- /**
1163
- * Renders this Hebrew date as a translated or transliterated string,
1164
- * including ordinal e.g. `'15th of Cheshvan, 5769'`.
1165
- * @example
1166
- * import {HDate, months} from '@hebcal/core';
1167
- *
1168
- * const hd = new HDate(15, months.CHESHVAN, 5769);
1169
- * console.log(hd.render('en')); // '15th of Cheshvan, 5769'
1170
- * console.log(hd.render('he')); // '15 חֶשְׁוָן, 5769'
1171
- * @param {string} [locale] Optional locale name (defaults to active locale).
1172
- * @param {boolean} [showYear=true] Display year (defaults to true).
1173
- * @return {string}
1174
- */
1175
- render() {
1176
- let locale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
1177
- let showYear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1178
- const locale0 = locale || Locale.getLocaleName();
1179
- const day = this.getDate();
1180
- const monthName = Locale.gettext(this.getMonthName(), locale0);
1181
- const nth = Locale.ordinal(day, locale0);
1182
- const dayOf = HDate.getDayOfTranslation(locale0);
1183
- const dateStr = `${nth}${dayOf} ${monthName}`;
1184
- if (showYear) {
1185
- const fullYear = this.getFullYear();
1186
- return `${dateStr}, ${fullYear}`;
1187
- } else {
1188
- return dateStr;
1189
- }
1190
- }
1191
-
1192
- /**
1193
- * @private
1194
- * @param {string} locale
1195
- * @return {string}
1196
- */
1197
- static getDayOfTranslation(locale) {
1198
- switch (locale) {
1199
- case 'en':
1200
- case 's':
1201
- case 'a':
1202
- case 'ashkenazi':
1203
- return ' of';
1204
- }
1205
- const ofStr = Locale.lookupTranslation('of', locale);
1206
- if (ofStr) {
1207
- return ' ' + ofStr;
1208
- }
1209
- if (locale.startsWith('ashkenazi')) {
1210
- return ' of';
1211
- }
1212
- return '';
1213
- }
1214
-
1215
- /**
1216
- * Renders this Hebrew date in Hebrew gematriya, regardless of locale.
1217
- * @example
1218
- * import {HDate, months} from '@hebcal/core';
1219
- * const hd = new HDate(15, months.CHESHVAN, 5769);
1220
- * console.log(hd.renderGematriya()); // 'ט״ו חֶשְׁוָן תשס״ט'
1221
- * @param {boolean} [suppressNikud]
1222
- * @return {string}
1223
- */
1224
- renderGematriya() {
1225
- let suppressNikud = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1226
- const d = this.getDate();
1227
- const locale = suppressNikud ? 'he-x-NoNikud' : 'he';
1228
- const m = Locale.gettext(this.getMonthName(), locale);
1229
- const y = this.getFullYear();
1230
- return gematriya(d) + ' ' + m + ' ' + gematriya(y);
1231
- }
1232
-
1233
- /**
1234
- * Returns an `HDate` representing the a dayNumber before the current date.
1235
- * Sunday=0, Saturday=6
1236
- * @example
1237
- * new HDate(new Date('Wednesday February 19, 2014')).before(6).greg() // Sat Feb 15 2014
1238
- * @param {number} day day of week
1239
- * @return {HDate}
1240
- */
1241
- before(day) {
1242
- return onOrBefore(day, this, -1);
1243
- }
1244
-
1245
- /**
1246
- * Returns an `HDate` representing the a dayNumber on or before the current date.
1247
- * Sunday=0, Saturday=6
1248
- * @example
1249
- * new HDate(new Date('Wednesday February 19, 2014')).onOrBefore(6).greg() // Sat Feb 15 2014
1250
- * new HDate(new Date('Saturday February 22, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014
1251
- * new HDate(new Date('Sunday February 23, 2014')).onOrBefore(6).greg() // Sat Feb 22 2014
1252
- * @param {number} dow day of week
1253
- * @return {HDate}
1254
- */
1255
- onOrBefore(dow) {
1256
- return onOrBefore(dow, this, 0);
1257
- }
1258
-
1259
- /**
1260
- * Returns an `HDate` representing the nearest dayNumber to the current date
1261
- * Sunday=0, Saturday=6
1262
- * @example
1263
- * new HDate(new Date('Wednesday February 19, 2014')).nearest(6).greg() // Sat Feb 22 2014
1264
- * new HDate(new Date('Tuesday February 18, 2014')).nearest(6).greg() // Sat Feb 15 2014
1265
- * @param {number} dow day of week
1266
- * @return {HDate}
1267
- */
1268
- nearest(dow) {
1269
- return onOrBefore(dow, this, 3);
1270
- }
1271
-
1272
- /**
1273
- * Returns an `HDate` representing the a dayNumber on or after the current date.
1274
- * Sunday=0, Saturday=6
1275
- * @example
1276
- * new HDate(new Date('Wednesday February 19, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014
1277
- * new HDate(new Date('Saturday February 22, 2014')).onOrAfter(6).greg() // Sat Feb 22 2014
1278
- * new HDate(new Date('Sunday February 23, 2014')).onOrAfter(6).greg() // Sat Mar 01 2014
1279
- * @param {number} dow day of week
1280
- * @return {HDate}
1281
- */
1282
- onOrAfter(dow) {
1283
- return onOrBefore(dow, this, 6);
1284
- }
1285
-
1286
- /**
1287
- * Returns an `HDate` representing the a dayNumber after the current date.
1288
- * Sunday=0, Saturday=6
1289
- * @example
1290
- * new HDate(new Date('Wednesday February 19, 2014')).after(6).greg() // Sat Feb 22 2014
1291
- * new HDate(new Date('Saturday February 22, 2014')).after(6).greg() // Sat Mar 01 2014
1292
- * new HDate(new Date('Sunday February 23, 2014')).after(6).greg() // Sat Mar 01 2014
1293
- * @param {number} day day of week
1294
- * @return {HDate}
1295
- */
1296
- after(day) {
1297
- return onOrBefore(day, this, 7);
1298
- }
1299
-
1300
- /**
1301
- * Returns the next Hebrew date
1302
- * @return {HDate}
1303
- */
1304
- next() {
1305
- return new HDate(this.abs() + 1);
1306
- }
1307
-
1308
- /**
1309
- * Returns the previous Hebrew date
1310
- * @return {HDate}
1311
- */
1312
- prev() {
1313
- return new HDate(this.abs() - 1);
1314
- }
1315
-
1316
- /**
1317
- * Returns a cloned `HDate` object with a specified amount of time added
1318
- *
1319
- * Units are case insensitive, and support plural and short forms.
1320
- * Note, short forms are case sensitive.
1321
- *
1322
- * | Unit | Shorthand | Description
1323
- * | --- | --- | --- |
1324
- * | `day` | `d` | days |
1325
- * | `week` | `w` | weeks |
1326
- * | `month` | `M` | months |
1327
- * | `year` | `y` | years |
1328
- * @param {number} number
1329
- * @param {string} [units]
1330
- * @return {HDate}
1331
- */
1332
- add(number) {
1333
- let units = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd';
1334
- number = parseInt(number, 10);
1335
- if (!number) {
1336
- return new HDate(this);
1337
- }
1338
- units = HDate.standardizeUnits(units);
1339
- if (units === UNITS_DAY) {
1340
- return new HDate(this.abs() + number);
1341
- } else if (units === UNITS_WEEK) {
1342
- return new HDate(this.abs() + 7 * number);
1343
- } else if (units === UNITS_YEAR) {
1344
- return new HDate(this.getDate(), this.getMonth(), this.getFullYear() + number);
1345
- } else if (units === UNITS_MONTH) {
1346
- let hd = new HDate(this);
1347
- const sign = number > 0 ? 1 : -1;
1348
- number = Math.abs(number);
1349
- for (let i = 0; i < number; i++) {
1350
- hd = new HDate(hd.abs() + sign * hd.daysInMonth());
1351
- }
1352
- return hd;
1353
- }
1354
- }
1355
-
1356
- /**
1357
- * @private
1358
- * @param {string} units
1359
- * @return {string}
1360
- */
1361
- static standardizeUnits(units) {
1362
- const full = UNITS_SINGLE[units] || String(units || '').toLowerCase().replace(/s$/, '');
1363
- return UNITS_VALID[full] || throwTypeError(`Invalid units '${units}'`);
1364
- }
1365
-
1366
- /**
1367
- * Returns a cloned `HDate` object with a specified amount of time subracted
1368
- *
1369
- * Units are case insensitive, and support plural and short forms.
1370
- * Note, short forms are case sensitive.
1371
- *
1372
- * | Unit | Shorthand | Description
1373
- * | --- | --- | --- |
1374
- * | `day` | `d` | days |
1375
- * | `week` | `w` | weeks |
1376
- * | `month` | `M` | months |
1377
- * | `year` | `y` | years |
1378
- * @example
1379
- * import {HDate, months} from '@hebcal/core';
1380
- *
1381
- * const hd1 = new HDate(15, months.CHESHVAN, 5769);
1382
- * const hd2 = hd1.add(1, 'weeks'); // 7 Kislev 5769
1383
- * const hd3 = hd1.add(-3, 'M'); // 30 Av 5768
1384
- * @param {number} number
1385
- * @param {string} [units]
1386
- * @return {HDate}
1387
- */
1388
- subtract(number) {
1389
- let units = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd';
1390
- return this.add(number * -1, units);
1391
- }
1392
-
1393
- /**
1394
- * Returns the difference in days between the two given HDates.
1395
- *
1396
- * The result is positive if `this` date is comes chronologically
1397
- * after the `other` date, and negative
1398
- * if the order of the two dates is reversed.
1399
- *
1400
- * The result is zero if the two dates are identical.
1401
- * @example
1402
- * import {HDate, months} from '@hebcal/core';
1403
- *
1404
- * const hd1 = new HDate(25, months.KISLEV, 5770);
1405
- * const hd2 = new HDate(15, months.CHESHVAN, 5769);
1406
- * const days = hd1.deltaDays(hd2); // 394
1407
- * @param {HDate} other Hebrew date to compare
1408
- * @return {number}
1409
- */
1410
- deltaDays(other) {
1411
- if (!HDate.isHDate(other)) {
1412
- throw new TypeError(`Bad argument: ${other}`);
1413
- }
1414
- return this.abs() - other.abs();
1415
- }
1416
-
1417
- /**
1418
- * Compares this date to another date, returning `true` if the dates match.
1419
- * @param {HDate} other Hebrew date to compare
1420
- * @return {boolean}
1421
- */
1422
- isSameDate(other) {
1423
- if (HDate.isHDate(other)) {
1424
- return this.year == other.year && this.month == other.month && this.day == other.day;
1425
- }
1426
- return false;
1427
- }
1428
-
1429
- /** @return {string} */
1430
- toString() {
1431
- const day = this.getDate();
1432
- const fullYear = this.getFullYear();
1433
- const monthName = this.getMonthName();
1434
- return `${day} ${monthName} ${fullYear}`;
1435
- }
1436
-
1437
- /**
1438
- * Returns true if Hebrew year is a leap year
1439
- * @param {number} year Hebrew year
1440
- * @return {boolean}
1441
- */
1442
- static isLeapYear(year) {
1443
- return isLeapYear(year);
1444
- }
1445
-
1446
- /**
1447
- * Number of months in this Hebrew year (either 12 or 13 depending on leap year)
1448
- * @param {number} year Hebrew year
1449
- * @return {number}
1450
- */
1451
- static monthsInYear(year) {
1452
- return monthsInYear(year);
1453
- }
1454
-
1455
- /**
1456
- * Number of days in Hebrew month in a given year (29 or 30)
1457
- * @param {number} month Hebrew month (e.g. months.TISHREI)
1458
- * @param {number} year Hebrew year
1459
- * @return {number}
1460
- */
1461
- static daysInMonth(month, year) {
1462
- return daysInMonth(month, year);
1463
- }
1464
-
1465
- /**
1466
- * Returns a transliterated string name of Hebrew month in year,
1467
- * for example 'Elul' or 'Cheshvan'.
1468
- * @param {number} month Hebrew month (e.g. months.TISHREI)
1469
- * @param {number} year Hebrew year
1470
- * @return {string}
1471
- */
1472
- static getMonthName(month, year) {
1473
- return getMonthName(month, year);
1474
- }
1475
-
1476
- /**
1477
- * Returns the Hebrew month number (NISAN=1, TISHREI=7)
1478
- * @param {number|string} month A number, or Hebrew month name string
1479
- * @return {number}
1480
- */
1481
- static monthNum(month) {
1482
- if (typeof month === 'number') {
1483
- if (isNaN(month) || month > 14) {
1484
- throw new RangeError(`Invalid month number: ${month}`);
1485
- }
1486
- return month;
1487
- }
1488
- return month.charCodeAt(0) >= 48 && month.charCodeAt(0) <= 57 ? /* number */
1489
- parseInt(month, 10) : HDate.monthFromName(month);
1490
- }
1491
-
1492
- /**
1493
- * Number of days in the hebrew YEAR
1494
- * @param {number} year Hebrew year
1495
- * @return {number}
1496
- */
1497
- static daysInYear(year) {
1498
- return daysInYear(year);
1499
- }
1500
-
1501
- /**
1502
- * true if Cheshvan is long in Hebrew year
1503
- * @param {number} year Hebrew year
1504
- * @return {boolean}
1505
- */
1506
- static longCheshvan(year) {
1507
- return longCheshvan(year);
1508
- }
1509
-
1510
- /**
1511
- * true if Kislev is short in Hebrew year
1512
- * @param {number} year Hebrew year
1513
- * @return {boolean}
1514
- */
1515
- static shortKislev(year) {
1516
- return shortKislev(year);
1517
- }
1518
-
1519
- /**
1520
- * Converts Hebrew month string name to numeric
1521
- * @param {string} monthName monthName
1522
- * @return {number}
1523
- */
1524
- static monthFromName(monthName) {
1525
- if (typeof monthName === 'number') {
1526
- if (isNaN(monthName) || monthName < 1 || monthName > 14) {
1527
- throw new RangeError(`Invalid month name: ${monthName}`);
1528
- }
1529
- return monthName;
1530
- }
1531
- let c = Locale.hebrewStripNikkud(monthName).trim().toLowerCase();
1532
- // If Hebrew month starts with a bet (for example `בתמוז`) then ignore it
1533
- if (c[0] === 'ב') {
1534
- c = c.substring(1);
1535
- }
1536
- /*
1537
- the Hebrew months are unique to their second letter
1538
- N Nisan (November?)
1539
- I Iyyar
1540
- E Elul
1541
- C Cheshvan
1542
- K Kislev
1543
- 1 1Adar
1544
- 2 2Adar
1545
- Si Sh Sivan, Shvat
1546
- Ta Ti Te Tamuz, Tishrei, Tevet
1547
- Av Ad Av, Adar
1548
- אב אד אי אל אב אדר אייר אלול
1549
- ח חשון
1550
- ט טבת
1551
- כ כסלו
1552
- נ ניסן
1553
- ס סיון
1554
- ש שבט
1555
- תמ תש תמוז תשרי
1556
- */
1557
- switch (c[0]) {
1558
- case 'n':
1559
- case 'נ':
1560
- if (c[1] == 'o') {
1561
- break; /* this catches "november" */
1562
- }
1563
-
1564
- return months.NISAN;
1565
- case 'i':
1566
- return months.IYYAR;
1567
- case 'e':
1568
- return months.ELUL;
1569
- case 'c':
1570
- case 'ח':
1571
- return months.CHESHVAN;
1572
- case 'k':
1573
- case 'כ':
1574
- return months.KISLEV;
1575
- case 's':
1576
- switch (c[1]) {
1577
- case 'i':
1578
- return months.SIVAN;
1579
- case 'h':
1580
- return months.SHVAT;
1581
- }
1582
- break;
1583
- case 't':
1584
- switch (c[1]) {
1585
- case 'a':
1586
- return months.TAMUZ;
1587
- case 'i':
1588
- return months.TISHREI;
1589
- case 'e':
1590
- return months.TEVET;
1591
- }
1592
- break;
1593
- case 'a':
1594
- switch (c[1]) {
1595
- case 'v':
1596
- return months.AV;
1597
- case 'd':
1598
- if (/(1|[^i]i|a|א)$/i.test(monthName)) {
1599
- return months.ADAR_I;
1600
- }
1601
- return months.ADAR_II;
1602
- }
1603
- break;
1604
- case 'ס':
1605
- return months.SIVAN;
1606
- case 'ט':
1607
- return months.TEVET;
1608
- case 'ש':
1609
- return months.SHVAT;
1610
- case 'א':
1611
- switch (c[1]) {
1612
- case 'ב':
1613
- return months.AV;
1614
- case 'ד':
1615
- if (/(1|[^i]i|a|א)$/i.test(monthName)) {
1616
- return months.ADAR_I;
1617
- }
1618
- return months.ADAR_II;
1619
- // else assume sheini
1620
- case 'י':
1621
- return months.IYYAR;
1622
- case 'ל':
1623
- return months.ELUL;
1624
- }
1625
- break;
1626
- case 'ת':
1627
- switch (c[1]) {
1628
- case 'מ':
1629
- return months.TAMUZ;
1630
- case 'ש':
1631
- return months.TISHREI;
1632
- }
1633
- break;
1634
- }
1635
- throw new RangeError(`Unable to parse month name: ${monthName}`);
1636
- }
1637
-
1638
- /**
1639
- * Note: Applying this function to d+6 gives us the DAYNAME on or after an
1640
- * absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to
1641
- * absolute date d, applying it to d-1 gives the DAYNAME previous to absolute
1642
- * date d, and applying it to d+7 gives the DAYNAME following absolute date d.
1643
- * @param {number} dayOfWeek
1644
- * @param {number} absdate
1645
- * @return {number}
1646
- */
1647
- static dayOnOrBefore(dayOfWeek, absdate) {
1648
- return absdate - (absdate - dayOfWeek) % 7;
1649
- }
1650
-
1651
- /**
1652
- * Tests if the object is an instance of `HDate`
1653
- * @param {any} obj
1654
- * @return {boolean}
1655
- */
1656
- static isHDate(obj) {
1657
- return obj !== null && typeof obj === 'object' && typeof obj.year === 'number' && typeof obj.month === 'number' && typeof obj.day === 'number' && typeof obj.greg === 'function' && typeof obj.abs === 'function';
1658
- }
1659
-
1660
- /**
1661
- * Construct a new instance of `HDate` from a Gematriya-formatted string
1662
- * @example
1663
- * HDate.fromGematriyaString('כ״ז בְּתַמּוּז תשפ״ג') // 27 Tamuz 5783
1664
- * HDate.fromGematriyaString('כ׳ סיון תש״ד') // 20 Sivan 5704
1665
- * HDate.fromGematriyaString('ה׳ אִיָיר תש״ח') // 5 Iyyar 5708
1666
- * @param {string} str
1667
- * @param {number} currentThousands
1668
- * @return {HDate}
1669
- */
1670
- static fromGematriyaString(str) {
1671
- let currentThousands = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000;
1672
- const parts = str.split(' ');
1673
- const day = gematriyaStrToNum(parts[0]);
1674
- const month = HDate.monthFromName(parts[1]);
1675
- let year = gematriyaStrToNum(parts[2]);
1676
- if (year < 1000) {
1677
- year += currentThousands;
1678
- }
1679
- return new HDate(day, month, year);
1680
- }
1681
- }
1682
-
1683
- /**
1684
- * @private
1685
- * @param {HDate} date
1686
- */
1687
- function fix(date) {
1688
- fixMonth(date);
1689
- fixDate(date);
1690
- }
1691
-
1692
- /**
1693
- * @private
1694
- * @param {HDate} date
1695
- */
1696
- function fixDate(date) {
1697
- if (date.day < 1) {
1698
- if (date.month == months.TISHREI) {
1699
- date.year -= 1;
1700
- }
1701
- date.day += daysInMonth(date.month, date.year);
1702
- date.month -= 1;
1703
- fix(date);
1704
- }
1705
- if (date.day > daysInMonth(date.month, date.year)) {
1706
- if (date.month === months.ELUL) {
1707
- date.year += 1;
1708
- }
1709
- date.day -= daysInMonth(date.month, date.year);
1710
- date.month += 1;
1711
- fix(date);
1712
- }
1713
- fixMonth(date);
1714
- }
1715
-
1716
- /**
1717
- * @private
1718
- * @param {HDate} date
1719
- */
1720
- function fixMonth(date) {
1721
- if (date.month === months.ADAR_II && !date.isLeapYear()) {
1722
- date.month -= 1; // to Adar I
1723
- fix(date);
1724
- } else if (date.month < 1) {
1725
- date.month += monthsInYear(date.year);
1726
- date.year -= 1;
1727
- fix(date);
1728
- } else if (date.month > monthsInYear(date.year)) {
1729
- date.month -= monthsInYear(date.year);
1730
- date.year += 1;
1731
- fix(date);
1732
- }
1733
- delete date.abs0;
1734
- }
1735
-
1736
- /**
1737
- * @private
1738
- * @param {number} day
1739
- * @param {HDate} t
1740
- * @param {number} offset
1741
- * @return {HDate}
1742
- */
1743
- function onOrBefore(day, t, offset) {
1744
- return new HDate(HDate.dayOnOrBefore(day, t.abs() + offset));
1745
- }
1746
-
1747
- const NISAN = months.NISAN;
1748
- const CHESHVAN = months.CHESHVAN;
1749
- const KISLEV = months.KISLEV;
1750
- const TEVET = months.TEVET;
1751
- const SHVAT = months.SHVAT;
1752
- const ADAR_I = months.ADAR_I;
1753
- const ADAR_II = months.ADAR_II;
1754
-
1755
- /**
1756
- * @private
1757
- * @param {number} hyear Hebrew year
1758
- * @param {Date|HDate} gdate Gregorian or Hebrew date of death
1759
- * @return {HDate} anniversary occurring in hyear
1760
- */
1761
- function getYahrzeit_(hyear, gdate) {
1762
- const orig = HDate.isHDate(gdate) ? gdate : new HDate(gdate);
1763
- let hDeath = {
1764
- yy: orig.getFullYear(),
1765
- mm: orig.getMonth(),
1766
- dd: orig.getDate()
1767
- };
1768
- if (hyear <= hDeath.yy) {
1769
- // `Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy}`
1770
- return undefined;
1771
- }
1772
- if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hDeath.yy + 1)) {
1773
- // If it's Heshvan 30 it depends on the first anniversary;
1774
- // if that was not Heshvan 30, use the day before Kislev 1.
1775
- hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV, 1) - 1);
1776
- } else if (hDeath.mm == KISLEV && hDeath.dd == 30 && shortKislev(hDeath.yy + 1)) {
1777
- // If it's Kislev 30 it depends on the first anniversary;
1778
- // if that was not Kislev 30, use the day before Teveth 1.
1779
- hDeath = abs2hebrew(hebrew2abs(hyear, TEVET, 1) - 1);
1780
- } else if (hDeath.mm == ADAR_II) {
1781
- // If it's Adar II, use the same day in last month of year (Adar or Adar II).
1782
- hDeath.mm = monthsInYear(hyear);
1783
- } else if (hDeath.mm == ADAR_I && hDeath.dd == 30 && !isLeapYear(hyear)) {
1784
- // If it's the 30th in Adar I and year is not a leap year
1785
- // (so Adar has only 29 days), use the last day in Shevat.
1786
- hDeath.dd = 30;
1787
- hDeath.mm = SHVAT;
1788
- }
1789
- // In all other cases, use the normal anniversary of the date of death.
1790
-
1791
- // advance day to rosh chodesh if needed
1792
- if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hyear)) {
1793
- hDeath.mm = KISLEV;
1794
- hDeath.dd = 1;
1795
- } else if (hDeath.mm == KISLEV && hDeath.dd == 30 && shortKislev(hyear)) {
1796
- hDeath.mm = TEVET;
1797
- hDeath.dd = 1;
1798
- }
1799
- return new HDate(hDeath.dd, hDeath.mm, hyear);
1800
- }
1801
-
1802
- /**
1803
- * @private
1804
- * @param {number} hyear Hebrew year
1805
- * @param {Date|HDate} gdate Gregorian or Hebrew date of event
1806
- * @return {HDate} anniversary occurring in `hyear`
1807
- */
1808
- function getBirthdayOrAnniversary_(hyear, gdate) {
1809
- const orig = HDate.isHDate(gdate) ? gdate : new HDate(gdate);
1810
- const origYear = orig.getFullYear();
1811
- if (hyear === origYear) {
1812
- return orig;
1813
- } else if (hyear < origYear) {
1814
- // `Hebrew year ${hyear} occurs on or before original date in ${origYear}`
1815
- return undefined;
1816
- }
1817
- const isOrigLeap = isLeapYear(origYear);
1818
- let month = orig.getMonth();
1819
- let day = orig.getDate();
1820
- if (month == ADAR_I && !isOrigLeap || month == ADAR_II && isOrigLeap) {
1821
- month = monthsInYear(hyear);
1822
- } else if (month == CHESHVAN && day == 30 && !longCheshvan(hyear)) {
1823
- month = KISLEV;
1824
- day = 1;
1825
- } else if (month == KISLEV && day == 30 && shortKislev(hyear)) {
1826
- month = TEVET;
1827
- day = 1;
1828
- } else if (month == ADAR_I && day == 30 && isOrigLeap && !isLeapYear(hyear)) {
1829
- month = NISAN;
1830
- day = 1;
1831
- }
1832
- return new HDate(day, month, hyear);
1833
- }
1834
-
1835
- const version="4.5.1";
1836
-
1837
- const headers={"plural-forms":"nplurals=2; plural=(n > 1);"};const contexts={"":{Adar:["אַדָר"],"Adar I":["אַדָר א׳"],"Adar II":["אַדָר ב׳"],Av:["אָב"],Cheshvan:["חֶשְׁוָן"],Elul:["אֱלוּל"],Iyyar:["אִיָיר"],Kislev:["כִּסְלֵו"],Nisan:["נִיסָן"],"Sh'vat":["שְׁבָט"],Sivan:["סִיוָן"],Tamuz:["תַּמּוּז"],Tevet:["טֵבֵת"],Tishrei:["תִּשְׁרֵי"]}};var poHeMin = {headers:headers,contexts:contexts};
1838
-
1839
- Locale.addLocale('he', poHeMin);
1840
- Locale.addLocale('h', poHeMin);
1841
- const heStrs = poHeMin.contexts[''];
1842
- const heNoNikud = {};
1843
- Object.keys(heStrs).forEach(key => {
1844
- heNoNikud[key] = [Locale.hebrewStripNikkud(heStrs[key][0])];
1845
- });
1846
- Locale.addLocale('he-x-NoNikud', {
1847
- headers: poHeMin.headers,
1848
- contexts: {
1849
- '': heNoNikud
1850
- }
1851
- });
1852
-
1853
- exports.HDate = HDate;
1854
- exports.Locale = Locale;
1855
- exports.gematriya = gematriya;
1856
- exports.getBirthdayOrAnniversary = getBirthdayOrAnniversary_;
1857
- exports.getYahrzeit = getYahrzeit_;
1858
- exports.greg = greg;
1859
- exports.months = months;
1860
- exports.version = version;
1861
-
1862
- return exports;
1863
-
1864
- })({});