bn-calendar 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1169 -0
- package/dist/index.d.cts +656 -0
- package/dist/index.d.mts +656 -0
- package/dist/index.mjs +1166 -0
- package/dist/types-1mlac5Hi.d.mts +313 -0
- package/dist/types-DJR_67-s.d.cts +313 -0
- package/dist/types.cjs +0 -0
- package/dist/types.d.cts +2 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +1 -0
- package/package.json +100 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1169 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/guards/primitives.js
|
|
3
|
+
function isNumber(value) {
|
|
4
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
5
|
+
}
|
|
6
|
+
function isString(value) {
|
|
7
|
+
return typeof value === "string";
|
|
8
|
+
}
|
|
9
|
+
function isInteger(value) {
|
|
10
|
+
return isNumber(value) && Number.isInteger(value);
|
|
11
|
+
}
|
|
12
|
+
function isNonEmptyString(value) {
|
|
13
|
+
return isString(value) && value?.length > 0;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/guards/non-primitives.js
|
|
17
|
+
function isArray(value) {
|
|
18
|
+
return Array.isArray(value);
|
|
19
|
+
}
|
|
20
|
+
function isObject(value) {
|
|
21
|
+
return value !== null && typeof value === "object" && !isArray(value);
|
|
22
|
+
}
|
|
23
|
+
function isObjectWithKeys(value, keys) {
|
|
24
|
+
return isObject(value) && keys?.every((key) => key in value);
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/guards/specials.js
|
|
28
|
+
function isDateString(value) {
|
|
29
|
+
return isString(value) && !isNaN(Date.parse(value));
|
|
30
|
+
}
|
|
31
|
+
function isNumericString(value) {
|
|
32
|
+
return isString(value) && value?.trim() !== "" && Number.isFinite(Number(value));
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/number/constants.js
|
|
36
|
+
const BN_DIGITS = /* @__PURE__ */ Object.freeze({
|
|
37
|
+
"০": 0,
|
|
38
|
+
"১": 1,
|
|
39
|
+
"২": 2,
|
|
40
|
+
"৩": 3,
|
|
41
|
+
"৪": 4,
|
|
42
|
+
"৫": 5,
|
|
43
|
+
"৬": 6,
|
|
44
|
+
"৭": 7,
|
|
45
|
+
"৮": 8,
|
|
46
|
+
"৯": 9
|
|
47
|
+
});
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/number/utilities.js
|
|
50
|
+
function normalizeNumber(num) {
|
|
51
|
+
return isNumber(num) ? num : isNumericString(num) ? Number(num) : void 0;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/number/convert.js
|
|
55
|
+
function banglaToDigit(bnDigit, forceNumber = true) {
|
|
56
|
+
if (!isNonEmptyString(bnDigit)) return forceNumber ? NaN : "";
|
|
57
|
+
const digitStr = bnDigit.replace(/[০১২৩৪৫৬৭৮৯]/g, (d) => String(BN_DIGITS[d]));
|
|
58
|
+
if (forceNumber) return Number(digitStr.split("").filter((dig) => !isNaN(Number(dig))).join(""));
|
|
59
|
+
return digitStr;
|
|
60
|
+
}
|
|
61
|
+
function digitToBangla(digit, preserveNonDigit = true) {
|
|
62
|
+
const banglaDigits = Object.keys(BN_DIGITS);
|
|
63
|
+
const _matchAndConvert = (value) => {
|
|
64
|
+
return value.replace(/\d/g, (dig) => banglaDigits[Number(dig)]);
|
|
65
|
+
};
|
|
66
|
+
if (isNumber(digit)) return _matchAndConvert(String(digit));
|
|
67
|
+
if (isNonEmptyString(digit)) {
|
|
68
|
+
const bnDigStr = _matchAndConvert(digit);
|
|
69
|
+
if (preserveNonDigit || isNumericString(digit)) return bnDigStr;
|
|
70
|
+
return bnDigStr.split("").filter((dig) => banglaDigits.includes(dig)).join("");
|
|
71
|
+
}
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.30.1/node_modules/nhb-toolbox/dist/esm/date/guards.js
|
|
76
|
+
function isLeapYear(year) {
|
|
77
|
+
const $year = normalizeNumber(year);
|
|
78
|
+
return $year ? $year % 4 === 0 && $year % 100 !== 0 || $year % 400 === 0 : false;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/constants.ts
|
|
82
|
+
/** Milliseconds per day */
|
|
83
|
+
const MS_PER_DAY = 864e5;
|
|
84
|
+
/** Bangla month days table for different variants */
|
|
85
|
+
const BN_MONTH_TABLES = /* @__PURE__ */ Object.freeze({
|
|
86
|
+
"revised-2019": {
|
|
87
|
+
normal: [
|
|
88
|
+
31,
|
|
89
|
+
31,
|
|
90
|
+
31,
|
|
91
|
+
31,
|
|
92
|
+
31,
|
|
93
|
+
31,
|
|
94
|
+
30,
|
|
95
|
+
30,
|
|
96
|
+
30,
|
|
97
|
+
30,
|
|
98
|
+
29,
|
|
99
|
+
30
|
|
100
|
+
],
|
|
101
|
+
leap: [
|
|
102
|
+
31,
|
|
103
|
+
31,
|
|
104
|
+
31,
|
|
105
|
+
31,
|
|
106
|
+
31,
|
|
107
|
+
31,
|
|
108
|
+
30,
|
|
109
|
+
30,
|
|
110
|
+
30,
|
|
111
|
+
30,
|
|
112
|
+
30,
|
|
113
|
+
30
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"revised-1966": {
|
|
117
|
+
normal: [
|
|
118
|
+
31,
|
|
119
|
+
31,
|
|
120
|
+
31,
|
|
121
|
+
31,
|
|
122
|
+
31,
|
|
123
|
+
30,
|
|
124
|
+
30,
|
|
125
|
+
30,
|
|
126
|
+
30,
|
|
127
|
+
30,
|
|
128
|
+
30,
|
|
129
|
+
30
|
|
130
|
+
],
|
|
131
|
+
leap: [
|
|
132
|
+
31,
|
|
133
|
+
31,
|
|
134
|
+
31,
|
|
135
|
+
31,
|
|
136
|
+
31,
|
|
137
|
+
30,
|
|
138
|
+
30,
|
|
139
|
+
30,
|
|
140
|
+
30,
|
|
141
|
+
30,
|
|
142
|
+
31,
|
|
143
|
+
30
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
/** List of Bangla season names in Bangla and English */
|
|
148
|
+
const BN_SEASONS = /* @__PURE__ */ Object.freeze([
|
|
149
|
+
{
|
|
150
|
+
bn: "গ্রীষ্ম",
|
|
151
|
+
en: "Grisma (Summer)"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
bn: "বর্ষা",
|
|
155
|
+
en: "Barsa (Monsoon)"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
bn: "শরৎ",
|
|
159
|
+
en: "Sarat (Autumn)"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
bn: "হেমন্ত",
|
|
163
|
+
en: "Hemanta (Late-Autumn)"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
bn: "শীত",
|
|
167
|
+
en: "Shhit (Winter)"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
bn: "বসন্ত",
|
|
171
|
+
en: "Basanta (Spring)"
|
|
172
|
+
}
|
|
173
|
+
]);
|
|
174
|
+
/** List of Bangla day names in Bangla and English */
|
|
175
|
+
const BN_DAYS = /* @__PURE__ */ Object.freeze([
|
|
176
|
+
{
|
|
177
|
+
bn: "রবিবার",
|
|
178
|
+
en: "Robibar (Sunday)",
|
|
179
|
+
short: "র"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
bn: "সোমবার",
|
|
183
|
+
en: "Shombar (Monday)",
|
|
184
|
+
short: "সো"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
bn: "মঙ্গলবার",
|
|
188
|
+
en: "Mongolbar (Tuesday)",
|
|
189
|
+
short: "ম"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
bn: "বুধবার",
|
|
193
|
+
en: "Budhbar (Wednesday)",
|
|
194
|
+
short: "বু"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
bn: "বৃহস্পতিবার",
|
|
198
|
+
en: "Brihoshpotibar (Thursday)",
|
|
199
|
+
short: "বৃ"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
bn: "শুক্রবার",
|
|
203
|
+
en: "Shukrobar (Friday)",
|
|
204
|
+
short: "শু"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
bn: "শনিবার",
|
|
208
|
+
en: "Shonibar (Saturday)",
|
|
209
|
+
short: "শ"
|
|
210
|
+
}
|
|
211
|
+
]);
|
|
212
|
+
/** List of Bangla month names in Bangla and English */
|
|
213
|
+
const BN_MONTHS = /* @__PURE__ */ Object.freeze([
|
|
214
|
+
{
|
|
215
|
+
bn: "বৈশাখ",
|
|
216
|
+
en: "Boishakh",
|
|
217
|
+
short: "বৈ"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
bn: "জ্যৈষ্ঠ",
|
|
221
|
+
en: "Joishtho",
|
|
222
|
+
short: "জ্য"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
bn: "আষাঢ়",
|
|
226
|
+
en: "Asharh",
|
|
227
|
+
short: "আ"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
bn: "শ্রাবণ",
|
|
231
|
+
en: "Srabon",
|
|
232
|
+
short: "শ্রা"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
bn: "ভাদ্র",
|
|
236
|
+
en: "Bhadro",
|
|
237
|
+
short: "ভা"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
bn: "আশ্বিন",
|
|
241
|
+
en: "Ashwin",
|
|
242
|
+
short: "আ"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
bn: "কার্তিক",
|
|
246
|
+
en: "Kartik",
|
|
247
|
+
short: "কা"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
bn: "অগ্রহায়ণ",
|
|
251
|
+
en: "Ogrohayon",
|
|
252
|
+
short: "অ"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
bn: "পৌষ",
|
|
256
|
+
en: "Poush",
|
|
257
|
+
short: "পৌ"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
bn: "মাঘ",
|
|
261
|
+
en: "Magh",
|
|
262
|
+
short: "মা"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
bn: "ফাল্গুন",
|
|
266
|
+
en: "Falgun",
|
|
267
|
+
short: "ফা"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
bn: "চৈত্র",
|
|
271
|
+
en: "Choitro",
|
|
272
|
+
short: "চৈ"
|
|
273
|
+
}
|
|
274
|
+
]);
|
|
275
|
+
const YEAR_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
276
|
+
"YYYY",
|
|
277
|
+
"YY",
|
|
278
|
+
"yyyy",
|
|
279
|
+
"yy"
|
|
280
|
+
]);
|
|
281
|
+
const MONTH_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
282
|
+
"M",
|
|
283
|
+
"MM",
|
|
284
|
+
"mmm",
|
|
285
|
+
"mmmm"
|
|
286
|
+
]);
|
|
287
|
+
const DATE_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
288
|
+
"DD",
|
|
289
|
+
"D",
|
|
290
|
+
"Do"
|
|
291
|
+
]);
|
|
292
|
+
const DAY_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
293
|
+
"d",
|
|
294
|
+
"dd",
|
|
295
|
+
"ddd"
|
|
296
|
+
]);
|
|
297
|
+
const HOUR_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
298
|
+
"H",
|
|
299
|
+
"HH",
|
|
300
|
+
"hh",
|
|
301
|
+
"h"
|
|
302
|
+
]);
|
|
303
|
+
const MINUTE_FORMATS = /* @__PURE__ */ Object.freeze(["mm", "m"]);
|
|
304
|
+
const SECOND_FORMATS = /* @__PURE__ */ Object.freeze(["ss", "s"]);
|
|
305
|
+
const MILLISECOND_FORMATS = /* @__PURE__ */ Object.freeze(["ms", "mss"]);
|
|
306
|
+
const TIME_FORMATS = /* @__PURE__ */ Object.freeze(["a", "A"]);
|
|
307
|
+
const EXTRA_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
308
|
+
"Z",
|
|
309
|
+
"ZZ",
|
|
310
|
+
"S",
|
|
311
|
+
"SS"
|
|
312
|
+
]);
|
|
313
|
+
const SORTED_TIME_FORMATS = /* @__PURE__ */ Object.freeze([
|
|
314
|
+
...YEAR_FORMATS,
|
|
315
|
+
...MONTH_FORMATS,
|
|
316
|
+
...DAY_FORMATS,
|
|
317
|
+
...DATE_FORMATS,
|
|
318
|
+
...HOUR_FORMATS,
|
|
319
|
+
...MINUTE_FORMATS,
|
|
320
|
+
...SECOND_FORMATS,
|
|
321
|
+
...MILLISECOND_FORMATS,
|
|
322
|
+
...TIME_FORMATS,
|
|
323
|
+
...EXTRA_FORMATS
|
|
324
|
+
].sort((a, b) => b.length - a.length));
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/helpers.ts
|
|
327
|
+
/** Core formatting logic shared by `formatDate` and `Chronos`, `BanglaCalendar` classes */
|
|
328
|
+
function _formatDateCore(format, dateComponents) {
|
|
329
|
+
const tokenRegex = new RegExp(`^(${SORTED_TIME_FORMATS.join("|")})`);
|
|
330
|
+
let result = "";
|
|
331
|
+
let i = 0;
|
|
332
|
+
while (i < format.length) {
|
|
333
|
+
if (format[i] === "[") {
|
|
334
|
+
const end = format.indexOf("]", i);
|
|
335
|
+
if (end !== -1) {
|
|
336
|
+
result += format.slice(i + 1, end);
|
|
337
|
+
i = end + 1;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const match = tokenRegex.exec(format.slice(i));
|
|
342
|
+
if (match) {
|
|
343
|
+
result += dateComponents[match[0]] ?? match[0];
|
|
344
|
+
i += match[0].length;
|
|
345
|
+
} else {
|
|
346
|
+
result += format[i];
|
|
347
|
+
i++;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
/** Check whether a Bangla year is leap by Gregorian and Bangla years and calendar variant */
|
|
353
|
+
function _isBnLeapYear(by, gy, v) {
|
|
354
|
+
return v === "revised-1966" ? by % 4 === 2 : isLeapYear(gy);
|
|
355
|
+
}
|
|
356
|
+
/** Get Bangla season name by month index (`0-11`) */
|
|
357
|
+
function _getBnSeason(month, locale) {
|
|
358
|
+
const season = BN_SEASONS[Math.floor(month / 2)];
|
|
359
|
+
return locale === "en" ? season.en : season.bn;
|
|
360
|
+
}
|
|
361
|
+
/** Extract selective unit values from {@link Date} object */
|
|
362
|
+
function _extractDateUnits(date) {
|
|
363
|
+
const month = date.getMonth();
|
|
364
|
+
return {
|
|
365
|
+
gy: date.getFullYear(),
|
|
366
|
+
$gm: month,
|
|
367
|
+
gm: month + 1,
|
|
368
|
+
gd: date.getDate(),
|
|
369
|
+
wd: date.getDay()
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
/** Get Gregorian base year from {@link Date} object for Bangla year */
|
|
373
|
+
function _getGregBaseYear(date) {
|
|
374
|
+
const { gy, gm, gd } = _extractDateUnits(date);
|
|
375
|
+
return gm < 4 || gm === 4 && gd < 14 ? gy - 1 : gy;
|
|
376
|
+
}
|
|
377
|
+
/** Get Bangla year from {@link Date} object */
|
|
378
|
+
function _getBnYear(date) {
|
|
379
|
+
return _getGregBaseYear(date) - 593;
|
|
380
|
+
}
|
|
381
|
+
/** Get timestamp in milliseconds between midnight, January 1, 1970 (UTC) and the specified {@link Date} object */
|
|
382
|
+
function _getUtcTs(date) {
|
|
383
|
+
const { gy, $gm, gd } = _extractDateUnits(date);
|
|
384
|
+
return Date.UTC(gy, $gm, gd);
|
|
385
|
+
}
|
|
386
|
+
/** Get number of days elapsed since midnight April 14, 1970 (UTC) for specific {@link Date} */
|
|
387
|
+
function _getElapsedDays(date) {
|
|
388
|
+
return Math.floor((_getUtcTs(date) - Date.UTC(_getGregBaseYear(date), 3, 14)) / MS_PER_DAY);
|
|
389
|
+
}
|
|
390
|
+
/** Get number of days elapsed since midnight April 14, 1970 (UTC) and month index for specific `Date` and Bangla calendar variant */
|
|
391
|
+
function _bnDaysMonthIdx(date, variant) {
|
|
392
|
+
const v = variant ?? "revised-2019";
|
|
393
|
+
const table = _isBnLeapYear(_getBnYear(date), date.getFullYear(), v) ? BN_MONTH_TABLES?.[v].leap : BN_MONTH_TABLES?.[v].normal;
|
|
394
|
+
let days = _getElapsedDays(date);
|
|
395
|
+
let monthIdx = 0;
|
|
396
|
+
while (days >= table[monthIdx]) {
|
|
397
|
+
days -= table[monthIdx];
|
|
398
|
+
monthIdx++;
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
days,
|
|
402
|
+
monthIdx
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Pad at the start of a string with Bangla zero (`'০'`)
|
|
407
|
+
* @param str String to pad with
|
|
408
|
+
* @param length Maximum length to pad, default is `2`
|
|
409
|
+
* @returns The padded string
|
|
410
|
+
*/
|
|
411
|
+
function _padShunno(str, length = 2) {
|
|
412
|
+
return str.padStart(length, "০");
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region src/BanglaCalendar.ts
|
|
416
|
+
/**
|
|
417
|
+
* @class Represents a date in the Bangla calendar system with support for different variants.
|
|
418
|
+
* - This class provides functionality to create, manipulate, convert dates between the Bangla and Gregorian calendar systems.
|
|
419
|
+
* - It supports two Bangla calendar variants: `'revised-2019'` (default) and `'revised-1966'`.
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* // Create from current date
|
|
423
|
+
* const today = new BanglaCalendar();
|
|
424
|
+
*
|
|
425
|
+
* // Create from Bangla date string (Bangla digit)
|
|
426
|
+
* const date0 = new BanglaCalendar('১৪৩২-১১-০৮');
|
|
427
|
+
*
|
|
428
|
+
* // Create from Gregorian date
|
|
429
|
+
* const date1 = new BanglaCalendar('2023-04-14'); // Latin digit
|
|
430
|
+
* const date2 = new BanglaCalendar(new Date('2023-04-14')); // Date object
|
|
431
|
+
*
|
|
432
|
+
* // Create with specific Bangla date using Latin digits
|
|
433
|
+
* const date3 = new BanglaCalendar(1430, 1, 1);
|
|
434
|
+
*
|
|
435
|
+
* // Create with specific Bangla date using Bangla digits
|
|
436
|
+
* const date4 = new BanglaCalendar('১৪৩০', '১', '১');
|
|
437
|
+
*
|
|
438
|
+
* // Create with specific variant
|
|
439
|
+
* const date5 = new BanglaCalendar('১৪৩০', '১', '১', { variant: 'revised-1966' });
|
|
440
|
+
*
|
|
441
|
+
* @remarks
|
|
442
|
+
* - The Bangla calendar year starts on `April 14th (১ বৈশাখ)` in the Gregorian calendar.
|
|
443
|
+
* - The class automatically handles leap years according to the selected variant.
|
|
444
|
+
*/
|
|
445
|
+
var BanglaCalendar = class BanglaCalendar {
|
|
446
|
+
/** Bangla calendar variant */
|
|
447
|
+
variant;
|
|
448
|
+
/** Bangla year */
|
|
449
|
+
year;
|
|
450
|
+
/** Bangla month */
|
|
451
|
+
month;
|
|
452
|
+
/** Bangla day of the month */
|
|
453
|
+
date;
|
|
454
|
+
/** Gregorian equivalent of the current bangla date */
|
|
455
|
+
gregorian;
|
|
456
|
+
/** Gets the day of the week (0-6, where 0 is Sunday (রবিবার)). */
|
|
457
|
+
weekDay;
|
|
458
|
+
/** Gets ISO weekday: 1 = Monday, 7 = Sunday */
|
|
459
|
+
isoWeekDay;
|
|
460
|
+
/** * Creates a `BanglaCalendar` instance based on given parameter(s) */
|
|
461
|
+
constructor(dateBnYrOrCfg, bnMonthOrCfg, bnDateOrCfg, config) {
|
|
462
|
+
this.variant = this.#processVariants(dateBnYrOrCfg, bnMonthOrCfg, bnDateOrCfg, config);
|
|
463
|
+
let date = dateBnYrOrCfg instanceof Date ? dateBnYrOrCfg : new Date(isDateString(dateBnYrOrCfg) && !BanglaCalendar.isBanglaDateString(dateBnYrOrCfg) ? dateBnYrOrCfg : isNumber(dateBnYrOrCfg) && !BanglaCalendar.isBanglaYearEn(dateBnYrOrCfg) ? dateBnYrOrCfg : Date.now());
|
|
464
|
+
if (isNaN(date.getTime())) date = /* @__PURE__ */ new Date();
|
|
465
|
+
const { year, month, monthDate } = this.#processDate(date);
|
|
466
|
+
let bnYear = BanglaCalendar.isBanglaYear(dateBnYrOrCfg) ? banglaToDigit(dateBnYrOrCfg) : isNumber(dateBnYrOrCfg) && BanglaCalendar.isBanglaYearEn(dateBnYrOrCfg) ? dateBnYrOrCfg : year;
|
|
467
|
+
let bnMonth = BanglaCalendar.isBanglaMonth(bnMonthOrCfg) ? banglaToDigit(bnMonthOrCfg) : BanglaCalendar.isBanglaMonthEn(bnMonthOrCfg) ? bnMonthOrCfg : month;
|
|
468
|
+
let bnDate = BanglaCalendar.isBanglaDate(bnDateOrCfg) ? banglaToDigit(bnDateOrCfg) : BanglaCalendar.isBanglaDateEn(bnDateOrCfg) ? bnDateOrCfg : monthDate;
|
|
469
|
+
if (BanglaCalendar.isBanglaDateString(dateBnYrOrCfg)) {
|
|
470
|
+
const parts = dateBnYrOrCfg.replace(/['"]/g, "").split("-");
|
|
471
|
+
bnYear = banglaToDigit(parts[0]);
|
|
472
|
+
bnMonth = banglaToDigit(parts[1]);
|
|
473
|
+
bnDate = banglaToDigit(parts[2]);
|
|
474
|
+
}
|
|
475
|
+
const { gregYear } = this.#processGregYear(bnYear, bnMonth);
|
|
476
|
+
const { bnMonthTable } = this.#getBnMonthTableLeap(gregYear, bnYear);
|
|
477
|
+
const monthRange = bnMonthTable[bnMonth - 1];
|
|
478
|
+
if (bnDate > monthRange) {
|
|
479
|
+
bnDate -= monthRange;
|
|
480
|
+
if (bnMonth === 12) {
|
|
481
|
+
bnMonth = 1;
|
|
482
|
+
bnYear += 1;
|
|
483
|
+
} else bnMonth += 1;
|
|
484
|
+
}
|
|
485
|
+
this.year = {
|
|
486
|
+
bn: digitToBangla(bnYear),
|
|
487
|
+
en: bnYear
|
|
488
|
+
};
|
|
489
|
+
this.month = {
|
|
490
|
+
bn: digitToBangla(bnMonth),
|
|
491
|
+
en: bnMonth
|
|
492
|
+
};
|
|
493
|
+
this.date = {
|
|
494
|
+
bn: digitToBangla(bnDate),
|
|
495
|
+
en: bnDate
|
|
496
|
+
};
|
|
497
|
+
const { gy, gm, gd, wd } = _extractDateUnits(this.toDate());
|
|
498
|
+
this.gregorian = {
|
|
499
|
+
year: gy,
|
|
500
|
+
month: gm,
|
|
501
|
+
date: gd
|
|
502
|
+
};
|
|
503
|
+
this.weekDay = wd;
|
|
504
|
+
this.isoWeekDay = wd === 0 ? 7 : wd;
|
|
505
|
+
}
|
|
506
|
+
[Symbol.toPrimitive](hint) {
|
|
507
|
+
if (hint === "number") return this.valueOf();
|
|
508
|
+
return this.toJSON();
|
|
509
|
+
}
|
|
510
|
+
get [Symbol.toStringTag]() {
|
|
511
|
+
return this.toJSON();
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* @instance Get timestamp in milliseconds for the current date.
|
|
515
|
+
* @remarks
|
|
516
|
+
* - Converts the current Bangla date to a Gregorian {@link Date} using {@link toDate()}.
|
|
517
|
+
* - Returns the Unix timestamp (in milliseconds) of the converted date.
|
|
518
|
+
* - The time component is normalized to midnight UTC during the conversion process.
|
|
519
|
+
*/
|
|
520
|
+
valueOf() {
|
|
521
|
+
return this.toDate().getTime();
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* @instance Returns a string representation of the Bangla date in ISO-like format (YYYY-MM-DD with Bangla digits).
|
|
525
|
+
*
|
|
526
|
+
* @returns Bangla date string in the format: "YYYY-MM-DD" (e.g., "১৪৩০-০১-০১")
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
530
|
+
* console.log(bnCal.toJSON()); // "১৪৩০-০১-০১"
|
|
531
|
+
*
|
|
532
|
+
* @remarks
|
|
533
|
+
* - This method is automatically called by {@link JSON.stringify()} method
|
|
534
|
+
* - Output follows the pattern: `"বছর-মাস-দিন"` with zero-padded Bangla digits
|
|
535
|
+
* - Month and date are padded to 2 digits, year to 4 digits
|
|
536
|
+
*/
|
|
537
|
+
toJSON() {
|
|
538
|
+
const { year, month, date } = this;
|
|
539
|
+
return `${_padShunno(year.bn, 4)}-${_padShunno(month.bn)}-${_padShunno(date.bn)}`;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* * Checks if the current Bangla year is a leap year.
|
|
543
|
+
*
|
|
544
|
+
* @returns `true` if the year is a leap year, `false` otherwise
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* const date = new BanglaCalendar(1430, 1, 1);
|
|
548
|
+
* const isLeap = date.isLeapYear(); // false
|
|
549
|
+
*
|
|
550
|
+
* @remarks
|
|
551
|
+
* - Leap year determination depends on the selected calendar variant.
|
|
552
|
+
* - The `'revised-2019'` and `'revised-1966'` variants have different leap year rules.
|
|
553
|
+
* - **Revised-2019**: Leap year is determined by the associated Gregorian year's leap rule:
|
|
554
|
+
* - A year is a leap year if it is divisible by 4, but not divisible by 100, unless it is also divisible by 400.
|
|
555
|
+
* - **Revised-1966**: Leap year is determined solely by the Bangla year (`bnYear % 4 === 2`), no Gregorian rule applies.
|
|
556
|
+
*/
|
|
557
|
+
isLeapYear() {
|
|
558
|
+
const { gregYear } = this.#processGregYear();
|
|
559
|
+
return this.#getBnMonthTableLeap(gregYear).isBnLeapYear;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* * Converts the Bangla calendar date to a JS {@link Date} object.
|
|
563
|
+
*
|
|
564
|
+
* @returns Gregorian Date object equivalent to the Bangla date
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* const bnDate = new BanglaCalendar('১৪৩০', '১', '১');
|
|
568
|
+
* const gregorianDate = bnDate.toDate(); // Date for April 14, 2023
|
|
569
|
+
* console.log(gregorianDate.toISOString()); // 2023-04-14T00:00:00.000Z
|
|
570
|
+
*
|
|
571
|
+
* @remarks
|
|
572
|
+
* - The conversion takes into account the calendar variant and leap year rules.
|
|
573
|
+
* - Time component is always set to `00:00:00` in UTC.
|
|
574
|
+
*/
|
|
575
|
+
toDate() {
|
|
576
|
+
const { baseGregYear, gregYear } = this.#processGregYear();
|
|
577
|
+
const { bnMonthTable } = this.#getBnMonthTableLeap(gregYear);
|
|
578
|
+
const epoch = Date.UTC(baseGregYear, 3, 13);
|
|
579
|
+
let days = this.date.en;
|
|
580
|
+
for (let i = 0; i < this.month.en - 1; i++) days += bnMonthTable[i];
|
|
581
|
+
return new Date(days * MS_PER_DAY + epoch);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* @instance Gets the Bangla season name for the current date.
|
|
585
|
+
*
|
|
586
|
+
* @param locale - Output locale ('bn' for Bengali, 'en' for English)
|
|
587
|
+
* @returns Name of the season in the specified locale
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
591
|
+
* bnCal.getSeasonName(); // Returns: 'গ্রীষ্ম'
|
|
592
|
+
* bnCal.getSeasonName('en'); // Returns: 'Grisma (Summer)'
|
|
593
|
+
*
|
|
594
|
+
* @remarks
|
|
595
|
+
* Bangla calendar is traditionally divided into 6 seasons (ঋতু):
|
|
596
|
+
* - গ্রীষ্ম (Summer): Mid-April to Mid-June
|
|
597
|
+
* - বর্ষা (Monsoon): Mid-June to Mid-August
|
|
598
|
+
* - শরৎ (Autumn): Mid-August to Mid-October
|
|
599
|
+
* - হেমন্ত (Late Autumn): Mid-October to Mid-December
|
|
600
|
+
* - শীত (Winter): Mid-December to Mid-February
|
|
601
|
+
* - বসন্ত (Spring): Mid-February to Mid-April
|
|
602
|
+
*/
|
|
603
|
+
getSeasonName(locale) {
|
|
604
|
+
return _getBnSeason(this.month.en - 1, locale);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* @instance Gets the Bangla name of the month for the current date.
|
|
608
|
+
*
|
|
609
|
+
* @param locale - Output locale ('bn' for Bengali, 'en' for English)
|
|
610
|
+
* @returns Name of the month in the specified locale
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
614
|
+
* bnCal.getMonthName(); // Returns: 'বৈশাখ'
|
|
615
|
+
* bnCal.getMonthName('en'); // Returns: 'Boishakh'
|
|
616
|
+
*
|
|
617
|
+
* @remarks
|
|
618
|
+
* - Month names follow traditional Bengali naming conventions.
|
|
619
|
+
* - English names are transliterated versions of the Bengali names.
|
|
620
|
+
* - Month determination may vary slightly between calendar variants near month boundaries.
|
|
621
|
+
*/
|
|
622
|
+
getMonthName(locale) {
|
|
623
|
+
const MONTH = BN_MONTHS[this.month.en - 1];
|
|
624
|
+
return locale === "en" ? MONTH.en : MONTH.bn;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* @instance Gets the Bangla name of the weekday for the current date.
|
|
628
|
+
*
|
|
629
|
+
* @param locale - Output locale ('bn' for Bengali, 'en' for English)
|
|
630
|
+
* @returns Name of the weekday in the specified locale
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* const bnCal = new BanglaCalendar('2023-04-14'); // Friday
|
|
634
|
+
* bnCal.getDayName(); // Returns: 'শুক্রবার'
|
|
635
|
+
* bnCal.getDayName('en'); // Returns: 'Shukrobar (Friday)'
|
|
636
|
+
*
|
|
637
|
+
* @remarks
|
|
638
|
+
* - Weekday names follow the standard Bengali naming convention ending with 'বার'.
|
|
639
|
+
* - English names are the Latin transliterations of the Bangla names with standard English weekday names.
|
|
640
|
+
*/
|
|
641
|
+
getDayName(locale) {
|
|
642
|
+
const DAY = BN_DAYS[this.weekDay];
|
|
643
|
+
return locale === "en" ? DAY.en : DAY.bn;
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* @instance Adds days to the current Bangla date.
|
|
647
|
+
*
|
|
648
|
+
* @param days - Number of days to add (can be negative to subtract days)
|
|
649
|
+
* @returns New `BanglaCalendar` instance with the adjusted date
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '১', '১'); // ১ বৈশাখ ১৪৩০
|
|
653
|
+
*
|
|
654
|
+
* // Add days
|
|
655
|
+
* bnCal.addDays(7); // Returns: ৮ বৈশাখ ১৪৩০
|
|
656
|
+
*
|
|
657
|
+
* // Subtract days
|
|
658
|
+
* bnCal.addDays(-3); // Returns: ২৮ চৈত্র ১৪২৯
|
|
659
|
+
*
|
|
660
|
+
* // Add days crossing month boundary
|
|
661
|
+
* bnCal.addDays(35); // Returns: ৫ জ্যৈষ্ঠ ১৪৩০
|
|
662
|
+
*
|
|
663
|
+
* // Add days crossing year boundary
|
|
664
|
+
* const lateDate = new BanglaCalendar('১৪৩০', '১২', '২৫');
|
|
665
|
+
* lateDate.addDays(10); // Returns: ৫ বৈশাখ ১৪৩১
|
|
666
|
+
*
|
|
667
|
+
* @remarks
|
|
668
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
669
|
+
* - Handles month and year transitions automatically
|
|
670
|
+
* - Accounts for varying month lengths and leap years
|
|
671
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
672
|
+
* - Negative values subtract days from the current date
|
|
673
|
+
*/
|
|
674
|
+
addDays(days) {
|
|
675
|
+
const date = this.toDate();
|
|
676
|
+
return new BanglaCalendar(date.setDate(date.getDate() + days), { variant: this.variant });
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* @instance Adds weeks to the current Bangla date.
|
|
680
|
+
*
|
|
681
|
+
* @param weeks - Number of weeks to add (can be negative to subtract weeks)
|
|
682
|
+
* @returns New `BanglaCalendar` instance with the adjusted date
|
|
683
|
+
*
|
|
684
|
+
* @example
|
|
685
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '১', '১'); // ১ বৈশাখ ১৪৩০
|
|
686
|
+
*
|
|
687
|
+
* // Add weeks
|
|
688
|
+
* bnCal.addWeeks(2); // Returns: ১৫ বৈশাখ ১৪৩০
|
|
689
|
+
*
|
|
690
|
+
* // Subtract weeks
|
|
691
|
+
* bnCal.addWeeks(-1); // Returns: ২৪ চৈত্র ১৪২৯
|
|
692
|
+
*
|
|
693
|
+
* // Add weeks crossing month boundary
|
|
694
|
+
* bnCal.addWeeks(5); // Returns: ৫ জ্যৈষ্ঠ ১৪৩০
|
|
695
|
+
*
|
|
696
|
+
* @remarks
|
|
697
|
+
* - Each week is treated as 7 days
|
|
698
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
699
|
+
* - Handles month and year transitions automatically
|
|
700
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
701
|
+
* - Negative values subtract weeks from the current date
|
|
702
|
+
* - Useful for scheduling recurring weekly events
|
|
703
|
+
*/
|
|
704
|
+
addWeeks(weeks) {
|
|
705
|
+
const date = this.toDate();
|
|
706
|
+
return new BanglaCalendar(date.setDate(date.getDate() + weeks * 7), { variant: this.variant });
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* @instance Adds months to the current Bangla date.
|
|
710
|
+
*
|
|
711
|
+
* @param months - Number of months to add (can be negative to subtract months)
|
|
712
|
+
* @param overflow - If `true`, allows date overflow to next month when day doesn't exist;
|
|
713
|
+
* if `false`, clamps to last day of target month (default: `true`)
|
|
714
|
+
* @returns New `BanglaCalendar` instance with the adjusted date
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* // Normal case: day exists in target month
|
|
718
|
+
* const normal = new BanglaCalendar('১৪৩০', '২', '১৫');
|
|
719
|
+
* normal.addMonths(1); // Returns: ১৫ আষাঢ় ১৪৩০
|
|
720
|
+
* normal.addMonths(1, false); // Returns: ১৫ আষাঢ় ১৪৩০ (same behavior for both)
|
|
721
|
+
*
|
|
722
|
+
* // Edge case: day does not exist in target month
|
|
723
|
+
* const edgeCase = new BanglaCalendar('১৪৩০', '৬', '৩১'); // ৩১ আশ্বিন ১৪৩০
|
|
724
|
+
*
|
|
725
|
+
* // With overflow (default): 31st doesn't exist in কার্তিক (30 days)
|
|
726
|
+
* edgeCase.addMonths(1); // Returns: ১ অগ্রহায়ণ ১৪৩০ (overflows to next month)
|
|
727
|
+
*
|
|
728
|
+
* // Without overflow: clamps to last day of target month
|
|
729
|
+
* edgeCase.addMonths(1, false); // Returns: ৩০ কার্তিক ১৪৩০ (clamped)
|
|
730
|
+
*
|
|
731
|
+
* // Subtract months
|
|
732
|
+
* edgeCase.addMonths(-1); // Returns: ১ আশ্বিন ১৪৩০
|
|
733
|
+
* edgeCase.addMonths(-1, false); // Returns: ৩১ ভাদ্র ১৪৩০
|
|
734
|
+
*
|
|
735
|
+
* @remarks
|
|
736
|
+
* - When `overflow=true` (default):
|
|
737
|
+
* Follows JavaScript {@link Date} behavior where invalid dates overflow to the next month (e.g., ৩১ আশ্বিন + 1 month → ১ অগ্রহায়ণ)
|
|
738
|
+
* - When `overflow=false`:
|
|
739
|
+
* Clamps to the last valid day of the target month (e.g., ৩১ আশ্বিন + 1 month → ৩০ কার্তিক)
|
|
740
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
741
|
+
* - Handles year transitions automatically
|
|
742
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
743
|
+
* - Negative values subtract months from the current date
|
|
744
|
+
*/
|
|
745
|
+
addMonths(months, overflow = true) {
|
|
746
|
+
if (overflow) {
|
|
747
|
+
const current = this.toDate();
|
|
748
|
+
return new BanglaCalendar(current.setMonth(current.getMonth() + months), { variant: this.variant });
|
|
749
|
+
} else {
|
|
750
|
+
const { variant, year, month, date } = this;
|
|
751
|
+
let targetMonth = month.en + months;
|
|
752
|
+
let targetYear = year.en;
|
|
753
|
+
while (targetMonth > 12) {
|
|
754
|
+
targetMonth -= 12;
|
|
755
|
+
targetYear += 1;
|
|
756
|
+
}
|
|
757
|
+
while (targetMonth < 1) {
|
|
758
|
+
targetMonth += 12;
|
|
759
|
+
targetYear -= 1;
|
|
760
|
+
}
|
|
761
|
+
return this.#getClampedBnCal(targetYear, targetMonth, date.en, variant);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* @instance Adds years to the current Bangla date.
|
|
766
|
+
*
|
|
767
|
+
* @param years - Number of years to add (can be negative to subtract years)
|
|
768
|
+
* @param overflow - If `true`, allows date overflow when day doesn't exist in target year;
|
|
769
|
+
* if `false`, clamps to last valid day of month (default: `true`)
|
|
770
|
+
* @returns New `BanglaCalendar` instance with the adjusted date
|
|
771
|
+
*
|
|
772
|
+
* @example
|
|
773
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '১', '১৫'); // ১৫ বৈশাখ ১৪৩০
|
|
774
|
+
*
|
|
775
|
+
* // Add years
|
|
776
|
+
* bnCal.addYears(1); // Returns: ১৫ বৈশাখ ১৪৩১
|
|
777
|
+
*
|
|
778
|
+
* // Subtract years
|
|
779
|
+
* bnCal.addYears(-1); // Returns: ১৫ বৈশাখ ১৪২৯
|
|
780
|
+
*
|
|
781
|
+
* // Multiple years
|
|
782
|
+
* bnCal.addYears(5); // Returns: ১৫ বৈশাখ ১৪৩৫
|
|
783
|
+
*
|
|
784
|
+
* // Edge case: day adjustment for ফাল্গুন (accounting leap year)
|
|
785
|
+
* const leapDay = new BanglaCalendar('১৪৩১', '১১', '৩০'); // ১৪৩১ is a leap year
|
|
786
|
+
* leapDay.addYears(1, false); // Returns: ২৯ ফাল্গুন ১৪৩২ (non-leap years have 29 days in ফাল্গুন)
|
|
787
|
+
*
|
|
788
|
+
* @remarks
|
|
789
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
790
|
+
* - Negative values subtract years from the current date
|
|
791
|
+
* - Year addition follows Bangla calendar years
|
|
792
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
793
|
+
* - The month and day generally remain the same unless affected by leap year rules
|
|
794
|
+
*/
|
|
795
|
+
addYears(years, overflow = true) {
|
|
796
|
+
const { variant, year, month, date } = this;
|
|
797
|
+
const targetYear = year.en + years;
|
|
798
|
+
if (overflow) return new BanglaCalendar(targetYear, month.en, date.en, { variant });
|
|
799
|
+
else return this.#getClampedBnCal(targetYear, month.en, date.en, variant);
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* @instance Gets a new `BanglaCalendar` instance representing the first day of the current month.
|
|
803
|
+
*
|
|
804
|
+
* @returns A `BanglaCalendar` instance set to the 1st day of the current month
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '৫', '১৫');
|
|
808
|
+
* const startOfMonth = bnCal.startOfMonth(); // Returns: ১ জ্যৈষ্ঠ ১৪৩০
|
|
809
|
+
*
|
|
810
|
+
* @remarks
|
|
811
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
812
|
+
* - Useful for date range calculations and month-based operations
|
|
813
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
814
|
+
*/
|
|
815
|
+
startOfMonth() {
|
|
816
|
+
const { year, month, variant } = this;
|
|
817
|
+
return new BanglaCalendar(year.en, month.en, 1, { variant });
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* @instance Gets a new `BanglaCalendar` instance representing the last day of the current month.
|
|
821
|
+
*
|
|
822
|
+
* @returns A `BanglaCalendar` instance set to the last day of the current month
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '৫', '১৫');
|
|
826
|
+
* const endOfMonth = bnCal.endOfMonth(); // Returns: ৩১ জ্যৈষ্ঠ ১৪৩০ (or 30 for some months)
|
|
827
|
+
*
|
|
828
|
+
* @remarks
|
|
829
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
830
|
+
* - Accounts for month length variations (29/30/31 days) including leap years
|
|
831
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
832
|
+
*/
|
|
833
|
+
endOfMonth() {
|
|
834
|
+
const { year, month, variant } = this;
|
|
835
|
+
return new BanglaCalendar(year.en, month.en, this.daysInMonth(), { variant });
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* @instance Gets a new `BanglaCalendar` instance representing the first day of the current year (১ বৈশাখ).
|
|
839
|
+
*
|
|
840
|
+
* @returns A `BanglaCalendar` instance set to ১ বৈশাখ of the current year
|
|
841
|
+
*
|
|
842
|
+
* @example
|
|
843
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '৫', '১৫');
|
|
844
|
+
* const startOfYear = bnCal.startOfYear(); // Returns: ১ বৈশাখ ১৪৩০
|
|
845
|
+
*
|
|
846
|
+
* @remarks
|
|
847
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
848
|
+
* - Always returns the 1st day of the 1st month (বৈশাখ)
|
|
849
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
850
|
+
*/
|
|
851
|
+
startOfYear() {
|
|
852
|
+
const { year, variant } = this;
|
|
853
|
+
return new BanglaCalendar(year.en, 1, 1, { variant });
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* @instance Gets a new `BanglaCalendar` instance representing the last day of the current year (৩০ চৈত্র).
|
|
857
|
+
*
|
|
858
|
+
* @returns A `BanglaCalendar` instance set to ৩০ চৈত্র of the current year
|
|
859
|
+
*
|
|
860
|
+
* @example
|
|
861
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '৫', '১৫');
|
|
862
|
+
* const endOfYear = bnCal.endOfYear(); // Returns: ৩০ চৈত্র ১৪৩০
|
|
863
|
+
*
|
|
864
|
+
* @remarks
|
|
865
|
+
* - The resulting instance preserves the calendar variant of the original
|
|
866
|
+
* - Always returns the 30th day of the 12th month (চৈত্র)
|
|
867
|
+
* - Time component remains at midnight UTC in the Gregorian conversion (using {@link BanglaCalendar.toDate()} method)
|
|
868
|
+
*/
|
|
869
|
+
endOfYear() {
|
|
870
|
+
const { year, variant } = this;
|
|
871
|
+
return new BanglaCalendar(year.en, 12, 30, { variant });
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* @instance Gets the number of days in a Bangla month.
|
|
875
|
+
*
|
|
876
|
+
* @param month - Optional Bangla month (1-12 in Latin digits)
|
|
877
|
+
* @returns Number of days in the specified month (29, 30, or 31)
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* const bnCal = new BanglaCalendar('১৪৩০', '১', '১');
|
|
881
|
+
*
|
|
882
|
+
* // Get days in current month
|
|
883
|
+
* bnCal.daysInMonth(); // Returns: 31 (বৈশাখ has 31 days)
|
|
884
|
+
*
|
|
885
|
+
* // Get days in specific month
|
|
886
|
+
* bnCal.daysInMonth(2); // Returns: 31 (জ্যৈষ্ঠ has 31 days)
|
|
887
|
+
* bnCal.daysInMonth(12); // Returns: 30 (চৈত্র has 30 days)
|
|
888
|
+
*
|
|
889
|
+
* @remarks
|
|
890
|
+
* - The method accounts for the selected calendar variant when determining leap years
|
|
891
|
+
* - If no month is provided, uses the current instance's month
|
|
892
|
+
* - In the 'revised-2019' variant, leap years follow Gregorian leap rules
|
|
893
|
+
* - In the 'revised-1966' variant, leap years occur when `bnYear % 4 === 2`
|
|
894
|
+
*/
|
|
895
|
+
daysInMonth(month) {
|
|
896
|
+
const { gregYear } = this.#processGregYear();
|
|
897
|
+
const { bnMonthTable } = this.#getBnMonthTableLeap(gregYear);
|
|
898
|
+
return bnMonthTable[(month ?? this.month.en) - 1];
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* @instance Returns a string representation of the Bangla date in Bengali format.
|
|
902
|
+
*
|
|
903
|
+
* @returns Bangla date string in the format: "শুক্রবার, ১৫ জ্যৈষ্ঠ, ১৪৩০ [গ্রীষ্ম]"
|
|
904
|
+
*
|
|
905
|
+
* @example
|
|
906
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
907
|
+
* console.log(bnCal.toString()); // "শুক্রবার, ১ বৈশাখ, ১৪৩০ [গ্রীষ্ম]"
|
|
908
|
+
*
|
|
909
|
+
* @remarks
|
|
910
|
+
* - Equivalent to calling {@link toStringEn()} with 'bn' locale
|
|
911
|
+
* - Format includes day name, date, month name, year, and season in brackets
|
|
912
|
+
* - Uses Bengali digits and Bengali month/day names
|
|
913
|
+
*/
|
|
914
|
+
toString() {
|
|
915
|
+
return this.#toString("bn");
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* @instance Returns a string representation of the Bangla date in English/Latin format.
|
|
919
|
+
*
|
|
920
|
+
* @returns Bangla date string in the format: "Shukrobar (Friday), 15 Joishtho, 1430 [Grisma (Summer)]"
|
|
921
|
+
*
|
|
922
|
+
* @example
|
|
923
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
924
|
+
* console.log(bnCal.toStringEn()); // "Shukrobar (Friday), 1 Boishakh, 1430 [Grisma (Summer)]"
|
|
925
|
+
*
|
|
926
|
+
* @remarks
|
|
927
|
+
* - Equivalent to calling {@link toString()} with 'en' locale
|
|
928
|
+
* - Format includes transliterated day name (with English equivalent), date, transliterated month and season name, and year.
|
|
929
|
+
* - Uses Latin digits and transliterated Bengali names
|
|
930
|
+
*/
|
|
931
|
+
toStringEn() {
|
|
932
|
+
return this.#toString("en");
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* @instance Formats the current date as a Bangla calendar date string (no time) using customizable tokens.
|
|
936
|
+
*
|
|
937
|
+
* @param format - Format string using tokens (default: `'ddd, DD mmmm (SS), YYYY বঙ্গাব্দ'`)
|
|
938
|
+
* @returns Formatted Bangla date string according to the specified format
|
|
939
|
+
*
|
|
940
|
+
* @example
|
|
941
|
+
* const bnCal = new BanglaCalendar('2023-04-14');
|
|
942
|
+
*
|
|
943
|
+
* bnCal.format();
|
|
944
|
+
* // Returns: 'শুক্রবার, বৈশাখ ০১ (গ্রীষ্মকাল), ১৪৩০ বঙ্গাব্দ'
|
|
945
|
+
*
|
|
946
|
+
* bnCal.format('YYYY-MM-DD');
|
|
947
|
+
* // Returns: '১৪৩০-০১-০১'
|
|
948
|
+
*
|
|
949
|
+
* bnCal.format('mmmm DD, YYYY');
|
|
950
|
+
* // Returns: 'বৈশাখ ০১, ১৪৩০'
|
|
951
|
+
*
|
|
952
|
+
* @remarks
|
|
953
|
+
* - **Important:** Does not allow time formatting tokens!
|
|
954
|
+
* - Supported format tokens include: `YYYY`, `YY`, `mmmm`, `mmm`, `MM`, `M`, `DD`, `D`, `dd`, `ddd`, `Do`, `SS` and `S`.
|
|
955
|
+
* - **Year**: `YYYY/yyyy` (full year), `YY/yy` (last 2 digits)
|
|
956
|
+
* - **Month**: `M/MM`(padded), `mmm` (short name), `mmmm` (full name)
|
|
957
|
+
* - **Day**: `D/DD`(padded), Do (results same as cardinal for Bangla dates)
|
|
958
|
+
* - **Weekday**: `d` (short), `dd` (without 'বার'), `ddd` (full)
|
|
959
|
+
* - **Season**: `S` (season), `SS` (season with 'কাল' suffix)
|
|
960
|
+
* - To output raw text (i.e., not interpreted as a date token), wrap it in square brackets.
|
|
961
|
+
* - For example, `[আজ] ddd` results in `আজ রবিবার`, and `[year ]YYYY` results in `year ২০২৫`.
|
|
962
|
+
* - *Any token not wrapped in brackets will be parsed and replaced with its corresponding date component.*
|
|
963
|
+
*/
|
|
964
|
+
format(format) {
|
|
965
|
+
const { year, month, date, weekDay } = this;
|
|
966
|
+
const seasonName = this.getSeasonName();
|
|
967
|
+
const M_NAME = BN_MONTHS[month.en - 1];
|
|
968
|
+
const D_NAME = BN_DAYS[weekDay];
|
|
969
|
+
const paddedYear = _padShunno(year.bn, 4);
|
|
970
|
+
const dateComponents = {
|
|
971
|
+
YYYY: paddedYear,
|
|
972
|
+
YY: paddedYear.slice(-2),
|
|
973
|
+
yyyy: paddedYear,
|
|
974
|
+
yy: paddedYear.slice(-2),
|
|
975
|
+
M: month.bn,
|
|
976
|
+
MM: _padShunno(month.bn),
|
|
977
|
+
mmm: M_NAME.short,
|
|
978
|
+
mmmm: M_NAME.bn,
|
|
979
|
+
d: D_NAME.short,
|
|
980
|
+
dd: D_NAME.bn.replace("বার", ""),
|
|
981
|
+
ddd: D_NAME.bn,
|
|
982
|
+
D: date.bn,
|
|
983
|
+
DD: _padShunno(date.bn),
|
|
984
|
+
Do: date.bn,
|
|
985
|
+
S: seasonName,
|
|
986
|
+
SS: seasonName + "কাল"
|
|
987
|
+
};
|
|
988
|
+
return _formatDateCore(format || "ddd, DD mmmm (SS), YYYY বঙ্গাব্দ", dateComponents);
|
|
989
|
+
}
|
|
990
|
+
/** Process Gregorian base year and calculated year from optional Bangla year and month */
|
|
991
|
+
#processGregYear(bnYear, bnMonth) {
|
|
992
|
+
const baseGregYear = (bnYear ?? this.year.en) + 593;
|
|
993
|
+
return {
|
|
994
|
+
baseGregYear,
|
|
995
|
+
gregYear: (bnMonth ?? this.month.en) > 10 ? baseGregYear + 1 : baseGregYear
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
/** Get the Bangla month table and leap year flag based on calendar variant */
|
|
999
|
+
#getBnMonthTableLeap(gregYear, bnYear) {
|
|
1000
|
+
const isBnLeapYear = _isBnLeapYear(bnYear ?? this.year.en, gregYear, this.variant);
|
|
1001
|
+
return {
|
|
1002
|
+
bnMonthTable: isBnLeapYear ? BN_MONTH_TABLES?.[this.variant].leap : BN_MONTH_TABLES?.[this.variant].normal,
|
|
1003
|
+
isBnLeapYear
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* @internal Get new `BanglaCalendar` instance with clamped date
|
|
1008
|
+
* @param tyBn - Target Bangla year
|
|
1009
|
+
* @param tmBn - Target Bangla month
|
|
1010
|
+
* @param cdBn - Current Bangla date of the month
|
|
1011
|
+
* @param variant - Calendar variant to preserve
|
|
1012
|
+
* @returns New `BanglaCalendar` instance with date clamped to valid range
|
|
1013
|
+
*
|
|
1014
|
+
* @remarks
|
|
1015
|
+
* - Clamps the date to not exceed the number of days in the target month
|
|
1016
|
+
* - Used internally for non-overflow date arithmetic
|
|
1017
|
+
* - Ensures dates like ৩১ don't become invalid in months with only 30 days
|
|
1018
|
+
*/
|
|
1019
|
+
#getClampedBnCal(tyBn, tmBn, cdBn, variant) {
|
|
1020
|
+
const { gregYear } = this.#processGregYear(tyBn, tmBn);
|
|
1021
|
+
const { bnMonthTable } = this.#getBnMonthTableLeap(gregYear, tyBn);
|
|
1022
|
+
return new BanglaCalendar(tyBn, tmBn, Math.min(cdBn, bnMonthTable[tmBn - 1]), { variant });
|
|
1023
|
+
}
|
|
1024
|
+
/** Process variant from the config */
|
|
1025
|
+
#processVariants(v1, v2, v3, v4) {
|
|
1026
|
+
return this.$hasVariantConfig(v1) ? v1.variant : this.$hasVariantConfig(v2) ? v2.variant : this.$hasVariantConfig(v3) ? v3.variant : this.$hasVariantConfig(v4) ? v4.variant : "revised-2019";
|
|
1027
|
+
}
|
|
1028
|
+
/** Process {@link Date} and extract Bangla year, month and dates in both Bangla and Latin */
|
|
1029
|
+
#processDate(date) {
|
|
1030
|
+
const bnYear = _getBnYear(date);
|
|
1031
|
+
const { days, monthIdx } = _bnDaysMonthIdx(date, this.variant);
|
|
1032
|
+
return {
|
|
1033
|
+
year: bnYear,
|
|
1034
|
+
month: monthIdx + 1,
|
|
1035
|
+
monthDate: days + 1
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
/** Convert to human readable string either in `bn` or `en` locale */
|
|
1039
|
+
#toString(lcl = "bn") {
|
|
1040
|
+
const { year, date } = this;
|
|
1041
|
+
return `${this.getDayName(lcl)}, ${date[lcl]} ${this.getMonthName(lcl)}, ${year[lcl]} [${this.getSeasonName(lcl)}]`;
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* @static Check if a value is a configuration object that contains a valid {@link variant}
|
|
1045
|
+
* @param value Value to check
|
|
1046
|
+
* @returns `true` if the value contains a valid {@link variant} property, `false` otherwise
|
|
1047
|
+
*/
|
|
1048
|
+
$hasVariantConfig(value) {
|
|
1049
|
+
return isObjectWithKeys(value, ["variant"]) && isNonEmptyString(value.variant) && (value.variant === "revised-1966" || value.variant === "revised-2019");
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* @static Checks whether a value is a valid Bangla year in Bangla digits (`০–৯৯৯৯`).
|
|
1053
|
+
*
|
|
1054
|
+
* @param value - Value to check. Accepts both zero-padded and non-padded Bangla digits
|
|
1055
|
+
* @returns `true` if the value is a valid Bangla year, `false` otherwise
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* BanglaCalendar.isBanglaYear('১৪৩০'); // true
|
|
1059
|
+
* BanglaCalendar.isBanglaYear('০'); // true
|
|
1060
|
+
* BanglaCalendar.isBanglaYear('১০০০০'); // false (too many digits)
|
|
1061
|
+
* BanglaCalendar.isBanglaYear('1430'); // false (Latin digits)
|
|
1062
|
+
*/
|
|
1063
|
+
static isBanglaYear(value) {
|
|
1064
|
+
return isNonEmptyString(value) && /^(?:০{0,3}[১-৯][০-৯]{0,3}|০)$/.test(value.trim());
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* @static Checks whether a value is a valid Bangla year in Latin digits (`0–9999`).
|
|
1068
|
+
*
|
|
1069
|
+
* @param value - Value to check (must be a number)
|
|
1070
|
+
* @returns `true` if the value is a valid Bangla year, `false` otherwise
|
|
1071
|
+
*
|
|
1072
|
+
* @example
|
|
1073
|
+
* BanglaCalendar.isBanglaYearEn(1430); // true
|
|
1074
|
+
* BanglaCalendar.isBanglaYearEn(0); // true
|
|
1075
|
+
* BanglaCalendar.isBanglaYearEn(10000); // false
|
|
1076
|
+
* BanglaCalendar.isBanglaYearEn(-1); // false
|
|
1077
|
+
*/
|
|
1078
|
+
static isBanglaYearEn(value) {
|
|
1079
|
+
return isInteger(value) && value >= 0 && value <= 9999;
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* @static Checks whether a value is a valid Bangla month in Bangla digits (`১–১২`).
|
|
1083
|
+
*
|
|
1084
|
+
* @param value - Value to check. Accepts both zero-padded and non-padded Bangla digits
|
|
1085
|
+
* @returns `true` if the value is a valid Bangla month, `false` otherwise
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* BanglaCalendar.isBanglaMonth('১'); // true
|
|
1089
|
+
* BanglaCalendar.isBanglaMonth('১২'); // true
|
|
1090
|
+
* BanglaCalendar.isBanglaMonth('১৩'); // false
|
|
1091
|
+
* BanglaCalendar.isBanglaMonth('0'); // false (Latin digit)
|
|
1092
|
+
*/
|
|
1093
|
+
static isBanglaMonth(value) {
|
|
1094
|
+
return isNonEmptyString(value) && /^(?:০?[১-৯]|১০|১১|১২)$/.test(value.trim());
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* @static Checks whether a value is a valid Bangla month in Latin digits (`1–12`).
|
|
1098
|
+
*
|
|
1099
|
+
* @param value - Value to check
|
|
1100
|
+
* @returns `true` if the value is a valid Bangla month, `false` otherwise
|
|
1101
|
+
*
|
|
1102
|
+
* @example
|
|
1103
|
+
* BanglaCalendar.isBanglaMonthEn(1); // true
|
|
1104
|
+
* BanglaCalendar.isBanglaMonthEn(12); // true
|
|
1105
|
+
* BanglaCalendar.isBanglaMonthEn(0); // false
|
|
1106
|
+
* BanglaCalendar.isBanglaMonthEn(13); // false
|
|
1107
|
+
*/
|
|
1108
|
+
static isBanglaMonthEn(value) {
|
|
1109
|
+
return isInteger(value) && value >= 1 && value <= 12;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* @static Checks whether a value is a valid Bangla date of month in Bangla digits (`১–৩১`).
|
|
1113
|
+
*
|
|
1114
|
+
* @param value - Value to check. Accepts both zero-padded and non-padded Bangla digits
|
|
1115
|
+
* @returns `true` if the value is a valid Bangla date, `false` otherwise
|
|
1116
|
+
*
|
|
1117
|
+
* @example
|
|
1118
|
+
* BanglaCalendar.isBanglaDate('১'); // true
|
|
1119
|
+
* BanglaCalendar.isBanglaDate('৩১'); // true
|
|
1120
|
+
* BanglaCalendar.isBanglaDate('৩২'); // false
|
|
1121
|
+
* BanglaCalendar.isBanglaDate('০'); // false
|
|
1122
|
+
*/
|
|
1123
|
+
static isBanglaDate(value) {
|
|
1124
|
+
return isNonEmptyString(value) && /^(?:০?[১-৯]|[১২][০-৯]|৩০|৩১)$/.test(value.trim());
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* @static Checks whether a value is a valid Bangla date of month in Latin digits (`1–31`).
|
|
1128
|
+
*
|
|
1129
|
+
* @param value - Value to check
|
|
1130
|
+
* @returns `true` if the value is a valid Bangla date, `false` otherwise
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* BanglaCalendar.isBanglaDateEn(1); // true
|
|
1134
|
+
* BanglaCalendar.isBanglaDateEn(31); // true
|
|
1135
|
+
* BanglaCalendar.isBanglaDateEn(32); // false
|
|
1136
|
+
* BanglaCalendar.isBanglaDateEn(0); // false
|
|
1137
|
+
*/
|
|
1138
|
+
static isBanglaDateEn(value) {
|
|
1139
|
+
return isInteger(value) && value >= 1 && value <= 31;
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* @static Checks whether a string follows the Bangla date format pattern (`YYYY-MM-DD` with Bangla digits).
|
|
1143
|
+
*
|
|
1144
|
+
* @param value - String value to check
|
|
1145
|
+
* @returns `true` if the string matches the pattern `"বছর-মাস-দিন"` with Bangla digits, `false` otherwise
|
|
1146
|
+
*
|
|
1147
|
+
* @example
|
|
1148
|
+
* BanglaCalendar.isBanglaDateString('১৪৩০-০১-০১'); // true
|
|
1149
|
+
* BanglaCalendar.isBanglaDateString('1430-01-01'); // false (Latin digits)
|
|
1150
|
+
* BanglaCalendar.isBanglaDateString('১৪৩০-১-১'); // true (single-digit month/date)
|
|
1151
|
+
* BanglaCalendar.isBanglaDateString('১৪৩০-১৩-০১'); // false (invalid month)
|
|
1152
|
+
*
|
|
1153
|
+
* @remarks
|
|
1154
|
+
* - Accepts both zero-padded and non-padded Bangla digits
|
|
1155
|
+
* - Validates year, month, and date components separately
|
|
1156
|
+
* - Year must be `০-৯৯৯৯`, month must be `১-১২`, date must be `১-৩১`
|
|
1157
|
+
*/
|
|
1158
|
+
static isBanglaDateString(value) {
|
|
1159
|
+
if (isNonEmptyString(value) && value.includes("-")) {
|
|
1160
|
+
const [year, month, date] = value.replace(/['"]/g, "").split("-");
|
|
1161
|
+
return BanglaCalendar.isBanglaYear(year) && BanglaCalendar.isBanglaMonth(month) && BanglaCalendar.isBanglaDate(date);
|
|
1162
|
+
}
|
|
1163
|
+
return false;
|
|
1164
|
+
}
|
|
1165
|
+
};
|
|
1166
|
+
//#endregion
|
|
1167
|
+
exports.BanglaCalendar = BanglaCalendar;
|
|
1168
|
+
exports.BnCalendar = BanglaCalendar;
|
|
1169
|
+
exports.Bongabdo = BanglaCalendar;
|