@hebcal/core 5.0.0 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +136 -225
- package/dist/bundle.js +551 -596
- package/dist/bundle.min.js +2 -2
- package/dist/index.js +433 -478
- package/dist/index.mjs +433 -478
- package/package.json +9 -9
package/dist/bundle.js
CHANGED
|
@@ -1,457 +1,112 @@
|
|
|
1
|
-
/*! @hebcal/core v5.0.
|
|
1
|
+
/*! @hebcal/core v5.0.2 */
|
|
2
2
|
var hebcal = (function (exports) {
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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 = new Map();
|
|
32
|
-
Object.keys(heb2num).forEach(key => {
|
|
33
|
-
const val = heb2num[key];
|
|
34
|
-
num2heb.set(val, key);
|
|
35
|
-
});
|
|
36
|
-
|
|
5
|
+
/** @private */
|
|
6
|
+
const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
7
|
+
/** @private */
|
|
8
|
+
const monthLengths = [lengths, lengths.slice()];
|
|
9
|
+
monthLengths[1][2] = 29;
|
|
37
10
|
/**
|
|
38
11
|
* @private
|
|
39
|
-
* @param {number} num
|
|
40
|
-
* @return {number[]}
|
|
41
12
|
*/
|
|
42
|
-
function
|
|
43
|
-
|
|
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;
|
|
13
|
+
function mod$1(x, y) {
|
|
14
|
+
return x - y * Math.floor(x / y);
|
|
61
15
|
}
|
|
62
|
-
|
|
63
16
|
/**
|
|
64
|
-
*
|
|
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}
|
|
17
|
+
* @private
|
|
76
18
|
*/
|
|
77
|
-
function
|
|
78
|
-
|
|
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.get(tdig);
|
|
88
|
-
}
|
|
89
|
-
str += GERESH;
|
|
90
|
-
}
|
|
91
|
-
const digits = num2digits(num % 1000);
|
|
92
|
-
if (digits.length == 1) {
|
|
93
|
-
return str + num2heb.get(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.get(digits[i]);
|
|
100
|
-
}
|
|
101
|
-
return str;
|
|
19
|
+
function quotient(x, y) {
|
|
20
|
+
return Math.floor(x / y);
|
|
102
21
|
}
|
|
103
|
-
|
|
22
|
+
/*
|
|
23
|
+
const ABS_14SEP1752 = 639797;
|
|
24
|
+
const ABS_2SEP1752 = 639785;
|
|
25
|
+
*/
|
|
104
26
|
/**
|
|
105
|
-
*
|
|
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}
|
|
27
|
+
* Gregorian date helper functions.
|
|
113
28
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
29
|
+
exports.greg = void 0;
|
|
30
|
+
(function (greg) {
|
|
31
|
+
/**
|
|
32
|
+
* Long names of the Gregorian months (1='January', 12='December')
|
|
33
|
+
* @readonly
|
|
34
|
+
* @type {string[]}
|
|
35
|
+
*/
|
|
36
|
+
greg.monthNames = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
37
|
+
/**
|
|
38
|
+
* Returns true if the Gregorian year is a leap year
|
|
39
|
+
* @param {number} year Gregorian year
|
|
40
|
+
* @return {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function isLeapYear(year) {
|
|
43
|
+
return !(year % 4) && (!!(year % 100) || !(year % 400));
|
|
121
44
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
45
|
+
greg.isLeapYear = isLeapYear;
|
|
46
|
+
/**
|
|
47
|
+
* Number of days in the Gregorian month for given year
|
|
48
|
+
* @param {number} month Gregorian month (1=January, 12=December)
|
|
49
|
+
* @param {number} year Gregorian year
|
|
50
|
+
* @return {number}
|
|
51
|
+
*/
|
|
52
|
+
function daysInMonth(month, year) {
|
|
53
|
+
// 1 based months
|
|
54
|
+
return monthLengths[+isLeapYear(year)][month];
|
|
127
55
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
'': {}
|
|
56
|
+
greg.daysInMonth = daysInMonth;
|
|
57
|
+
/**
|
|
58
|
+
* Returns true if the object is a Javascript Date
|
|
59
|
+
* @param {Object} obj
|
|
60
|
+
* @return {boolean}
|
|
61
|
+
*/
|
|
62
|
+
function isDate(obj) {
|
|
63
|
+
return typeof obj === 'object' && Date.prototype.isPrototypeOf(obj);
|
|
137
64
|
}
|
|
138
|
-
|
|
139
|
-
const alias = {
|
|
140
|
-
'h': 'he',
|
|
141
|
-
'a': 'ashkenazi',
|
|
142
|
-
's': 'en',
|
|
143
|
-
'': 'en'
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
/** @private */
|
|
147
|
-
const locales = new Map();
|
|
148
|
-
/** @private */
|
|
149
|
-
let activeLocale = null;
|
|
150
|
-
/** @private */
|
|
151
|
-
let activeName = null;
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* A locale in Hebcal is used for translations/transliterations of
|
|
155
|
-
* holidays. `@hebcal/core` supports four locales by default
|
|
156
|
-
* * `en` - default, Sephardic transliterations (e.g. "Shabbat")
|
|
157
|
-
* * `ashkenazi` - Ashkenazi transliterations (e.g. "Shabbos")
|
|
158
|
-
* * `he` - Hebrew (e.g. "שַׁבָּת")
|
|
159
|
-
* * `he-x-NoNikud` - Hebrew without nikud (e.g. "שבת")
|
|
160
|
-
*/
|
|
161
|
-
class Locale {
|
|
65
|
+
greg.isDate = isDate;
|
|
162
66
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @param {string} id Message ID to translate
|
|
166
|
-
* @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
167
|
-
* @return {string}
|
|
67
|
+
* @private
|
|
68
|
+
* @param abs - R.D. number of days
|
|
168
69
|
*/
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
70
|
+
function yearFromFixed(abs) {
|
|
71
|
+
const l0 = abs - 1;
|
|
72
|
+
const n400 = quotient(l0, 146097);
|
|
73
|
+
const d1 = mod$1(l0, 146097);
|
|
74
|
+
const n100 = quotient(d1, 36524);
|
|
75
|
+
const d2 = mod$1(d1, 36524);
|
|
76
|
+
const n4 = quotient(d2, 1461);
|
|
77
|
+
const d3 = mod$1(d2, 1461);
|
|
78
|
+
const n1 = quotient(d3, 365);
|
|
79
|
+
const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
80
|
+
return n100 != 4 && n1 != 4 ? year + 1 : year;
|
|
177
81
|
}
|
|
178
|
-
|
|
179
82
|
/**
|
|
180
|
-
*
|
|
181
|
-
* @param
|
|
182
|
-
* @param
|
|
183
|
-
* @
|
|
83
|
+
* @private
|
|
84
|
+
* @param year
|
|
85
|
+
* @param month (1-12)
|
|
86
|
+
* @param day (1-31)
|
|
184
87
|
*/
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
return id;
|
|
189
|
-
}
|
|
190
|
-
return text;
|
|
88
|
+
function toFixed(year, month, day) {
|
|
89
|
+
const py = year - 1;
|
|
90
|
+
return 365 * py + quotient(py, 4) - quotient(py, 100) + quotient(py, 400) + quotient(367 * month - 362, 12) + (month <= 2 ? 0 : isLeapYear(year) ? -1 : -2) + day;
|
|
191
91
|
}
|
|
192
|
-
|
|
193
92
|
/**
|
|
194
|
-
*
|
|
195
|
-
* @param {
|
|
196
|
-
* @
|
|
93
|
+
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
94
|
+
* @param {Date} date Gregorian date
|
|
95
|
+
* @return {number}
|
|
197
96
|
*/
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
throw new TypeError(`
|
|
97
|
+
function greg2abs(date) {
|
|
98
|
+
if (!isDate(date)) {
|
|
99
|
+
throw new TypeError(`Argument not a Date: ${date}`);
|
|
201
100
|
}
|
|
202
|
-
|
|
203
|
-
|
|
101
|
+
const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
102
|
+
/*
|
|
103
|
+
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
104
|
+
throw new RangeError(`Invalid Date: ${date}`);
|
|
204
105
|
}
|
|
205
|
-
|
|
106
|
+
*/
|
|
107
|
+
return abs;
|
|
206
108
|
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Adds a translation to `locale`, replacing any previous translation.
|
|
210
|
-
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
|
|
211
|
-
* @param {string} id Message ID to translate
|
|
212
|
-
* @param {string} translation Translation text
|
|
213
|
-
*/
|
|
214
|
-
static addTranslation(locale, id, translation) {
|
|
215
|
-
if (typeof locale !== 'string') {
|
|
216
|
-
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
217
|
-
}
|
|
218
|
-
const locale0 = locale.toLowerCase();
|
|
219
|
-
const loc = locales.get(locale0);
|
|
220
|
-
if (!loc) {
|
|
221
|
-
throw new TypeError(`Unknown locale: ${locale}`);
|
|
222
|
-
}
|
|
223
|
-
if (typeof id !== 'string' || id.length === 0) {
|
|
224
|
-
throw new TypeError(`Invalid id: ${id}`);
|
|
225
|
-
}
|
|
226
|
-
const isArray = Array.isArray(translation);
|
|
227
|
-
if (isArray) {
|
|
228
|
-
const t0 = translation[0];
|
|
229
|
-
if (typeof t0 !== 'string' || t0.length === 0) {
|
|
230
|
-
throw new TypeError(`Invalid translation array: ${translation}`);
|
|
231
|
-
}
|
|
232
|
-
} else if (typeof translation !== 'string') {
|
|
233
|
-
throw new TypeError(`Invalid translation: ${translation}`);
|
|
234
|
-
}
|
|
235
|
-
loc[id] = isArray ? translation : [translation];
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Adds multiple translations to `locale`, replacing any previous translations.
|
|
239
|
-
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
|
|
240
|
-
* @param {LocaleData} data parsed data from a `.po` file.
|
|
241
|
-
*/
|
|
242
|
-
static addTranslations(locale, data) {
|
|
243
|
-
if (typeof locale !== 'string') {
|
|
244
|
-
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
245
|
-
}
|
|
246
|
-
const locale0 = locale.toLowerCase();
|
|
247
|
-
const loc = locales.get(locale0);
|
|
248
|
-
if (!loc) {
|
|
249
|
-
throw new TypeError(`Unknown locale: ${locale}`);
|
|
250
|
-
}
|
|
251
|
-
if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
|
|
252
|
-
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
253
|
-
}
|
|
254
|
-
const ctx = data.contexts[''];
|
|
255
|
-
Object.keys(ctx).forEach(id => {
|
|
256
|
-
loc[id] = ctx[id];
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Activates a locale. Throws an error if the locale has not been previously added.
|
|
261
|
-
* After setting the locale to be used, all strings marked for translations
|
|
262
|
-
* will be represented by the corresponding translation in the specified locale.
|
|
263
|
-
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`)
|
|
264
|
-
* @return {LocaleData}
|
|
265
|
-
*/
|
|
266
|
-
static useLocale(locale) {
|
|
267
|
-
const locale0 = locale.toLowerCase();
|
|
268
|
-
const obj = locales.get(locale0);
|
|
269
|
-
if (!obj) {
|
|
270
|
-
throw new RangeError(`Locale '${locale}' not found`);
|
|
271
|
-
}
|
|
272
|
-
activeName = alias[locale0] || locale0;
|
|
273
|
-
activeLocale = obj;
|
|
274
|
-
return activeLocale;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Returns the name of the active locale (i.e. 'he', 'ashkenazi', 'fr')
|
|
279
|
-
* @return {string}
|
|
280
|
-
*/
|
|
281
|
-
static getLocaleName() {
|
|
282
|
-
return activeName;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Returns the names of registered locales
|
|
287
|
-
* @return {string[]}
|
|
288
|
-
*/
|
|
289
|
-
static getLocaleNames() {
|
|
290
|
-
const keys = Array.from(locales.keys());
|
|
291
|
-
return keys.sort((a, b) => a.localeCompare(b));
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @param {number} n
|
|
296
|
-
* @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
297
|
-
* @return {string}
|
|
298
|
-
*/
|
|
299
|
-
static ordinal(n, locale) {
|
|
300
|
-
const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
301
|
-
const locale0 = locale1 || activeName;
|
|
302
|
-
if (!locale0) {
|
|
303
|
-
return this.getEnOrdinal(n);
|
|
304
|
-
}
|
|
305
|
-
switch (locale0) {
|
|
306
|
-
case 'en':
|
|
307
|
-
case 's':
|
|
308
|
-
case 'a':
|
|
309
|
-
case 'ashkenazi':
|
|
310
|
-
case 'ashkenazi_litvish':
|
|
311
|
-
case 'ashkenazi_poylish':
|
|
312
|
-
case 'ashkenazi_standard':
|
|
313
|
-
return this.getEnOrdinal(n);
|
|
314
|
-
case 'es':
|
|
315
|
-
return n + 'º';
|
|
316
|
-
case 'h':
|
|
317
|
-
case 'he':
|
|
318
|
-
case 'he-x-nonikud':
|
|
319
|
-
return String(n);
|
|
320
|
-
default:
|
|
321
|
-
return n + '.';
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* @private
|
|
327
|
-
* @param {number} n
|
|
328
|
-
* @return {string}
|
|
329
|
-
*/
|
|
330
|
-
static getEnOrdinal(n) {
|
|
331
|
-
const s = ['th', 'st', 'nd', 'rd'];
|
|
332
|
-
const v = n % 100;
|
|
333
|
-
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Removes nekudot from Hebrew string
|
|
338
|
-
* @param {string} str
|
|
339
|
-
* @return {string}
|
|
340
|
-
*/
|
|
341
|
-
static hebrewStripNikkud(str) {
|
|
342
|
-
return str.replace(/[\u0590-\u05bd]/g, '').replace(/[\u05bf-\u05c7]/g, '');
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
Locale.addLocale('en', noopLocale);
|
|
346
|
-
Locale.addLocale('s', noopLocale);
|
|
347
|
-
Locale.addLocale('', noopLocale);
|
|
348
|
-
Locale.useLocale('en');
|
|
349
|
-
|
|
350
|
-
/** @private */
|
|
351
|
-
const lengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
352
|
-
/** @private */
|
|
353
|
-
const monthLengths = [lengths, lengths.slice()];
|
|
354
|
-
monthLengths[1][2] = 29;
|
|
355
|
-
/**
|
|
356
|
-
* @private
|
|
357
|
-
*/
|
|
358
|
-
function mod$1(x, y) {
|
|
359
|
-
return x - y * Math.floor(x / y);
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* @private
|
|
363
|
-
*/
|
|
364
|
-
function quotient(x, y) {
|
|
365
|
-
return Math.floor(x / y);
|
|
366
|
-
}
|
|
367
|
-
/*
|
|
368
|
-
const ABS_14SEP1752 = 639797;
|
|
369
|
-
const ABS_2SEP1752 = 639785;
|
|
370
|
-
*/
|
|
371
|
-
/**
|
|
372
|
-
* Gregorian date helper functions.
|
|
373
|
-
*/
|
|
374
|
-
exports.greg = void 0;
|
|
375
|
-
(function (greg) {
|
|
376
|
-
/**
|
|
377
|
-
* Long names of the Gregorian months (1='January', 12='December')
|
|
378
|
-
* @readonly
|
|
379
|
-
* @type {string[]}
|
|
380
|
-
*/
|
|
381
|
-
greg.monthNames = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
382
|
-
/**
|
|
383
|
-
* Returns true if the Gregorian year is a leap year
|
|
384
|
-
* @param {number} year Gregorian year
|
|
385
|
-
* @return {boolean}
|
|
386
|
-
*/
|
|
387
|
-
function isLeapYear(year) {
|
|
388
|
-
return !(year % 4) && (!!(year % 100) || !(year % 400));
|
|
389
|
-
}
|
|
390
|
-
greg.isLeapYear = isLeapYear;
|
|
391
|
-
/**
|
|
392
|
-
* Number of days in the Gregorian month for given year
|
|
393
|
-
* @param {number} month Gregorian month (1=January, 12=December)
|
|
394
|
-
* @param {number} year Gregorian year
|
|
395
|
-
* @return {number}
|
|
396
|
-
*/
|
|
397
|
-
function daysInMonth(month, year) {
|
|
398
|
-
// 1 based months
|
|
399
|
-
return monthLengths[+isLeapYear(year)][month];
|
|
400
|
-
}
|
|
401
|
-
greg.daysInMonth = daysInMonth;
|
|
402
|
-
/**
|
|
403
|
-
* Returns true if the object is a Javascript Date
|
|
404
|
-
* @param {Object} obj
|
|
405
|
-
* @return {boolean}
|
|
406
|
-
*/
|
|
407
|
-
function isDate(obj) {
|
|
408
|
-
return typeof obj === 'object' && Date.prototype.isPrototypeOf(obj);
|
|
409
|
-
}
|
|
410
|
-
greg.isDate = isDate;
|
|
411
|
-
/**
|
|
412
|
-
* @private
|
|
413
|
-
* @param abs - R.D. number of days
|
|
414
|
-
*/
|
|
415
|
-
function yearFromFixed(abs) {
|
|
416
|
-
const l0 = abs - 1;
|
|
417
|
-
const n400 = quotient(l0, 146097);
|
|
418
|
-
const d1 = mod$1(l0, 146097);
|
|
419
|
-
const n100 = quotient(d1, 36524);
|
|
420
|
-
const d2 = mod$1(d1, 36524);
|
|
421
|
-
const n4 = quotient(d2, 1461);
|
|
422
|
-
const d3 = mod$1(d2, 1461);
|
|
423
|
-
const n1 = quotient(d3, 365);
|
|
424
|
-
const year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
425
|
-
return n100 != 4 && n1 != 4 ? year + 1 : year;
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* @private
|
|
429
|
-
* @param year
|
|
430
|
-
* @param month (1-12)
|
|
431
|
-
* @param day (1-31)
|
|
432
|
-
*/
|
|
433
|
-
function toFixed(year, month, day) {
|
|
434
|
-
const py = year - 1;
|
|
435
|
-
return 365 * py + quotient(py, 4) - quotient(py, 100) + quotient(py, 400) + quotient(367 * month - 362, 12) + (month <= 2 ? 0 : isLeapYear(year) ? -1 : -2) + day;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Converts Gregorian date to absolute R.D. (Rata Die) days
|
|
439
|
-
* @param {Date} date Gregorian date
|
|
440
|
-
* @return {number}
|
|
441
|
-
*/
|
|
442
|
-
function greg2abs(date) {
|
|
443
|
-
if (!isDate(date)) {
|
|
444
|
-
throw new TypeError(`Argument not a Date: ${date}`);
|
|
445
|
-
}
|
|
446
|
-
const abs = toFixed(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
447
|
-
/*
|
|
448
|
-
if (abs < ABS_14SEP1752 && abs > ABS_2SEP1752) {
|
|
449
|
-
throw new RangeError(`Invalid Date: ${date}`);
|
|
450
|
-
}
|
|
451
|
-
*/
|
|
452
|
-
return abs;
|
|
453
|
-
}
|
|
454
|
-
greg.greg2abs = greg2abs;
|
|
109
|
+
greg.greg2abs = greg2abs;
|
|
455
110
|
/**
|
|
456
111
|
* Converts from Rata Die (R.D. number) to Gregorian date.
|
|
457
112
|
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
|
|
@@ -850,106 +505,443 @@ function monthFromName(monthName) {
|
|
|
850
505
|
case 'ש':
|
|
851
506
|
return months.TISHREI;
|
|
852
507
|
}
|
|
853
|
-
break;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
throw new RangeError(`Unable to parse month name: ${monthName}`);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const NISAN$3 = months.NISAN;
|
|
514
|
+
const CHESHVAN = months.CHESHVAN;
|
|
515
|
+
const KISLEV$1 = months.KISLEV;
|
|
516
|
+
const TEVET$1 = months.TEVET;
|
|
517
|
+
const SHVAT = months.SHVAT;
|
|
518
|
+
const ADAR_I$1 = months.ADAR_I;
|
|
519
|
+
const ADAR_II = months.ADAR_II;
|
|
520
|
+
/**
|
|
521
|
+
* Returns true if the object is a Javascript Date
|
|
522
|
+
* @private
|
|
523
|
+
* @param {Object} obj
|
|
524
|
+
*/
|
|
525
|
+
function isSimpleHebrewDate(obj) {
|
|
526
|
+
return typeof obj === 'object' && obj !== null && typeof obj.yy === 'number' && typeof obj.mm === 'number' && typeof obj.dd === 'number';
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* @private
|
|
530
|
+
*/
|
|
531
|
+
function toSimpleHebrewDate(obj) {
|
|
532
|
+
if (isSimpleHebrewDate(obj)) {
|
|
533
|
+
return obj;
|
|
534
|
+
} else if (typeof obj === 'number') {
|
|
535
|
+
return abs2hebrew(obj);
|
|
536
|
+
} else if (exports.greg.isDate(obj)) {
|
|
537
|
+
const abs = exports.greg.greg2abs(obj);
|
|
538
|
+
return abs2hebrew(abs);
|
|
539
|
+
} else {
|
|
540
|
+
throw new TypeError(`Argument not a Date: ${obj}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function getYahrzeitHD(hyear, date) {
|
|
544
|
+
let hDeath = toSimpleHebrewDate(date);
|
|
545
|
+
if (hyear <= hDeath.yy) {
|
|
546
|
+
// Hebrew year ${hyear} occurs on or before original date in ${hDeath.yy}
|
|
547
|
+
return undefined;
|
|
548
|
+
}
|
|
549
|
+
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hDeath.yy + 1)) {
|
|
550
|
+
// If it's Heshvan 30 it depends on the first anniversary;
|
|
551
|
+
// if that was not Heshvan 30, use the day before Kislev 1.
|
|
552
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, KISLEV$1, 1) - 1);
|
|
553
|
+
} else if (hDeath.mm == KISLEV$1 && hDeath.dd == 30 && shortKislev(hDeath.yy + 1)) {
|
|
554
|
+
// If it's Kislev 30 it depends on the first anniversary;
|
|
555
|
+
// if that was not Kislev 30, use the day before Teveth 1.
|
|
556
|
+
hDeath = abs2hebrew(hebrew2abs(hyear, TEVET$1, 1) - 1);
|
|
557
|
+
} else if (hDeath.mm == ADAR_II) {
|
|
558
|
+
// If it's Adar II, use the same day in last month of year (Adar or Adar II).
|
|
559
|
+
hDeath.mm = monthsInYear(hyear);
|
|
560
|
+
} else if (hDeath.mm == ADAR_I$1 && hDeath.dd == 30 && !isLeapYear(hyear)) {
|
|
561
|
+
// If it's the 30th in Adar I and year is not a leap year
|
|
562
|
+
// (so Adar has only 29 days), use the last day in Shevat.
|
|
563
|
+
hDeath.dd = 30;
|
|
564
|
+
hDeath.mm = SHVAT;
|
|
565
|
+
}
|
|
566
|
+
// In all other cases, use the normal anniversary of the date of death.
|
|
567
|
+
// advance day to rosh chodesh if needed
|
|
568
|
+
if (hDeath.mm == CHESHVAN && hDeath.dd == 30 && !longCheshvan(hyear)) {
|
|
569
|
+
hDeath.mm = KISLEV$1;
|
|
570
|
+
hDeath.dd = 1;
|
|
571
|
+
} else if (hDeath.mm == KISLEV$1 && hDeath.dd == 30 && shortKislev(hyear)) {
|
|
572
|
+
hDeath.mm = TEVET$1;
|
|
573
|
+
hDeath.dd = 1;
|
|
574
|
+
}
|
|
575
|
+
hDeath.yy = hyear;
|
|
576
|
+
return hDeath;
|
|
577
|
+
}
|
|
578
|
+
function getBirthdayHD(hyear, date) {
|
|
579
|
+
const orig = toSimpleHebrewDate(date);
|
|
580
|
+
const origYear = orig.yy;
|
|
581
|
+
if (hyear === origYear) {
|
|
582
|
+
return orig;
|
|
583
|
+
} else if (hyear < origYear) {
|
|
584
|
+
// Hebrew year ${hyear} occurs on or before original date in ${origYear}
|
|
585
|
+
return undefined;
|
|
586
|
+
}
|
|
587
|
+
const isOrigLeap = isLeapYear(origYear);
|
|
588
|
+
let month = orig.mm;
|
|
589
|
+
let day = orig.dd;
|
|
590
|
+
if (month == ADAR_I$1 && !isOrigLeap || month == ADAR_II && isOrigLeap) {
|
|
591
|
+
month = monthsInYear(hyear);
|
|
592
|
+
} else if (month == CHESHVAN && day == 30 && !longCheshvan(hyear)) {
|
|
593
|
+
month = KISLEV$1;
|
|
594
|
+
day = 1;
|
|
595
|
+
} else if (month == KISLEV$1 && day == 30 && shortKislev(hyear)) {
|
|
596
|
+
month = TEVET$1;
|
|
597
|
+
day = 1;
|
|
598
|
+
} else if (month == ADAR_I$1 && day == 30 && isOrigLeap && !isLeapYear(hyear)) {
|
|
599
|
+
month = NISAN$3;
|
|
600
|
+
day = 1;
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
yy: hyear,
|
|
604
|
+
mm: month,
|
|
605
|
+
dd: day
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const GERESH = '׳';
|
|
610
|
+
const GERSHAYIM = '״';
|
|
611
|
+
const alefbet = {
|
|
612
|
+
'א': 1,
|
|
613
|
+
'ב': 2,
|
|
614
|
+
'ג': 3,
|
|
615
|
+
'ד': 4,
|
|
616
|
+
'ה': 5,
|
|
617
|
+
'ו': 6,
|
|
618
|
+
'ז': 7,
|
|
619
|
+
'ח': 8,
|
|
620
|
+
'ט': 9,
|
|
621
|
+
'י': 10,
|
|
622
|
+
'כ': 20,
|
|
623
|
+
'ל': 30,
|
|
624
|
+
'מ': 40,
|
|
625
|
+
'נ': 50,
|
|
626
|
+
'ס': 60,
|
|
627
|
+
'ע': 70,
|
|
628
|
+
'פ': 80,
|
|
629
|
+
'צ': 90,
|
|
630
|
+
'ק': 100,
|
|
631
|
+
'ר': 200,
|
|
632
|
+
'ש': 300,
|
|
633
|
+
'ת': 400
|
|
634
|
+
};
|
|
635
|
+
const heb2num = new Map();
|
|
636
|
+
const num2heb = new Map();
|
|
637
|
+
for (const [key, val] of Object.entries(alefbet)) {
|
|
638
|
+
heb2num.set(key, val);
|
|
639
|
+
num2heb.set(val, key);
|
|
640
|
+
}
|
|
641
|
+
function num2digits(num) {
|
|
642
|
+
const digits = [];
|
|
643
|
+
while (num > 0) {
|
|
644
|
+
if (num === 15 || num === 16) {
|
|
645
|
+
digits.push(9);
|
|
646
|
+
digits.push(num - 9);
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
let incr = 100;
|
|
650
|
+
let i;
|
|
651
|
+
for (i = 400; i > num; i -= incr) {
|
|
652
|
+
if (i === incr) {
|
|
653
|
+
incr = incr / 10;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
digits.push(i);
|
|
657
|
+
num -= i;
|
|
658
|
+
}
|
|
659
|
+
return digits;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Converts a numerical value to a string of Hebrew letters.
|
|
663
|
+
*
|
|
664
|
+
* When specifying years of the Hebrew calendar in the present millennium,
|
|
665
|
+
* we omit the thousands (which is presently 5 [ה]).
|
|
666
|
+
* @example
|
|
667
|
+
* gematriya(5774) // 'תשע״ד' - cropped to 774
|
|
668
|
+
* gematriya(25) // 'כ״ה'
|
|
669
|
+
* gematriya(60) // 'ס׳'
|
|
670
|
+
* gematriya(3761) // 'ג׳תשס״א'
|
|
671
|
+
* gematriya(1123) // 'א׳קכ״ג'
|
|
672
|
+
* @param {number} num
|
|
673
|
+
* @return {string}
|
|
674
|
+
*/
|
|
675
|
+
function gematriya(num) {
|
|
676
|
+
const num0 = num;
|
|
677
|
+
const num1 = parseInt(num0, 10);
|
|
678
|
+
if (!num1) {
|
|
679
|
+
throw new TypeError(`invalid parameter to gematriya ${num}`);
|
|
680
|
+
}
|
|
681
|
+
let str = '';
|
|
682
|
+
const thousands = Math.floor(num1 / 1000);
|
|
683
|
+
if (thousands > 0 && thousands !== 5) {
|
|
684
|
+
const tdigits = num2digits(thousands);
|
|
685
|
+
for (const tdig of tdigits) {
|
|
686
|
+
str += num2heb.get(tdig);
|
|
687
|
+
}
|
|
688
|
+
str += GERESH;
|
|
689
|
+
}
|
|
690
|
+
const digits = num2digits(num1 % 1000);
|
|
691
|
+
if (digits.length == 1) {
|
|
692
|
+
return str + num2heb.get(digits[0]) + GERESH;
|
|
693
|
+
}
|
|
694
|
+
for (let i = 0; i < digits.length; i++) {
|
|
695
|
+
if (i + 1 === digits.length) {
|
|
696
|
+
str += GERSHAYIM;
|
|
697
|
+
}
|
|
698
|
+
str += num2heb.get(digits[i]);
|
|
699
|
+
}
|
|
700
|
+
return str;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Converts a string of Hebrew letters to a numerical value.
|
|
704
|
+
*
|
|
705
|
+
* Only considers the value of Hebrew letters `א` through `ת`.
|
|
706
|
+
* Ignores final Hebrew letters such as `ך` (kaf sofit) or `ם` (mem sofit)
|
|
707
|
+
* and vowels (nekudot).
|
|
708
|
+
*
|
|
709
|
+
* @param {string} str
|
|
710
|
+
* @return {number}
|
|
711
|
+
*/
|
|
712
|
+
function gematriyaStrToNum(str) {
|
|
713
|
+
let num = 0;
|
|
714
|
+
const gereshIdx = str.indexOf(GERESH);
|
|
715
|
+
if (gereshIdx !== -1 && gereshIdx !== str.length - 1) {
|
|
716
|
+
const thousands = str.substring(0, gereshIdx);
|
|
717
|
+
num += gematriyaStrToNum(thousands) * 1000;
|
|
718
|
+
str = str.substring(gereshIdx);
|
|
719
|
+
}
|
|
720
|
+
for (const ch of str) {
|
|
721
|
+
const n = heb2num.get(ch);
|
|
722
|
+
if (typeof n === 'number') {
|
|
723
|
+
num += n;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return num;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
const noopLocale = {
|
|
730
|
+
headers: {
|
|
731
|
+
'plural-forms': 'nplurals=2; plural=(n!=1);'
|
|
732
|
+
},
|
|
733
|
+
contexts: {
|
|
734
|
+
'': {}
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
const alias = {
|
|
738
|
+
'h': 'he',
|
|
739
|
+
'a': 'ashkenazi',
|
|
740
|
+
's': 'en',
|
|
741
|
+
'': 'en'
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
/** @private */
|
|
745
|
+
const locales = new Map();
|
|
746
|
+
/** @private */
|
|
747
|
+
let activeLocale = null;
|
|
748
|
+
/** @private */
|
|
749
|
+
let activeName = null;
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* A locale in Hebcal is used for translations/transliterations of
|
|
753
|
+
* holidays. `@hebcal/core` supports four locales by default
|
|
754
|
+
* * `en` - default, Sephardic transliterations (e.g. "Shabbat")
|
|
755
|
+
* * `ashkenazi` - Ashkenazi transliterations (e.g. "Shabbos")
|
|
756
|
+
* * `he` - Hebrew (e.g. "שַׁבָּת")
|
|
757
|
+
* * `he-x-NoNikud` - Hebrew without nikud (e.g. "שבת")
|
|
758
|
+
*/
|
|
759
|
+
class Locale {
|
|
760
|
+
/**
|
|
761
|
+
* Returns translation only if `locale` offers a non-empty translation for `id`.
|
|
762
|
+
* Otherwise, returns `undefined`.
|
|
763
|
+
* @param {string} id Message ID to translate
|
|
764
|
+
* @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
765
|
+
* @return {string}
|
|
766
|
+
*/
|
|
767
|
+
static lookupTranslation(id, locale) {
|
|
768
|
+
const locale0 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
769
|
+
const loc = typeof locale == 'string' && locales.get(locale0) || activeLocale;
|
|
770
|
+
const array = loc[id];
|
|
771
|
+
if (array && array.length && array[0].length) {
|
|
772
|
+
return array[0];
|
|
773
|
+
}
|
|
774
|
+
return undefined;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* By default, if no translation was found, returns `id`.
|
|
779
|
+
* @param {string} id Message ID to translate
|
|
780
|
+
* @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
781
|
+
* @return {string}
|
|
782
|
+
*/
|
|
783
|
+
static gettext(id, locale) {
|
|
784
|
+
const text = this.lookupTranslation(id, locale);
|
|
785
|
+
if (typeof text == 'undefined') {
|
|
786
|
+
return id;
|
|
787
|
+
}
|
|
788
|
+
return text;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Register locale translations.
|
|
793
|
+
* @param {string} locale Locale name (i.e.: `'he'`, `'fr'`)
|
|
794
|
+
* @param {LocaleData} data parsed data from a `.po` file.
|
|
795
|
+
*/
|
|
796
|
+
static addLocale(locale, data) {
|
|
797
|
+
if (typeof locale !== 'string') {
|
|
798
|
+
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
799
|
+
}
|
|
800
|
+
if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
|
|
801
|
+
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
802
|
+
}
|
|
803
|
+
locales.set(locale.toLowerCase(), data.contexts['']);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Adds a translation to `locale`, replacing any previous translation.
|
|
808
|
+
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
|
|
809
|
+
* @param {string} id Message ID to translate
|
|
810
|
+
* @param {string} translation Translation text
|
|
811
|
+
*/
|
|
812
|
+
static addTranslation(locale, id, translation) {
|
|
813
|
+
if (typeof locale !== 'string') {
|
|
814
|
+
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
815
|
+
}
|
|
816
|
+
const locale0 = locale.toLowerCase();
|
|
817
|
+
const loc = locales.get(locale0);
|
|
818
|
+
if (!loc) {
|
|
819
|
+
throw new TypeError(`Unknown locale: ${locale}`);
|
|
820
|
+
}
|
|
821
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
822
|
+
throw new TypeError(`Invalid id: ${id}`);
|
|
823
|
+
}
|
|
824
|
+
const isArray = Array.isArray(translation);
|
|
825
|
+
if (isArray) {
|
|
826
|
+
const t0 = translation[0];
|
|
827
|
+
if (typeof t0 !== 'string' || t0.length === 0) {
|
|
828
|
+
throw new TypeError(`Invalid translation array: ${translation}`);
|
|
829
|
+
}
|
|
830
|
+
} else if (typeof translation !== 'string') {
|
|
831
|
+
throw new TypeError(`Invalid translation: ${translation}`);
|
|
832
|
+
}
|
|
833
|
+
loc[id] = isArray ? translation : [translation];
|
|
854
834
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
* @private
|
|
875
|
-
*/
|
|
876
|
-
function toSimpleHebrewDate(obj) {
|
|
877
|
-
if (isSimpleHebrewDate(obj)) {
|
|
878
|
-
return obj;
|
|
879
|
-
} else if (typeof obj === 'number') {
|
|
880
|
-
return abs2hebrew(obj);
|
|
881
|
-
} else if (exports.greg.isDate(obj)) {
|
|
882
|
-
const abs = exports.greg.greg2abs(obj);
|
|
883
|
-
return abs2hebrew(abs);
|
|
884
|
-
} else {
|
|
885
|
-
throw new TypeError(`Argument not a Date: ${obj}`);
|
|
835
|
+
/**
|
|
836
|
+
* Adds multiple translations to `locale`, replacing any previous translations.
|
|
837
|
+
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`).
|
|
838
|
+
* @param {LocaleData} data parsed data from a `.po` file.
|
|
839
|
+
*/
|
|
840
|
+
static addTranslations(locale, data) {
|
|
841
|
+
if (typeof locale !== 'string') {
|
|
842
|
+
throw new TypeError(`Invalid locale name: ${locale}`);
|
|
843
|
+
}
|
|
844
|
+
const locale0 = locale.toLowerCase();
|
|
845
|
+
const loc = locales.get(locale0);
|
|
846
|
+
if (!loc) {
|
|
847
|
+
throw new TypeError(`Unknown locale: ${locale}`);
|
|
848
|
+
}
|
|
849
|
+
if (typeof data.contexts !== 'object' || typeof data.contexts[''] !== 'object') {
|
|
850
|
+
throw new TypeError(`Locale '${locale}' invalid compact format`);
|
|
851
|
+
}
|
|
852
|
+
const ctx = data.contexts[''];
|
|
853
|
+
Object.assign(loc, ctx);
|
|
886
854
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
855
|
+
/**
|
|
856
|
+
* Activates a locale. Throws an error if the locale has not been previously added.
|
|
857
|
+
* After setting the locale to be used, all strings marked for translations
|
|
858
|
+
* will be represented by the corresponding translation in the specified locale.
|
|
859
|
+
* @param {string} locale Locale name (i.e: `'he'`, `'fr'`)
|
|
860
|
+
* @return {LocaleData}
|
|
861
|
+
*/
|
|
862
|
+
static useLocale(locale) {
|
|
863
|
+
const locale0 = locale.toLowerCase();
|
|
864
|
+
const obj = locales.get(locale0);
|
|
865
|
+
if (!obj) {
|
|
866
|
+
throw new RangeError(`Locale '${locale}' not found`);
|
|
867
|
+
}
|
|
868
|
+
activeName = alias[locale0] || locale0;
|
|
869
|
+
activeLocale = obj;
|
|
870
|
+
return activeLocale;
|
|
893
871
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
hDeath = abs2hebrew(hebrew2abs(hyear, TEVET$1, 1) - 1);
|
|
902
|
-
} else if (hDeath.mm == ADAR_II) {
|
|
903
|
-
// If it's Adar II, use the same day in last month of year (Adar or Adar II).
|
|
904
|
-
hDeath.mm = monthsInYear(hyear);
|
|
905
|
-
} else if (hDeath.mm == ADAR_I$1 && hDeath.dd == 30 && !isLeapYear(hyear)) {
|
|
906
|
-
// If it's the 30th in Adar I and year is not a leap year
|
|
907
|
-
// (so Adar has only 29 days), use the last day in Shevat.
|
|
908
|
-
hDeath.dd = 30;
|
|
909
|
-
hDeath.mm = SHVAT;
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* Returns the name of the active locale (i.e. 'he', 'ashkenazi', 'fr')
|
|
875
|
+
* @return {string}
|
|
876
|
+
*/
|
|
877
|
+
static getLocaleName() {
|
|
878
|
+
return activeName;
|
|
910
879
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Returns the names of registered locales
|
|
883
|
+
* @return {string[]}
|
|
884
|
+
*/
|
|
885
|
+
static getLocaleNames() {
|
|
886
|
+
const keys = Array.from(locales.keys());
|
|
887
|
+
return keys.sort((a, b) => a.localeCompare(b));
|
|
919
888
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* @param {number} n
|
|
892
|
+
* @param {string} [locale] Optional locale name (i.e: `'he'`, `'fr'`). Defaults to active locale.
|
|
893
|
+
* @return {string}
|
|
894
|
+
*/
|
|
895
|
+
static ordinal(n, locale) {
|
|
896
|
+
const locale1 = locale === null || locale === void 0 ? void 0 : locale.toLowerCase();
|
|
897
|
+
const locale0 = locale1 || activeName;
|
|
898
|
+
if (!locale0) {
|
|
899
|
+
return this.getEnOrdinal(n);
|
|
900
|
+
}
|
|
901
|
+
switch (locale0) {
|
|
902
|
+
case 'en':
|
|
903
|
+
case 's':
|
|
904
|
+
case 'a':
|
|
905
|
+
case 'ashkenazi':
|
|
906
|
+
case 'ashkenazi_litvish':
|
|
907
|
+
case 'ashkenazi_poylish':
|
|
908
|
+
case 'ashkenazi_standard':
|
|
909
|
+
return this.getEnOrdinal(n);
|
|
910
|
+
case 'es':
|
|
911
|
+
return n + 'º';
|
|
912
|
+
case 'h':
|
|
913
|
+
case 'he':
|
|
914
|
+
case 'he-x-nonikud':
|
|
915
|
+
return String(n);
|
|
916
|
+
default:
|
|
917
|
+
return n + '.';
|
|
918
|
+
}
|
|
931
919
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* @private
|
|
923
|
+
* @param {number} n
|
|
924
|
+
* @return {string}
|
|
925
|
+
*/
|
|
926
|
+
static getEnOrdinal(n) {
|
|
927
|
+
const s = ['th', 'st', 'nd', 'rd'];
|
|
928
|
+
const v = n % 100;
|
|
929
|
+
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* Removes nekudot from Hebrew string
|
|
934
|
+
* @param {string} str
|
|
935
|
+
* @return {string}
|
|
936
|
+
*/
|
|
937
|
+
static hebrewStripNikkud(str) {
|
|
938
|
+
return str.replace(/[\u0590-\u05bd]/g, '').replace(/[\u05bf-\u05c7]/g, '');
|
|
946
939
|
}
|
|
947
|
-
return {
|
|
948
|
-
yy: hyear,
|
|
949
|
-
mm: month,
|
|
950
|
-
dd: day
|
|
951
|
-
};
|
|
952
940
|
}
|
|
941
|
+
Locale.addLocale('en', noopLocale);
|
|
942
|
+
Locale.addLocale('s', noopLocale);
|
|
943
|
+
Locale.addLocale('', noopLocale);
|
|
944
|
+
Locale.useLocale('en');
|
|
953
945
|
|
|
954
946
|
/**
|
|
955
947
|
* @private
|
|
@@ -1784,7 +1776,7 @@ class Event {
|
|
|
1784
1776
|
this.desc = desc;
|
|
1785
1777
|
this.mask = +mask;
|
|
1786
1778
|
if (typeof attrs === 'object' && attrs !== null) {
|
|
1787
|
-
Object.
|
|
1779
|
+
Object.assign(this, attrs);
|
|
1788
1780
|
}
|
|
1789
1781
|
}
|
|
1790
1782
|
/**
|
|
@@ -6574,10 +6566,10 @@ class Location extends GeoLocation {
|
|
|
6574
6566
|
return true;
|
|
6575
6567
|
}
|
|
6576
6568
|
}
|
|
6577
|
-
|
|
6569
|
+
for (const city of classicCities0) {
|
|
6578
6570
|
const location = new Location(city[2], city[3], city[1] == 'IL', city[4], city[0], city[1], undefined, city[5]);
|
|
6579
6571
|
Location.addLocation(location.getName(), location);
|
|
6580
|
-
}
|
|
6572
|
+
}
|
|
6581
6573
|
|
|
6582
6574
|
const _formatters = new Map();
|
|
6583
6575
|
|
|
@@ -9490,40 +9482,7 @@ const MINOR_HOLIDAY$1 = flags.MINOR_HOLIDAY;
|
|
|
9490
9482
|
const EREV$1 = flags.EREV;
|
|
9491
9483
|
// const CHOL_HAMOED = flags.CHOL_HAMOED;
|
|
9492
9484
|
|
|
9493
|
-
|
|
9494
|
-
* Avoid dependency on ES6 Map object
|
|
9495
|
-
* @private
|
|
9496
|
-
*/
|
|
9497
|
-
class SimpleMap {
|
|
9498
|
-
/**
|
|
9499
|
-
* @param {string} key
|
|
9500
|
-
* @return {boolean}
|
|
9501
|
-
*/
|
|
9502
|
-
has(key) {
|
|
9503
|
-
return typeof this[key] !== 'undefined';
|
|
9504
|
-
}
|
|
9505
|
-
/**
|
|
9506
|
-
* @param {string} key
|
|
9507
|
-
* @return {any}
|
|
9508
|
-
*/
|
|
9509
|
-
get(key) {
|
|
9510
|
-
return this[key];
|
|
9511
|
-
}
|
|
9512
|
-
/**
|
|
9513
|
-
* @param {string} key
|
|
9514
|
-
* @param {any} val
|
|
9515
|
-
*/
|
|
9516
|
-
set(key, val) {
|
|
9517
|
-
this[key] = val;
|
|
9518
|
-
}
|
|
9519
|
-
/**
|
|
9520
|
-
* @return {string[]}
|
|
9521
|
-
*/
|
|
9522
|
-
keys() {
|
|
9523
|
-
return Object.keys(this);
|
|
9524
|
-
}
|
|
9525
|
-
}
|
|
9526
|
-
const sedraCache = new SimpleMap();
|
|
9485
|
+
const sedraCache = new Map();
|
|
9527
9486
|
|
|
9528
9487
|
/**
|
|
9529
9488
|
* @private
|
|
@@ -9567,16 +9526,15 @@ function getHolidaysForYear_(year) {
|
|
|
9567
9526
|
}
|
|
9568
9527
|
const RH = new HDate(1, TISHREI$1, year);
|
|
9569
9528
|
const pesach = new HDate(15, NISAN$1, year);
|
|
9570
|
-
const
|
|
9529
|
+
const map = new Map();
|
|
9571
9530
|
// eslint-disable-next-line require-jsdoc
|
|
9572
9531
|
function add() {
|
|
9573
9532
|
for (var _len = arguments.length, events = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
9574
9533
|
events[_key] = arguments[_key];
|
|
9575
9534
|
}
|
|
9576
|
-
|
|
9577
|
-
events.forEach(ev => {
|
|
9535
|
+
for (const ev of events) {
|
|
9578
9536
|
const key = ev.date.toString();
|
|
9579
|
-
const arr =
|
|
9537
|
+
const arr = map.get(key);
|
|
9580
9538
|
if (typeof arr === 'object') {
|
|
9581
9539
|
if (arr[0].getFlags() & flags.EREV) {
|
|
9582
9540
|
arr.unshift(ev);
|
|
@@ -9584,17 +9542,17 @@ function getHolidaysForYear_(year) {
|
|
|
9584
9542
|
arr.push(ev);
|
|
9585
9543
|
}
|
|
9586
9544
|
} else {
|
|
9587
|
-
|
|
9545
|
+
map.set(key, [ev]);
|
|
9588
9546
|
}
|
|
9589
|
-
}
|
|
9547
|
+
}
|
|
9590
9548
|
}
|
|
9591
|
-
|
|
9549
|
+
for (const h of staticHolidays) {
|
|
9592
9550
|
const hd = new HDate(h.dd, h.mm, year);
|
|
9593
9551
|
const ev = new HolidayEvent(hd, h.desc, h.flags);
|
|
9594
9552
|
if (h.emoji) ev.emoji = h.emoji;
|
|
9595
9553
|
if (h.chmDay) ev.cholHaMoedDay = h.chmDay;
|
|
9596
9554
|
add(ev);
|
|
9597
|
-
}
|
|
9555
|
+
}
|
|
9598
9556
|
|
|
9599
9557
|
// standard holidays that don't shift based on year
|
|
9600
9558
|
add(new RoshHashanaEvent(RH, year, CHAG | LIGHT_CANDLES_TZEIS$1));
|
|
@@ -9646,7 +9604,7 @@ function getHolidaysForYear_(year) {
|
|
|
9646
9604
|
if (yomHaZikaronDt) {
|
|
9647
9605
|
add(new HolidayEvent(yomHaZikaronDt, 'Yom HaZikaron', MODERN_HOLIDAY$1, emojiIsraelFlag), new HolidayEvent(yomHaZikaronDt.next(), 'Yom HaAtzma\'ut', MODERN_HOLIDAY$1, emojiIsraelFlag));
|
|
9648
9606
|
}
|
|
9649
|
-
|
|
9607
|
+
for (const h of staticModernHolidays) {
|
|
9650
9608
|
if (year >= h.firstYear) {
|
|
9651
9609
|
let hd = new HDate(h.dd, h.mm, year);
|
|
9652
9610
|
const dow = hd.getDay();
|
|
@@ -9664,7 +9622,7 @@ function getHolidaysForYear_(year) {
|
|
|
9664
9622
|
}
|
|
9665
9623
|
add(ev);
|
|
9666
9624
|
}
|
|
9667
|
-
}
|
|
9625
|
+
}
|
|
9668
9626
|
let tamuz17 = new HDate(17, TAMUZ, year);
|
|
9669
9627
|
let tamuz17attrs;
|
|
9670
9628
|
if (tamuz17.getDay() == SAT$1) {
|
|
@@ -9735,8 +9693,8 @@ function getHolidaysForYear_(year) {
|
|
|
9735
9693
|
emoji: '☀️'
|
|
9736
9694
|
}));
|
|
9737
9695
|
}
|
|
9738
|
-
yearCache.set(year,
|
|
9739
|
-
return
|
|
9696
|
+
yearCache.set(year, map);
|
|
9697
|
+
return map;
|
|
9740
9698
|
}
|
|
9741
9699
|
|
|
9742
9700
|
/**
|
|
@@ -9803,7 +9761,7 @@ class DailyLearning {
|
|
|
9803
9761
|
}
|
|
9804
9762
|
}
|
|
9805
9763
|
|
|
9806
|
-
const version="5.0.
|
|
9764
|
+
const version="5.0.2";
|
|
9807
9765
|
|
|
9808
9766
|
const headers$1={"plural-forms":"nplurals=2; plural=(n > 1);"};const contexts$1={"":{Shabbat:["Shabbos"],"Achrei Mot":["Achrei Mos"],Bechukotai:["Bechukosai"],"Beha'alotcha":["Beha'aloscha"],Bereshit:["Bereshis"],Chukat:["Chukas"],"Erev Shavuot":["Erev Shavuos"],"Erev Sukkot":["Erev Sukkos"],"Ki Tavo":["Ki Savo"],"Ki Teitzei":["Ki Seitzei"],"Ki Tisa":["Ki Sisa"],Matot:["Matos"],"Purim Katan":["Purim Koton"],"Shabbat Chazon":["Shabbos Chazon"],"Shabbat HaChodesh":["Shabbos HaChodesh"],"Shabbat HaGadol":["Shabbos HaGadol"],"Shabbat Nachamu":["Shabbos Nachamu"],"Shabbat Parah":["Shabbos Parah"],"Shabbat Shekalim":["Shabbos Shekalim"],"Shabbat Shuva":["Shabbos Shuvah"],"Shabbat Zachor":["Shabbos Zachor"],Shavuot:["Shavuos"],"Shavuot I":["Shavuos I"],"Shavuot II":["Shavuos II"],Shemot:["Shemos"],"Shmini Atzeret":["Shmini Atzeres"],"Simchat Torah":["Simchas Torah"],Sukkot:["Sukkos"],"Sukkot I":["Sukkos I"],"Sukkot II":["Sukkos II"],"Sukkot II (CH''M)":["Sukkos II (CH''M)"],"Sukkot III (CH''M)":["Sukkos III (CH''M)"],"Sukkot IV (CH''M)":["Sukkos IV (CH''M)"],"Sukkot V (CH''M)":["Sukkos V (CH''M)"],"Sukkot VI (CH''M)":["Sukkos VI (CH''M)"],"Sukkot VII (Hoshana Raba)":["Sukkos VII (Hoshana Raba)"],"Ta'anit Bechorot":["Ta'anis Bechoros"],"Ta'anit Esther":["Ta'anis Esther"],Toldot:["Toldos"],Vaetchanan:["Vaeschanan"],Yitro:["Yisro"],"Vezot Haberakhah":["Vezos Haberakhah"],Parashat:["Parshas"],"Leil Selichot":["Leil Selichos"],"Shabbat Mevarchim Chodesh":["Shabbos Mevorchim Chodesh"],"Shabbat Shirah":["Shabbos Shirah"],Tevet:["Teves"],"Asara B'Tevet":["Asara B'Teves"],"Alot HaShachar":["Alos HaShachar"],"Kriat Shema, sof zeman":["Krias Shema, sof zman"],"Tefilah, sof zeman":["Tefilah, sof zman"],"Kriat Shema, sof zeman (MGA)":["Krias Shema, sof zman (MGA)"],"Tefilah, sof zeman (MGA)":["Tefilah, sof zman (MGA)"],"Chatzot HaLailah":["Chatzos HaLailah"],"Chatzot hayom":["Chatzos"],"Tzeit HaKochavim":["Tzeis HaKochavim"],"Birkat Hachamah":["Birkas Hachamah"],"Shushan Purim Katan":["Shushan Purim Koton"]}};var poAshkenazi = {headers:headers$1,contexts:contexts$1};
|
|
9809
9767
|
|
|
@@ -9816,9 +9774,9 @@ Locale.addLocale('he', poHe);
|
|
|
9816
9774
|
Locale.addLocale('h', poHe);
|
|
9817
9775
|
const heStrs = poHe.contexts[''];
|
|
9818
9776
|
const heNoNikud = {};
|
|
9819
|
-
Object.
|
|
9820
|
-
heNoNikud[key] = [Locale.hebrewStripNikkud(
|
|
9821
|
-
}
|
|
9777
|
+
for (const [key, val] of Object.entries(heStrs)) {
|
|
9778
|
+
heNoNikud[key] = [Locale.hebrewStripNikkud(val[0])];
|
|
9779
|
+
}
|
|
9822
9780
|
const poHeNoNikud = {
|
|
9823
9781
|
headers: poHe.headers,
|
|
9824
9782
|
contexts: {
|
|
@@ -10611,24 +10569,12 @@ const RECOGNIZED_OPTIONS = {
|
|
|
10611
10569
|
* @param {CalOptions} options
|
|
10612
10570
|
*/
|
|
10613
10571
|
function warnUnrecognizedOptions(options) {
|
|
10614
|
-
Object.keys(options)
|
|
10572
|
+
for (const k of Object.keys(options)) {
|
|
10615
10573
|
if (typeof RECOGNIZED_OPTIONS[k] === 'undefined' && !unrecognizedAlreadyWarned.has(k)) {
|
|
10616
10574
|
console.warn(`Ignoring unrecognized HebrewCalendar option: ${k}`);
|
|
10617
10575
|
unrecognizedAlreadyWarned.add(k);
|
|
10618
10576
|
}
|
|
10619
|
-
}
|
|
10620
|
-
}
|
|
10621
|
-
|
|
10622
|
-
/**
|
|
10623
|
-
* A bit like Object.assign(), but just a shallow copy
|
|
10624
|
-
* @private
|
|
10625
|
-
* @param {any} target
|
|
10626
|
-
* @param {any} source
|
|
10627
|
-
* @return {any}
|
|
10628
|
-
*/
|
|
10629
|
-
function shallowCopy(target, source) {
|
|
10630
|
-
Object.keys(source).forEach(k => target[k] = source[k]);
|
|
10631
|
-
return target;
|
|
10577
|
+
}
|
|
10632
10578
|
}
|
|
10633
10579
|
const israelCityOffset = {
|
|
10634
10580
|
'Jerusalem': 40,
|
|
@@ -10989,6 +10935,7 @@ function observedInDiaspora(ev) {
|
|
|
10989
10935
|
return ev.observedInDiaspora();
|
|
10990
10936
|
}
|
|
10991
10937
|
const yearArrayCache = new Map();
|
|
10938
|
+
const holidaysOnDate = new Map();
|
|
10992
10939
|
|
|
10993
10940
|
/**
|
|
10994
10941
|
* HebrewCalendar is the main interface to the `@hebcal/core` library.
|
|
@@ -11107,7 +11054,7 @@ class HebrewCalendar {
|
|
|
11107
11054
|
*/
|
|
11108
11055
|
static calendar() {
|
|
11109
11056
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
11110
|
-
options =
|
|
11057
|
+
options = Object.assign({}, options); // so we can modify freely
|
|
11111
11058
|
checkCandleOptions(options);
|
|
11112
11059
|
const location = options.location = options.location || defaultLocation;
|
|
11113
11060
|
const il = options.il = options.il || location.il || false;
|
|
@@ -11156,9 +11103,9 @@ class HebrewCalendar {
|
|
|
11156
11103
|
const dow = hd.getDay();
|
|
11157
11104
|
let candlesEv;
|
|
11158
11105
|
const ev = holidaysYear.get(hd.toString()) || [];
|
|
11159
|
-
|
|
11106
|
+
for (const e of ev) {
|
|
11160
11107
|
candlesEv = appendHolidayAndRelated(evts, e, options, candlesEv, dow);
|
|
11161
|
-
}
|
|
11108
|
+
}
|
|
11162
11109
|
if (options.sedrot && dow === SAT) {
|
|
11163
11110
|
const parsha0 = sedra.lookup(abs);
|
|
11164
11111
|
if (!parsha0.chag) {
|
|
@@ -11167,8 +11114,7 @@ class HebrewCalendar {
|
|
|
11167
11114
|
}
|
|
11168
11115
|
const dailyLearning = options.dailyLearning;
|
|
11169
11116
|
if (typeof dailyLearning === 'object') {
|
|
11170
|
-
Object.
|
|
11171
|
-
const val = dailyLearning[key];
|
|
11117
|
+
for (const [key, val] of Object.entries(dailyLearning)) {
|
|
11172
11118
|
if (val) {
|
|
11173
11119
|
const name = key === 'yerushalmi' ? val === 2 ? 'yerushalmi-schottenstein' : 'yerushalmi-vilna' : key;
|
|
11174
11120
|
const learningEv = DailyLearning.lookup(name, hd);
|
|
@@ -11176,7 +11122,7 @@ class HebrewCalendar {
|
|
|
11176
11122
|
evts.push(learningEv);
|
|
11177
11123
|
}
|
|
11178
11124
|
}
|
|
11179
|
-
}
|
|
11125
|
+
}
|
|
11180
11126
|
}
|
|
11181
11127
|
if (options.omer && abs >= beginOmer && abs <= endOmer) {
|
|
11182
11128
|
const omer = abs - beginOmer + 1;
|
|
@@ -11338,20 +11284,29 @@ class HebrewCalendar {
|
|
|
11338
11284
|
}
|
|
11339
11285
|
|
|
11340
11286
|
/**
|
|
11341
|
-
* Returns an array of Events on this date (or undefined if no events)
|
|
11287
|
+
* Returns an array of Events on this date (or `undefined` if no events)
|
|
11342
11288
|
* @param {HDate|Date|number} date Hebrew Date, Gregorian date, or absolute R.D. day number
|
|
11343
11289
|
* @param {boolean} [il] use the Israeli schedule for holidays
|
|
11344
11290
|
* @return {Event[]}
|
|
11345
11291
|
*/
|
|
11346
11292
|
static getHolidaysOnDate(date, il) {
|
|
11347
11293
|
const hd = HDate.isHDate(date) ? date : new HDate(date);
|
|
11294
|
+
const hdStr = hd.toString();
|
|
11295
|
+
const cacheKey = hdStr + '/' + (typeof il === 'undefined' ? 2 : il ? 1 : 0);
|
|
11296
|
+
if (holidaysOnDate.has(cacheKey)) {
|
|
11297
|
+
return holidaysOnDate.get(cacheKey);
|
|
11298
|
+
}
|
|
11348
11299
|
const yearMap = getHolidaysForYear_(hd.getFullYear());
|
|
11349
|
-
const events = yearMap.get(
|
|
11300
|
+
const events = yearMap.get(hdStr);
|
|
11301
|
+
// if il isn't a boolean return both diaspora + IL for day
|
|
11350
11302
|
if (typeof il === 'undefined' || typeof events === 'undefined') {
|
|
11303
|
+
holidaysOnDate.set(cacheKey, events);
|
|
11351
11304
|
return events;
|
|
11352
11305
|
}
|
|
11353
11306
|
const myFilter = il ? observedInIsrael : observedInDiaspora;
|
|
11354
|
-
|
|
11307
|
+
const filtered = events.filter(myFilter);
|
|
11308
|
+
holidaysOnDate.set(cacheKey, filtered);
|
|
11309
|
+
return filtered;
|
|
11355
11310
|
}
|
|
11356
11311
|
|
|
11357
11312
|
/**
|