@coreify/tarikh 1.0.2 → 1.1.0

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 CHANGED
@@ -1,99 +1,132 @@
1
- # @coreify/tarikh
2
-
3
- [![npm version](https://img.shields.io/npm/v/@coreify/tarikh)](https://www.npmjs.com/package/@coreify/tarikh)
4
- [![downloads](https://img.shields.io/npm/dm/@coreify/tarikh)](https://www.npmjs.com/package/@coreify/tarikh)
5
- [![license](https://img.shields.io/npm/l/@coreify/tarikh)](https://github.com/coreify/tarikh/blob/main/package/LICENSE)
6
-
1
+ # @coreify/tarikh
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@coreify/tarikh)](https://www.npmjs.com/package/@coreify/tarikh)
4
+ [![downloads](https://img.shields.io/npm/dm/@coreify/tarikh)](https://www.npmjs.com/package/@coreify/tarikh)
5
+ [![license](https://img.shields.io/npm/l/@coreify/tarikh)](https://github.com/coreify/tarikh/blob/main/package/LICENSE)
6
+
7
7
  > The first JavaScript date library with Bangla and Hijri calendar support.
8
8
  > Built for Bangla dates, Bengali calendar conversion, and culturally correct formatting.
9
9
 
10
- | Main export | What it does |
11
- | ----------- | ------------ |
12
- | `format()` | Standard, Bangla, Hijri, and hybrid date formatting |
13
- | `toBanglaCalendar()` | Convert Gregorian dates into the Bangla calendar |
14
- | `toHijriCalendar()` | Convert Gregorian dates into the Hijri calendar |
15
- | `fromNow()` | Render relative time like today, yesterday, and tomorrow |
16
- | `HIJRI_TIME_ZONES` | Canonical supported Hijri time zones |
10
+ | Main export | What it does |
11
+ | --------------------------------- | -------------------------------------------------------- |
12
+ | `format()` | Standard, Bangla, Hijri, and hybrid date formatting |
13
+ | `toBanglaCalendar()` | Convert Gregorian dates into the Bangla calendar |
14
+ | `toHijriCalendar()` | Convert Gregorian dates into the Hijri calendar |
15
+ | `setDefaults()` / `getDefaults()` | Configure reusable package-wide defaults |
16
+ | `parseDateDetailed()` | Parse with structured success/failure metadata |
17
+ | `fromNow()` | Render relative time like today, yesterday, and tomorrow |
18
+ | `HIJRI_TIME_ZONES` | Canonical supported Hijri time zones |
17
19
 
18
20
  ## At a Glance
19
21
 
20
- | Snapshot | Example |
21
- | -------- | ------- |
22
+ | Snapshot | Example |
23
+ | -------------------- | ----------------------------------------------------------------------------- |
22
24
  | Bangla spoken format | `format("2026-04-14", { mode: "bangla", locale: "bn-BD", format: "spoken" })` |
23
- | Rendered output | `পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ` |
25
+ | Rendered output | `পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ` |
24
26
 
25
27
  ```ts
26
28
  format("2026-04-14", {
27
29
  mode: "bangla",
28
30
  locale: "bn-BD",
29
- format: "spoken"
30
- });
31
+ format: "spoken"
32
+ });
31
33
  // → "পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
32
- ```
33
-
34
+ ```
35
+
34
36
  ## Demo
35
37
 
36
- | Demo | Link |
37
- | ---- | ---- |
38
+ | Demo | Link |
39
+ | --------- | -------------------------------------- |
38
40
  | Live demo | [tarikh.js.org](https://tarikh.js.org) |
39
-
41
+
40
42
  ## Why this exists
41
43
 
42
- | Why this exists | Summary |
43
- | --------------- | ------- |
44
- | Bangla calendar | Convert Gregorian dates to Bengali calendar values like বৈশাখ and চৈত্র |
45
- | Hijri calendar | Render Islamic calendar dates alongside Bangla and Gregorian output |
46
- | Bangla digits | Render `৩১শে মার্চ ২০২৬ খ্রিস্টাব্দ` instead of `31st March 2026` |
47
- | Hybrid formatting | Mix English and Bangla in a single date string |
48
- | Weekday/time | Render weekday, hour, minute, and second output |
49
- | Relative time | Use `yesterday`, `tomorrow`, `গতকাল`, `আগামীকাল`, etc. |
50
- | Cultural correctness | Bangladeshi locale-aware formatting out of the box |
44
+ | Why this exists | Summary |
45
+ | -------------------- | -------------------------------------------------------------------------- |
46
+ | Bangla calendar | Convert Gregorian dates to Bengali calendar values like বৈশাখ and চৈত্র |
47
+ | Hijri calendar | Render Islamic calendar dates alongside Bangla and Gregorian output |
48
+ | Bangla digits | Render `৩১শে মার্চ ২০২৬ খ্রিস্টাব্দ` instead of `31st March 2026` |
49
+ | Hybrid formatting | Mix English and Bangla in a single date string |
50
+ | Weekday/time | Render weekday, hour, minute, and second output |
51
+ | Relative time | Use `yesterday`, `tomorrow`, `গতকাল`, `আগামীকাল`, etc. |
52
+ | Global defaults | Reuse locale, mode, month, Hijri timezone, and Hijri backend across an app |
53
+ | Cultural correctness | Bangladeshi locale-aware formatting out of the box |
51
54
 
52
55
  > `@coreify/tarikh` is a zero-dependency, tree-shakeable, SSR-safe toolkit purpose-built for Bangladesh.
53
-
54
- ## Installation
55
-
56
- ```bash
57
- npm install @coreify/tarikh
58
- ```
59
-
60
- ## Quick Start
61
-
62
- ```ts
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ npm install @coreify/tarikh
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ```ts
63
66
  import {
64
67
  HIJRI_TIME_ZONES,
65
68
  format,
66
69
  fromNow,
70
+ getDefaults,
71
+ parseDateDetailed,
72
+ setDefaults,
67
73
  toBanglaCalendar,
68
74
  toHijriCalendar
69
75
  } from "@coreify/tarikh";
70
76
 
71
77
  const [defaultHijriZone, utcHijriZone] = HIJRI_TIME_ZONES;
72
-
73
- // Preferred entry points:
78
+
79
+ // Preferred entry points:
74
80
  format("2026-03-31", { mode: "standard" });
75
81
  format("2026-03-31", { mode: "bangla" });
76
82
  format("2026-03-31", { mode: "hijri" });
77
83
  format("2026-03-31", { mode: "hybrid" });
78
-
79
- // Token-based output still works.
84
+
85
+ setDefaults({ locale: "bn-BD", mode: "standard", month: "long" });
86
+ getDefaults();
87
+ // → { locale: "bn-BD", mode: "standard", month: "long", timeZone: "Asia/Dhaka", hijriSystem: "islamic-umalqura" }
88
+
89
+ // Token-based output still works.
80
90
  format("2026-03-31", { pattern: "DD MMM YYYY" });
81
- // → "31 Mar 2026"
82
-
83
- // Structured Bangla calendar conversion
84
- // `monthIndex` stays numeric; `bn-BD` localizes `day`, `month`, and `year`.
85
- toBanglaCalendar("2026-03-31");
86
- // → { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
87
-
88
- toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
89
- // { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
90
-
91
- format("2026-03-31", { mode: "bangla" });
92
- // → "17th Chaitra 1432"
93
-
94
- format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
91
+ // → "31 Mar 2026"
92
+
93
+ format(new Date(2026, 2, 31, 15, 4, 9), {
94
+ mode: "standard",
95
+ preset: "dateTime"
96
+ });
97
+ // → "31st Mar 2026, 15:04"
98
+
99
+ format(new Date(2026, 2, 31, 15, 4, 9), {
100
+ mode: "standard",
101
+ preset: "isoLike"
102
+ });
103
+ // → "2026-03-31 15:04:09"
104
+
105
+ // Structured Bangla calendar conversion
106
+ // `monthIndex` stays numeric; `bn-BD` localizes `day`, `month`, and `year`.
107
+ toBanglaCalendar("2026-03-31");
108
+ // → { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
109
+
110
+ toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
111
+ // → { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
112
+
113
+ const dynamicLocale: "en-BD" | "bn-BD" =
114
+ Math.random() > 0.5 ? "en-BD" : "bn-BD";
115
+ const structuredBangla = toBanglaCalendar("2026-03-31", {
116
+ locale: dynamicLocale
117
+ });
118
+ // → BanglaCalendarResult<"en-BD" | "bn-BD">
119
+
120
+ const locale: "en-BD" | "bn-BD" = Math.random() > 0.5 ? "en-BD" : "bn-BD";
121
+ const structuredBangla = toBanglaCalendar("2026-03-31", { locale });
122
+ // → TypeScript infers BanglaCalendarResult<"en-BD" | "bn-BD">
123
+
124
+ format("2026-03-31", { mode: "bangla" });
125
+ // → "17th Chaitra 1432"
126
+
127
+ format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
95
128
  // → "১৭ই চৈত্র ১৪৩২ বঙ্গাব্দ"
96
-
129
+
97
130
  format("2026-04-14", { mode: "bangla", locale: "bn-BD" });
98
131
  // → "১লা বৈশাখ ১৪৩৩"
99
132
 
@@ -103,6 +136,14 @@ toHijriCalendar("2026-03-31");
103
136
  toHijriCalendar("2026-03-31", { locale: "bn-BD" });
104
137
  // → { day: "১১", month: "শাওয়াল", monthIndex: 10, year: "১৪৪৭" }
105
138
 
139
+ const structuredHijri = toHijriCalendar("2026-03-31", {
140
+ locale: dynamicLocale
141
+ });
142
+ // → HijriCalendarResult<"en-BD" | "bn-BD">
143
+
144
+ const structuredHijri = toHijriCalendar("2026-03-31", { locale });
145
+ // → TypeScript infers HijriCalendarResult<"en-BD" | "bn-BD">
146
+
106
147
  toHijriCalendar("2026-03-31", { timeZone: "UTC" });
107
148
  // → { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
108
149
 
@@ -122,182 +163,195 @@ format("2026-03-31", { mode: "hijri", locale: "bn-BD" });
122
163
 
123
164
  format(new Date(2026, 2, 31, 15, 4), {
124
165
  mode: "standard",
125
- weekday: "short",
126
- hour: "numeric",
127
- minute: "2-digit"
128
- });
129
- // → "Tue, 31st Mar 2026, 15:04"
130
-
131
- format(new Date(2026, 2, 31, 21, 4, 9), {
132
- mode: "standard",
133
- weekday: "long",
134
- hour: "2-digit",
135
- minute: "2-digit",
136
- second: "2-digit",
137
- hour12: true
138
- });
139
- // → "Tuesday, 31st Mar 2026, 09:04:09 PM"
140
-
166
+ weekday: "short",
167
+ hour: "numeric",
168
+ minute: "2-digit"
169
+ });
170
+ // → "Tue, 31st Mar 2026, 15:04"
171
+
172
+ format(new Date(2026, 2, 31, 21, 4, 9), {
173
+ mode: "standard",
174
+ weekday: "long",
175
+ hour: "2-digit",
176
+ minute: "2-digit",
177
+ second: "2-digit",
178
+ hour12: true
179
+ });
180
+ // → "Tuesday, 31st Mar 2026, 09:04:09 PM"
181
+
141
182
  fromNow(new Date(Date.now() - 86400000), { numeric: "auto" });
142
183
  // Output depends on the current clock.
143
-
184
+
144
185
  fromNow(new Date(), { numeric: "auto" });
145
186
  // Output depends on the current clock.
146
- ```
147
-
187
+
188
+ fromNow("2026-03-31T10:00:00Z", {
189
+ baseDate: "2026-03-31T12:00:00Z",
190
+ style: "short"
191
+ });
192
+ // → "2h ago"
193
+
194
+ parseDateDetailed("31 Mar 26", { strict: true });
195
+ // → { success: false, reason: "strict_mismatch", ... }
196
+ ```
197
+
148
198
  > Use `format()` for everything. Choose a mode (`standard`, `bangla`, `hijri`, `hybrid`) or pass a token pattern.
149
-
150
- ```ts
151
- // Show today's Bangla date in your app header
199
+
200
+ ```ts
201
+ // Show today's Bangla date in your app header
152
202
  format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
153
203
  // → "১৭ চৈত্র ১৪৩২ বঙ্গাব্দ"
154
- ```
155
-
156
- ## Features
157
-
158
- ### Standard Formatting
159
-
160
- ```ts
161
- import { format } from "@coreify/tarikh";
162
-
204
+ ```
205
+
206
+ ## Features
207
+
208
+ ### Standard Formatting
209
+
210
+ ```ts
211
+ import { format } from "@coreify/tarikh";
212
+
163
213
  format("2026-03-31", { mode: "standard" });
164
- // → "31st Mar 2026"
165
-
214
+ // → "31st Mar 2026"
215
+
166
216
  format("2026-03-31", { mode: "standard", locale: "bn-BD" });
167
217
  // → "৩১শে মার্চ ২০২৬ খ্রিস্টাব্দ"
168
-
218
+
169
219
  format("2026-03-31", { mode: "standard", month: "long", year: "2-digit" });
170
- // → "31st March 26"
171
-
172
- format(new Date(2026, 2, 31, 15, 4, 9), {
173
- mode: "standard",
174
- weekday: "long",
175
- hour: "2-digit",
176
- minute: "2-digit",
177
- second: "2-digit",
178
- hour12: true
179
- });
180
- // → "Tuesday, 31st Mar 2026, 03:04:09 PM"
181
- ```
182
-
183
- **Options:** `locale` (`"en-BD"` | `"bn-BD"`), `month` (`"short"` | `"long"`), `year` (`"numeric"` | `"2-digit"`), `day` (`"numeric"` | `"2-digit"`), `weekday` (`"short"` | `"long"`), `hour` / `minute` / `second` (`"numeric"` | `"2-digit"`), `hour12` (`boolean`)
184
-
185
- ### Pattern Formatting
186
-
187
- ```ts
188
- import { format } from "@coreify/tarikh";
189
-
220
+ // → "31st March 26"
221
+
222
+ format(new Date(2026, 2, 31, 15, 4, 9), {
223
+ mode: "standard",
224
+ weekday: "long",
225
+ hour: "2-digit",
226
+ minute: "2-digit",
227
+ second: "2-digit",
228
+ hour12: true
229
+ });
230
+ // → "Tuesday, 31st Mar 2026, 03:04:09 PM"
231
+ ```
232
+
233
+ **Options:** `locale` (`"en-BD"` | `"bn-BD"`), `month` (`"short"` | `"long"`), `year` (`"numeric"` | `"2-digit"`), `day` (`"numeric"` | `"2-digit"`), `weekday` (`"short"` | `"long"`), `hour` / `minute` / `second` (`"numeric"` | `"2-digit"`), `hour12` (`boolean`)
234
+
235
+ **Presets:** `preset: "date" | "dateTime" | "isoLike"`
236
+
237
+ ### Pattern Formatting
238
+
239
+ ```ts
240
+ import { format } from "@coreify/tarikh";
241
+
190
242
  format("2026-03-31", { pattern: "DD MMM YYYY" });
191
- // → "31 Mar 2026"
192
-
243
+ // → "31 Mar 2026"
244
+
193
245
  format("2026-03-31", { pattern: "DD MMMM YYYY", locale: "bn-BD" });
194
- // → "৩১ মার্চ ২০২৬"
195
-
246
+ // → "৩১ মার্চ ২০২৬"
247
+
196
248
  format("2026-03-31", { pattern: "DD/MM/YYYY" });
197
- // → "31/03/2026"
198
-
199
- format(new Date(2026, 2, 31, 15, 4, 9), {
200
- pattern: "ddd, D MMM YYYY HH:mm:ss"
201
- });
202
- // → "Tue, 31 Mar 2026 15:04:09"
203
-
204
- format(new Date(2026, 2, 31, 9, 4), {
205
- pattern: "ddd, D MMM YYYY h:mm a",
206
- locale: "bn-BD"
207
- });
208
- // → "মঙ্গল, ৩১ মার্চ ২০২৬ ৯:০৪ পূর্বাহ্ণ"
209
-
210
- format(new Date(2026, 2, 31, 21, 4, 9), {
211
- pattern: "dddd, D MMM YYYY hh:mm:ss A"
212
- });
213
- // → "Tuesday, 31 Mar 2026 09:04:09 PM"
214
- ```
215
-
249
+ // → "31/03/2026"
250
+
251
+ format(new Date(2026, 2, 31, 15, 4, 9), {
252
+ pattern: "ddd, D MMM YYYY HH:mm:ss"
253
+ });
254
+ // → "Tue, 31 Mar 2026 15:04:09"
255
+
256
+ format(new Date(2026, 2, 31, 9, 4), {
257
+ pattern: "ddd, D MMM YYYY h:mm a",
258
+ locale: "bn-BD"
259
+ });
260
+ // → "মঙ্গল, ৩১ মার্চ ২০২৬ ৯:০৪ পূর্বাহ্ণ"
261
+
262
+ format(new Date(2026, 2, 31, 21, 4, 9), {
263
+ pattern: "dddd, D MMM YYYY hh:mm:ss A"
264
+ });
265
+ // → "Tuesday, 31 Mar 2026 09:04:09 PM"
266
+ ```
267
+
216
268
  > `format()` is the primary API. Use `{ mode }` for date behavior or `{ pattern }` for token formatting. `mode` and `pattern` are mutually exclusive.
217
-
218
- **Tokens:** `dddd`, `ddd`, `DD`, `D`, `MMMM`, `MMM`, `MM`, `M`, `YYYY`, `YY`, `HH`, `H`, `hh`, `h`, `mm`, `m`, `ss`, `s`, `A`, `a`
219
-
269
+
270
+ **Tokens:** `dddd`, `ddd`, `DD`, `D`, `MMMM`, `MMM`, `MM`, `M`, `YYYY`, `YY`, `HH`, `H`, `hh`, `h`, `mm`, `m`, `ss`, `s`, `A`, `a`
271
+
220
272
  > Use square brackets to keep literal text untouched by token replacement:
221
-
222
- ```ts
223
- format(new Date(2026, 2, 31, 15, 4), { pattern: "[Today at] h:mm a" });
224
- // → "Today at 3:04 pm"
225
- ```
226
-
273
+
274
+ ```ts
275
+ format(new Date(2026, 2, 31, 15, 4), { pattern: "[Today at] h:mm a" });
276
+ // → "Today at 3:04 pm"
277
+ ```
278
+
227
279
  > Bracket literals are not nestable; the first `]` closes the literal block.
228
-
280
+
229
281
  ## 🇧🇩 Bangla Calendar (Core Feature)
230
282
 
231
- | Bangla calendar | Behavior |
232
- | --------------- | -------- |
233
- | `toBanglaCalendar()` | Returns a structured object |
234
- | Default output | English digits + Latin month names (`en-BD`) |
235
- | `bn-BD` output | Bangla day forms like `১লা`, `২রা`, `৩রা`, `৪ঠা`, `৫ই`, `১৯শে` |
236
- | Spoken mode | Returns `পহেলা`, `দোসরা`, `তেসরা`, `চৌঠা` |
237
- | `variant: "pohela"` | Keeps the standard `পহেলা` spelling |
238
- | `variant: "poyla"` | Uses `পয়লা` for day 1 |
239
- | `monthIndex` | Stays numeric in both cases |
283
+ | Bangla calendar | Behavior |
284
+ | -------------------- | -------------------------------------------------------------- |
285
+ | `toBanglaCalendar()` | Returns a structured object |
286
+ | Default output | English digits + Latin month names (`en-BD`) |
287
+ | `bn-BD` output | Bangla day forms like `১লা`, `২রা`, `৩রা`, `৪ঠা`, `৫ই`, `১৯শে` |
288
+ | Spoken mode | Returns `পহেলা`, `দোসরা`, `তেসরা`, `চৌঠা` |
289
+ | `variant: "pohela"` | Keeps the standard `পহেলা` spelling |
290
+ | `variant: "poyla"` | Uses `পয়লা` for day 1 |
291
+ | `monthIndex` | Stays numeric in both cases |
240
292
 
241
293
  ```ts
242
294
  import {
243
295
  format,
244
- formatBanglaCalendarDay,
245
- toBanglaCalendar
246
- } from "@coreify/tarikh";
247
-
248
- toBanglaCalendar("2026-03-31");
249
- // → { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
250
-
251
- toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
252
- // → { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
253
-
254
- format("2026-03-31", { mode: "bangla" });
255
- // → "17th Chaitra 1432"
256
-
257
- format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
296
+ formatBanglaCalendarDay,
297
+ toBanglaCalendar
298
+ } from "@coreify/tarikh";
299
+
300
+ toBanglaCalendar("2026-03-31");
301
+ // → { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
302
+
303
+ toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
304
+ // → { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
305
+
306
+ format("2026-03-31", { mode: "bangla" });
307
+ // → "17th Chaitra 1432"
308
+
309
+ format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
258
310
  // → "১৭ই চৈত্র ১৪৩২ বঙ্গাব্দ"
259
-
260
- format("2026-04-14", { mode: "bangla" });
261
- // → "1st Baishakh 1433"
262
-
263
- format("2026-04-14", { mode: "bangla", locale: "bn-BD", format: "spoken" });
311
+
312
+ format("2026-04-14", { mode: "bangla" });
313
+ // → "1st Baishakh 1433"
314
+
315
+ format("2026-04-14", { mode: "bangla", locale: "bn-BD", format: "spoken" });
264
316
  // → "পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
265
-
266
- format("2026-04-14", {
267
- mode: "bangla",
268
- locale: "bn-BD",
269
- format: "spoken",
270
- variant: "poyla"
271
- });
317
+
318
+ format("2026-04-14", {
319
+ mode: "bangla",
320
+ locale: "bn-BD",
321
+ format: "spoken",
322
+ variant: "poyla"
323
+ });
272
324
  // → "পয়লা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
273
-
274
- // Show today's Bangla date in your app header
325
+
326
+ // Show today's Bangla date in your app header
275
327
  format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
276
328
  // → "১৭ চৈত্র ১৪৩২ বঙ্গাব্দ" (example; depends on the current date)
277
-
278
- formatBanglaCalendarDay(21);
279
- // → "২১শে"
280
-
281
- formatBanglaCalendarDay(1, { format: "spoken" });
282
- // → "পহেলা"
283
-
284
- formatBanglaCalendarDay(1, { format: "spoken", variant: "poyla" });
285
- // → "পয়লা"
286
-
329
+
330
+ formatBanglaCalendarDay(21);
331
+ // → "২১শে"
332
+
333
+ formatBanglaCalendarDay(1, { format: "spoken" });
334
+ // → "পহেলা"
335
+
336
+ formatBanglaCalendarDay(1, { format: "spoken", variant: "poyla" });
337
+ // → "পয়লা"
338
+
287
339
  formatBanglaCalendarDay(1, { format: "spoken", variant: "pohela" });
288
340
  // → "পহেলা"
289
341
  ```
290
342
 
291
343
  ### Hijri Calendar
292
344
 
293
- | Hijri calendar | Behavior |
294
- | -------------- | -------- |
295
- | `toHijriCalendar()` | Returns a structured object |
296
- | Default timezone | `Asia/Dhaka` |
297
- | `timeZone` override | Accepts the exported `HIJRI_TIME_ZONES` values |
298
- | Default output | English month/day/year with `AH` |
299
- | `bn-BD` output | Bangla digits and the `হিজরি` suffix |
300
- | `UTC` override | Exposes the alternative canonical Hijri result |
345
+ | Hijri calendar | Behavior |
346
+ | ---------------------- | -------------------------------------------------- |
347
+ | `toHijriCalendar()` | Returns a structured object |
348
+ | Default timezone | `Asia/Dhaka` |
349
+ | `timeZone` override | Accepts the exported `HIJRI_TIME_ZONES` values |
350
+ | Default backend | `Intl` with `islamic-umalqura` |
351
+ | `hijriSystem` override | Accepts `"islamic-umalqura"` and `"islamic-civil"` |
352
+ | Default output | English month/day/year with `AH` |
353
+ | `bn-BD` output | Bangla digits and the `হিজরি` suffix |
354
+ | `UTC` override | Exposes the alternative canonical Hijri result |
301
355
 
302
356
  ```ts
303
357
  import { HIJRI_TIME_ZONES, format, toHijriCalendar } from "@coreify/tarikh";
@@ -313,6 +367,9 @@ toHijriCalendar("2026-03-31", { locale: "bn-BD" });
313
367
  toHijriCalendar("2026-03-31", { timeZone: "UTC" });
314
368
  // → { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
315
369
 
370
+ toHijriCalendar("2026-03-31", { hijriSystem: "islamic-civil" });
371
+ // → Civil Hijri output backed by Intl
372
+
316
373
  // Supported values: defaultHijriZone === "Asia/Dhaka", alternateHijriZone === "UTC"
317
374
 
318
375
  format("2026-03-31", { mode: "hijri" });
@@ -325,172 +382,211 @@ format("2026-03-31", { mode: "hijri", locale: "bn-BD" });
325
382
  // → "১২ই শাওয়াল ১৪৪৭ হিজরি"
326
383
  ```
327
384
 
385
+ > Hijri output is powered by `Intl` and defaults to `islamic-umalqura`. Regional moon-sighting expectations can differ from the returned value, so use `hijriSystem` and `timeZone` intentionally.
386
+
328
387
  ### Hybrid Formatting
329
-
330
- | Mixing rule | Summary |
331
- | ----------- | ------- |
388
+
389
+ | Mixing rule | Summary |
390
+ | ----------------- | ------------------------------------------------------------- |
332
391
  | Hybrid formatting | Mix English and Bangla independently for day, month, and year |
333
-
334
- ```ts
335
- import { format } from "@coreify/tarikh";
336
-
392
+
393
+ ```ts
394
+ import { format } from "@coreify/tarikh";
395
+
337
396
  format("2026-03-31", { mode: "hybrid" });
338
- // → "31 মার্চ 2026"
339
-
397
+ // → "31 মার্চ 2026"
398
+
340
399
  format("2026-03-31", {
341
- mode: "hybrid",
342
- digits: "bn",
343
- month: "bn",
344
- year: "en"
345
- });
346
- // → "৩১ মার্চ 2026"
347
- ```
348
-
349
- ### Bangla Digits
350
-
351
- ```ts
352
- import { toBanglaDigits, toEnglishDigits } from "@coreify/tarikh";
353
-
354
- toBanglaDigits("31 March 2026");
355
- // → "৩১ March ২০২৬"
356
-
357
- toEnglishDigits("৩১ মার্চ ২০২৬");
358
- // → "31 মার্চ 2026"
359
- ```
360
-
361
- ### Relative Time
362
-
363
- ```ts
364
- import { fromNow } from "@coreify/tarikh";
365
-
400
+ mode: "hybrid",
401
+ digits: "bn",
402
+ month: "bn",
403
+ year: "en"
404
+ });
405
+ // → "৩১ মার্চ 2026"
406
+ ```
407
+
408
+ ### Bangla Digits
409
+
410
+ ```ts
411
+ import { toBanglaDigits, toEnglishDigits } from "@coreify/tarikh";
412
+
413
+ toBanglaDigits("31 March 2026");
414
+ // → "৩১ March ২০২৬"
415
+
416
+ toEnglishDigits("৩১ মার্চ ২০২৬");
417
+ // → "31 মার্চ 2026"
418
+ ```
419
+
420
+ ### Relative Time
421
+
422
+ ```ts
423
+ import { fromNow } from "@coreify/tarikh";
424
+
366
425
  fromNow(new Date(Date.now() - 86400000));
367
426
  // Output depends on the current clock.
368
-
427
+
369
428
  fromNow(new Date(Date.now() - 86400000), { locale: "bn-BD" });
370
429
  // Output depends on the current clock.
371
-
430
+
372
431
  fromNow(new Date(Date.now() + 3600000));
373
432
  // Output depends on the current clock.
374
-
433
+
375
434
  fromNow(new Date(Date.now() - 86400000), { numeric: "auto" });
376
435
  // Output depends on the current clock.
377
-
436
+
378
437
  fromNow(new Date(Date.now() + 86400000), {
379
438
  locale: "bn-BD",
380
439
  numeric: "auto"
381
440
  });
382
441
  // Output depends on the current clock.
383
- ```
384
-
385
- ### Parsing
386
-
387
- ```ts
388
- import { parseDate } from "@coreify/tarikh";
389
-
390
- parseDate("৩১ মার্চ ২০২৬");
391
- // Date object (March 31, 2026)
392
-
393
- parseDate("17 Chaitra 1432", { calendar: "bangla" });
394
- // → Date object (March 31, 2026)
395
-
396
- // Legacy spellings (Boishakh, Joishtho, Choitro, etc.) are still accepted.
397
-
398
- parseDate("১৭ চৈত্র ১৪৩২", { calendar: "bangla" });
399
- // Date object (March 31, 2026)
400
-
401
- parseDate("31 March 2026");
402
- // → Date object (March 31, 2026)
403
-
404
- parseDate("March 31, 2026");
405
- // → Date object (March 31, 2026)
406
-
407
- parseDate("31-Mar-2026");
408
- // → Date object (March 31, 2026)
409
-
410
- parseDate("2026/03/31");
411
- // → Date object (March 31, 2026)
412
-
413
- parseDate("2026.03.31");
414
- // → Date object (March 31, 2026)
415
-
416
- parseDate("2026-03-31T15:30:00Z");
417
- // → Date object (March 31, 2026, 3:30 PM UTC)
418
-
419
- // `toDate()` accepts the same Gregorian string forms as `parseDate()`,
420
- // plus `Date` objects and timestamps.
421
- // Supported string shapes:
422
- // - `YYYY-MM-DD`
423
- // - `YYYY/MM/DD`
424
- // - `YYYY.MM.DD`
425
- // - `YYYY-M-D`, `YYYY/M/D`, `YYYY.M.D`
426
- // - `YYYY-MM-DDTHH:mm[:ss[.fraction]][Z|±HH:mm]`
427
- // - `DD Month YYYY`
428
- // - `Month DD, YYYY`
429
- // - `DD-Month-YYYY`
430
- // - Bangla calendar strings like `১৭ চৈত্র ১৪৩২`
431
- // - Common Bangla month aliases like `Boishakh`, `Poush`, `Falgun`, `Asharh`
432
- ```
433
-
434
- ### Utilities
435
-
436
- ```ts
437
- import {
438
- isToday,
439
- isYesterday,
440
- isTomorrow,
441
- startOfDay,
442
- endOfDay,
443
- startOfMonth,
444
- endOfMonth,
445
- startOfYear,
446
- endOfYear,
447
- addDays,
448
- subDays,
449
- addMonths,
450
- subMonths,
451
- addYears,
452
- subYears,
453
- getBanglaMonth
454
- } from "@coreify/tarikh";
455
-
456
- isToday(new Date()); // → true
457
- isYesterday(subDays(new Date(), 1)); // → true
458
- isTomorrow(addDays(new Date(), 1)); // → true
459
- startOfMonth(new Date()); // → Date at the start of this month
460
- endOfMonth(new Date()); // → Date at the end of this month
461
- addMonths("2026-01-31", 1); // → 2026-02-28
462
- addYears(new Date(2024, 1, 29), 1); // → 2025-02-28
463
-
464
- getBanglaMonth(3); // → "মার্চ"
465
- getBanglaMonth(3, "short"); // "মার্চ"
466
- getBanglaMonth(12); // → "ডিসেম্বর"
467
- ```
468
-
469
- ### Constants
470
-
471
- ```ts
472
- import {
473
- BANGLA_MONTHS_FULL,
474
- BANGLA_MONTHS_SHORT,
475
- BANGLA_CALENDAR_MONTHS,
476
- BANGLA_CALENDAR_MONTHS_EN,
477
- BANGLA_WEEKDAYS_FULL,
478
- BANGLA_WEEKDAYS_SHORT,
479
- ENGLISH_WEEKDAYS_FULL,
480
- ENGLISH_WEEKDAYS_SHORT,
481
- BANGLA_DIGITS,
482
- ENGLISH_DIGITS
483
- } from "@coreify/tarikh";
484
- ```
485
-
442
+
443
+ fromNow("2026-03-31T10:00:00Z", {
444
+ baseDate: "2026-03-31T12:00:00Z",
445
+ style: "short"
446
+ });
447
+ // "2h ago"
448
+
449
+ fromNow(new Date(Date.now() - 30000), {
450
+ threshold: { justNow: 60000 }
451
+ });
452
+ // "just now"
453
+ ```
454
+
455
+ ### Parsing
456
+
457
+ ```ts
458
+ import { parseDate, parseDateDetailed } from "@coreify/tarikh";
459
+
460
+ parseDate("৩১ মার্চ ২০২৬");
461
+ // → Date object (March 31, 2026)
462
+
463
+ parseDate("17 Chaitra 1432", { calendar: "bangla" });
464
+ // → Date object (March 31, 2026)
465
+
466
+ // Legacy spellings (Boishakh, Joishtho, Choitro, etc.) are still accepted.
467
+
468
+ parseDate("১৭ চৈত্র ১৪৩২", { calendar: "bangla" });
469
+ // → Date object (March 31, 2026)
470
+
471
+ parseDate("31 March 2026");
472
+ // → Date object (March 31, 2026)
473
+
474
+ parseDate("March 31, 2026");
475
+ // → Date object (March 31, 2026)
476
+
477
+ parseDate("31-Mar-2026");
478
+ // Date object (March 31, 2026)
479
+
480
+ parseDate("2026/03/31");
481
+ // Date object (March 31, 2026)
482
+
483
+ parseDate("2026.03.31");
484
+ // Date object (March 31, 2026)
485
+
486
+ parseDate("2026-03-31T15:30:00Z");
487
+ // Date object (March 31, 2026, 3:30 PM UTC)
488
+
489
+ parseDate("31 Mar 26", { strict: true });
490
+ // null
491
+
492
+ parseDateDetailed("31 Mar 26", { strict: true });
493
+ // → { success: false, reason: "strict_mismatch", ... }
494
+
495
+ // `toDate()` accepts the same Gregorian string forms as `parseDate()`,
496
+ // plus `Date` objects and timestamps.
497
+ // Supported string shapes:
498
+ // - `YYYY-MM-DD`
499
+ // - `YYYY/MM/DD`
500
+ // - `YYYY.MM.DD`
501
+ // - `YYYY-M-D`, `YYYY/M/D`, `YYYY.M.D`
502
+ // - `YYYY-MM-DDTHH:mm[:ss[.fraction]][Z|±HH:mm]`
503
+ // - `DD Month YYYY`
504
+ // - `Month DD, YYYY`
505
+ // - `DD-Month-YYYY`
506
+ // - Bangla calendar strings like `১৭ চৈত্র ১৪৩২`
507
+ // - Common Bangla month aliases like `Boishakh`, `Poush`, `Falgun`, `Asharh`
508
+ ```
509
+
510
+ ### Global Defaults
511
+
512
+ ```ts
513
+ import { format, getDefaults, setDefaults } from "@coreify/tarikh";
514
+
515
+ setDefaults({
516
+ locale: "bn-BD",
517
+ mode: "standard",
518
+ month: "long",
519
+ timeZone: "UTC",
520
+ hijriSystem: "islamic-civil"
521
+ });
522
+
523
+ getDefaults();
524
+ // → { locale: "bn-BD", mode: "standard", month: "long", timeZone: "UTC", hijriSystem: "islamic-civil" }
525
+
526
+ format("2026-03-31");
527
+ // → Uses the configured defaults
528
+ ```
529
+
530
+ ### Utilities
531
+
532
+ ```ts
533
+ import {
534
+ isToday,
535
+ isYesterday,
536
+ isTomorrow,
537
+ startOfDay,
538
+ endOfDay,
539
+ startOfMonth,
540
+ endOfMonth,
541
+ startOfYear,
542
+ endOfYear,
543
+ addDays,
544
+ subDays,
545
+ addMonths,
546
+ subMonths,
547
+ addYears,
548
+ subYears,
549
+ getBanglaMonth
550
+ } from "@coreify/tarikh";
551
+
552
+ isToday(new Date()); // → true
553
+ isYesterday(subDays(new Date(), 1)); // → true
554
+ isTomorrow(addDays(new Date(), 1)); // → true
555
+ startOfMonth(new Date()); // → Date at the start of this month
556
+ endOfMonth(new Date()); // → Date at the end of this month
557
+ addMonths("2026-01-31", 1); // → 2026-02-28
558
+ addYears(new Date(2024, 1, 29), 1); // → 2025-02-28
559
+
560
+ getBanglaMonth(3); // → "মার্চ"
561
+ getBanglaMonth(3, "short"); // → "মার্চ"
562
+ getBanglaMonth(12); // → "ডিসেম্বর"
563
+ ```
564
+
565
+ ### Constants
566
+
567
+ ```ts
568
+ import {
569
+ BANGLA_MONTHS_FULL,
570
+ BANGLA_MONTHS_SHORT,
571
+ BANGLA_CALENDAR_MONTHS,
572
+ BANGLA_CALENDAR_MONTHS_EN,
573
+ BANGLA_WEEKDAYS_FULL,
574
+ BANGLA_WEEKDAYS_SHORT,
575
+ ENGLISH_WEEKDAYS_FULL,
576
+ ENGLISH_WEEKDAYS_SHORT,
577
+ BANGLA_DIGITS,
578
+ ENGLISH_DIGITS
579
+ } from "@coreify/tarikh";
580
+ ```
581
+
486
582
  ## React Components
487
583
 
488
- | React export | Purpose |
489
- | ------------ | ------- |
490
- | `Tarikh` | Default semantic `<time>` formatter |
491
- | `Tarikh.Relative` | Relative time rendering |
492
- | `Tarikh.Bangla` | Bangla calendar rendering |
493
- | `Tarikh.Hijri` | Hijri calendar rendering |
584
+ | React export | Purpose |
585
+ | ----------------- | ----------------------------------- |
586
+ | `Tarikh` | Default semantic `<time>` formatter |
587
+ | `Tarikh.Relative` | Relative time rendering |
588
+ | `Tarikh.Bangla` | Bangla calendar rendering |
589
+ | `Tarikh.Hijri` | Hijri calendar rendering |
494
590
 
495
591
  > Import from `@coreify/tarikh/react` only when you need the React components.
496
592
 
@@ -503,22 +599,24 @@ const date = "2026-03-31";
503
599
  <Tarikh.Relative value={date} />
504
600
  <Tarikh.Bangla value={date} locale="bn-BD" />
505
601
  <Tarikh.Hijri value={date} locale="bn-BD" />
602
+ <Tarikh.Relative value={date} relativeStyle="short" />
603
+ ```
604
+
605
+ ```bash
606
+ npm install @coreify/tarikh react
506
607
  ```
507
-
508
- ```bash
509
- npm install @coreify/tarikh react
510
- ```
511
-
512
- | React detail | Notes |
513
- | ------------ | ----- |
514
- | Semantics | Renders `<time>` elements with `dateTime` and `aria-label` |
515
- | Runtime | SSR-safe, tree-shakeable, zero runtime dependencies beyond React |
516
- | Roles | `Tarikh` standard formatting, `Tarikh.Relative` relative time, `Tarikh.Bangla` Bangla calendar, `Tarikh.Hijri` Hijri calendar |
517
-
608
+
609
+ | React detail | Notes |
610
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
611
+ | Semantics | Renders `<time>` elements with `dateTime` and `aria-label` |
612
+ | Runtime | SSR-safe, tree-shakeable, zero runtime dependencies beyond React |
613
+ | Roles | `Tarikh` standard formatting, `Tarikh.Relative` relative time, `Tarikh.Bangla` Bangla calendar, `Tarikh.Hijri` Hijri calendar |
614
+ | Relative prop note | Use `relativeStyle` instead of `style` on `Tarikh.Relative` to avoid colliding with the native DOM `style` prop |
615
+
518
616
  ## What `Intl.DateTimeFormat` cannot do
519
617
 
520
- | Why `Intl` falls short | Summary |
521
- | --------------------- | ------- |
618
+ | Why `Intl` falls short | Summary |
619
+ | ----------------------------- | --------------------------------------------------- |
522
620
  | Bangladesh-focused formatting | Needs Bangla calendar and culturally correct output |
523
621
 
524
622
  | Feature | Intl | @coreify/tarikh |
@@ -526,32 +624,49 @@ npm install @coreify/tarikh react
526
624
  | Bangla calendar (বৈশাখ → চৈত্র) | No | Yes |
527
625
  | Hijri calendar | Partial | Yes |
528
626
  | Bangla digits in dates | Partial | Yes |
529
- | Hybrid formatting (mixed en/bn) | No | Yes |
530
- | Bangla calendar date parsing | No | Yes |
531
- | Relative time in Bangla | No | Yes |
532
- | SSR-safe React components | N/A | Yes |
533
-
627
+ | Hybrid formatting (mixed en/bn) | No | Yes |
628
+ | Bangla calendar date parsing | No | Yes |
629
+ | Relative time in Bangla | No | Yes |
630
+ | SSR-safe React components | N/A | Yes |
631
+
632
+ ## Common Pitfalls
633
+
634
+ | Pitfall | What to watch for |
635
+ | ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
636
+ | Hijri mismatch | Tarikh uses `Intl` and defaults to `islamic-umalqura`; local moon-sighting calendars may differ |
637
+ | Time zone expectations | Hijri conversion changes with `timeZone`, so `Asia/Dhaka` and `UTC` can return different days |
638
+ | `short` vs `long` month output | Standard mode defaults to short English month names but long Bangla month names unless you override `month` |
639
+ | Strict parsing | `strict: true` rejects loose helpers like two-digit years and legacy Bangla month aliases |
640
+
534
641
  ## TypeScript
535
642
 
536
- | Type | Purpose |
537
- | ---- | ------- |
538
- | `FormatOptions` | Primary object-based formatting contract |
539
- | `TarikhProps` | Props for the main React `<Tarikh />` component |
540
- | `HIJRI_TIME_ZONES` | Canonical supported Hijri time zones (`Asia/Dhaka`, `UTC`) |
541
- | Type-level contract | When using `pattern`, `mode` is intentionally disallowed in TypeScript |
643
+ | Type | Purpose |
644
+ | -------------------------------- | ---------------------------------------------------------------------- |
645
+ | `FormatOptions` | Primary object-based formatting contract |
646
+ | `BanglaCalendarResult<TLocale>` | Locale-aware structured Bangla calendar return type |
647
+ | `HijriCalendarResult<TLocale>` | Locale-aware structured Hijri return type |
648
+ | `BanglaCalendarOptions<TLocale>` | Locale-aware structured Bangla conversion options |
649
+ | `HijriCalendarOptions<TLocale>` | Locale-aware structured Hijri conversion options |
650
+ | `TarikhProps` | Props for the main React `<Tarikh />` component |
651
+ | `HIJRI_TIME_ZONES` | Canonical supported Hijri time zones (`Asia/Dhaka`, `UTC`) |
652
+ | Type-level contract | When using `pattern`, `mode` is intentionally disallowed in TypeScript |
542
653
 
543
654
  ```ts
544
655
  import type {
545
- Locale,
546
- FormatMode,
547
- FormatOptions,
548
- DateInput,
549
- RelativeTimeOptions
550
- } from "@coreify/tarikh";
551
-
552
- import type { TarikhProps } from "@coreify/tarikh/react";
553
- ```
554
-
555
- ## License
556
-
557
- MIT
656
+ BanglaCalendarOptions,
657
+ BanglaCalendarResult,
658
+ Locale,
659
+ FormatMode,
660
+ FormatOptions,
661
+ DateInput,
662
+ HijriCalendarOptions,
663
+ HijriCalendarResult,
664
+ RelativeTimeOptions
665
+ } from "@coreify/tarikh";
666
+
667
+ import type { TarikhProps } from "@coreify/tarikh/react";
668
+ ```
669
+
670
+ ## License
671
+
672
+ MIT