@hebcal/core 4.5.1 → 5.0.0-rc2

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