@coreify/tarikh 1.0.0 → 1.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 CHANGED
@@ -1,478 +1,557 @@
1
- # @coreify/tarikh
2
-
3
- The Bangladeshi date toolkit for modern apps.
4
-
5
- Format dates, render Bangla calendar, and handle localization correctly.
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
+ > The first JavaScript date library with Bangla and Hijri calendar support.
8
+ > Built for Bangla dates, Bengali calendar conversion, and culturally correct formatting.
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 |
17
+
18
+ ## At a Glance
19
+
20
+ | Snapshot | Example |
21
+ | -------- | ------- |
22
+ | Bangla spoken format | `format("2026-04-14", { mode: "bangla", locale: "bn-BD", format: "spoken" })` |
23
+ | Rendered output | `পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ` |
6
24
 
25
+ ```ts
26
+ format("2026-04-14", {
27
+ mode: "bangla",
28
+ locale: "bn-BD",
29
+ format: "spoken"
30
+ });
31
+ // → "পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
32
+ ```
33
+
34
+ ## Demo
35
+
36
+ | Demo | Link |
37
+ | ---- | ---- |
38
+ | Live demo | [tarikh.js.org](https://tarikh.js.org) |
39
+
7
40
  ## Why this exists
8
41
 
9
- JavaScript's `Intl.DateTimeFormat` and libraries like Day.js / date-fns don't solve these problems:
10
-
11
- - **Bangla calendar** Convert Gregorian dates to Bengali calendar (বৈশাখ, চৈত্র, etc.)
12
- - **Bangla digits** Render `৩১ মার্চ ২০২৬` instead of `31 March 2026`
13
- - **Hybrid formatting** Mix English and Bangla in a single date string
14
- - **Weekday and time formatting** Render weekday, hour, minute, and second output
15
- - **Natural relative time** Use `yesterday`, `tomorrow`, `গতকাল`, `আগামীকাল`, etc.
16
- - **Cultural correctness** Bangladeshi locale-aware formatting out of the box
17
-
18
- `@coreify/tarikh` is a zero-dependency, tree-shakeable, SSR-safe toolkit purpose-built for Bangladesh.
19
-
20
- ## Installation
21
-
22
- ```bash
23
- npm install @coreify/tarikh
24
- ```
25
-
26
- ## Quick Start
27
-
28
- ```ts
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 |
51
+
52
+ > `@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
29
63
  import {
30
- formatDate,
31
- formatBanglaCalendar,
64
+ HIJRI_TIME_ZONES,
65
+ format,
32
66
  fromNow,
33
- toBanglaCalendar
67
+ toBanglaCalendar,
68
+ toHijriCalendar
34
69
  } from "@coreify/tarikh";
35
70
 
36
- formatDate(new Date(), { locale: "bn-BD" });
37
- // → "৩১ মার্চ ২০২৬"
38
-
39
- // Structured Bangla calendar conversion
40
- // `monthIndex` stays numeric; `bn-BD` localizes `day`, `month`, and `year`.
41
- toBanglaCalendar("2026-03-31");
42
- // { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
43
-
44
- toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
45
- // → { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
46
-
47
- formatBanglaCalendar("2026-03-31");
48
- // "17 Chaitra 1432"
49
-
50
- formatBanglaCalendar("2026-03-31", { locale: "bn-BD" });
51
- // → "১৭ই চৈত্র ১৪৩২"
52
-
53
- formatBanglaCalendar("2026-04-14", { locale: "bn-BD" });
71
+ const [defaultHijriZone, utcHijriZone] = HIJRI_TIME_ZONES;
72
+
73
+ // Preferred entry points:
74
+ format("2026-03-31", { mode: "standard" });
75
+ format("2026-03-31", { mode: "bangla" });
76
+ format("2026-03-31", { mode: "hijri" });
77
+ format("2026-03-31", { mode: "hybrid" });
78
+
79
+ // Token-based output still works.
80
+ 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" });
95
+ // → "১৭ই চৈত্র ১৪৩২ বঙ্গাব্দ"
96
+
97
+ format("2026-04-14", { mode: "bangla", locale: "bn-BD" });
54
98
  // → "১লা বৈশাখ ১৪৩৩"
55
99
 
56
- formatDate(new Date(2026, 2, 31, 15, 4), {
57
- weekday: "short",
58
- hour: "numeric",
59
- minute: "2-digit"
60
- });
61
- // → "Tue, 31 Mar 2026, 15:04"
62
-
63
- formatDate(new Date(2026, 2, 31, 21, 4, 9), {
64
- weekday: "long",
65
- hour: "2-digit",
66
- minute: "2-digit",
67
- second: "2-digit",
68
- hour12: true
69
- });
70
- // → "Tuesday, 31 Mar 2026, 09:04:09 PM"
71
-
100
+ toHijriCalendar("2026-03-31");
101
+ // → { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
102
+
103
+ toHijriCalendar("2026-03-31", { locale: "bn-BD" });
104
+ // → { day: "১১", month: "শাওয়াল", monthIndex: 10, year: "১৪৪৭" }
105
+
106
+ toHijriCalendar("2026-03-31", { timeZone: "UTC" });
107
+ // { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
108
+
109
+ format("2026-03-31", { mode: "hijri" });
110
+ // "12th Shawwal 1447 AH"
111
+
112
+ format("2026-03-31", { mode: "hijri", timeZone: "UTC" });
113
+ // → "11th Shawwal 1447 AH"
114
+
115
+ | Timezone support | Details |
116
+ | ---------------- | ------- |
117
+ | `timeZone` | Accepts `Asia/Dhaka` and `UTC` |
118
+ | Supported list | Exported as `HIJRI_TIME_ZONES` |
119
+
120
+ format("2026-03-31", { mode: "hijri", locale: "bn-BD" });
121
+ // → "১২ই শাওয়াল ১৪৪৭ হিজরি"
122
+
123
+ format(new Date(2026, 2, 31, 15, 4), {
124
+ 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
+
72
141
  fromNow(new Date(Date.now() - 86400000), { numeric: "auto" });
73
- // "yesterday"
74
-
142
+ // Output depends on the current clock.
143
+
75
144
  fromNow(new Date(), { numeric: "auto" });
76
- // "today"
77
- ```
78
-
79
- ## Features
80
-
81
- ### Date Formatting
82
-
83
- ```ts
84
- import { formatDate } from "@coreify/tarikh";
85
-
86
- formatDate(new Date());
87
- // → "31 Mar 2026"
88
-
89
- formatDate(new Date(), { locale: "bn-BD" });
90
- // → "৩১ মার্চ ২০২৬"
91
-
92
- formatDate(new Date(), { month: "long", year: "2-digit" });
93
- // → "31 March 26"
94
-
95
- formatDate(new Date(2026, 2, 31, 15, 4, 9), {
96
- weekday: "long",
97
- hour: "2-digit",
98
- minute: "2-digit",
99
- second: "2-digit",
100
- hour12: true
101
- });
102
- // → "Tuesday, 31 Mar 2026, 03:04:09 PM"
103
- ```
104
-
105
- **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`)
106
-
107
- ### Token-based Formatting
108
-
109
- ```ts
110
- import { format } from "@coreify/tarikh";
111
-
112
- format(new Date(), "DD MMM YYYY");
113
- // → "31 Mar 2026"
114
-
115
- format(new Date(), "DD MMMM YYYY", { locale: "bn-BD" });
116
- // "৩১ মার্চ ২০২৬"
117
-
118
- format(new Date(), "DD/MM/YYYY");
119
- // "31/03/2026"
120
-
121
- format(new Date(2026, 2, 31, 15, 4, 9), "ddd, D MMM YYYY HH:mm:ss");
122
- // → "Tue, 31 Mar 2026 15:04:09"
123
-
124
- format(new Date(2026, 2, 31, 9, 4), "ddd, D MMM YYYY h:mm a", {
125
- locale: "bn-BD"
126
- });
127
- // → "মঙ্গল, ৩১ মার্চ ২০২৬ ৯:০৪ পূর্বাহ্ণ"
128
-
129
- format(new Date(2026, 2, 31, 21, 4, 9), "dddd, D MMM YYYY hh:mm:ss A");
130
- // "Tuesday, 31 Mar 2026 09:04:09 PM"
131
- ```
132
-
133
- **Tokens:** `dddd`, `ddd`, `DD`, `D`, `MMMM`, `MMM`, `MM`, `M`, `YYYY`, `YY`, `HH`, `H`, `hh`, `h`, `mm`, `m`, `ss`, `s`, `A`, `a`
134
-
135
- ### Bangla Calendar
136
-
137
- Convert Gregorian dates to the Bengali calendar (Bangladesh Revised Calendar, 1987).
138
-
139
- - `toBanglaCalendar()` returns a structured object.
140
- - Default output: English digits + Latin month names (`en-BD`).
141
- - Locale-aware output: Bangla date words like `১লা`, `২রা`, `৩রা`, `৪ঠা`, `৫ই`, `১৯শে` plus Bangla month names (`bn-BD`).
142
- - `monthIndex` remains numeric in both cases.
143
- - `formatBanglaCalendar(..., { locale: "bn-BD", format: "spoken" })` returns spoken day words like `পহেলা`, `দোসরা`, `তেসরা`, `চৌঠা`.
144
- - `formatBanglaCalendarDay(day, { format: "spoken" })` returns colloquial spoken forms for the first four days: `পহেলা`, `দোসরা`, `তেসরা`, `চৌঠা`.
145
- - Pass `{ variant: "pohela" }` to keep the standard `পহেলা` spelling explicitly, or `{ variant: "poyla" }` to get `পয়লা` for day 1. The parser also accepts the common `পয়লা` spelling.
145
+ // Output depends on the current clock.
146
+ ```
147
+
148
+ > 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
152
+ format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
153
+ // "১৭ চৈত্র ১৪৩২ বঙ্গাব্দ"
154
+ ```
155
+
156
+ ## Features
157
+
158
+ ### Standard Formatting
159
+
160
+ ```ts
161
+ import { format } from "@coreify/tarikh";
162
+
163
+ format("2026-03-31", { mode: "standard" });
164
+ // "31st Mar 2026"
165
+
166
+ format("2026-03-31", { mode: "standard", locale: "bn-BD" });
167
+ // "৩১শে মার্চ ২০২৬ খ্রিস্টাব্দ"
168
+
169
+ 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
+
190
+ format("2026-03-31", { pattern: "DD MMM YYYY" });
191
+ // → "31 Mar 2026"
192
+
193
+ format("2026-03-31", { pattern: "DD MMMM YYYY", locale: "bn-BD" });
194
+ // "৩১ মার্চ ২০২৬"
195
+
196
+ 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
+
216
+ > `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
+
220
+ > 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
+
227
+ > Bracket literals are not nestable; the first `]` closes the literal block.
228
+
229
+ ## 🇧🇩 Bangla Calendar (Core Feature)
230
+
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 |
146
240
 
147
241
  ```ts
148
242
  import {
149
- formatBanglaCalendar,
150
- formatBanglaCalendarDay,
151
- toBanglaCalendar
152
- } from "@coreify/tarikh";
153
-
154
- toBanglaCalendar("2026-03-31");
155
- // → { day: 17, month: "Chaitra", monthIndex: 12, year: 1432 }
156
-
157
- toBanglaCalendar("2026-03-31", { locale: "bn-BD" });
158
- // → { day: "১৭", month: "চৈত্র", monthIndex: 12, year: "১৪৩২" }
159
-
160
- formatBanglaCalendar("2026-03-31");
161
- // → "17 Chaitra 1432"
162
-
163
- formatBanglaCalendar("2026-03-31", { locale: "bn-BD" });
164
- // → "১৭ই চৈত্র ১৪৩২"
165
-
166
- formatBanglaCalendar("2026-04-14");
167
- // → "1 Baishakh 1433"
168
-
169
- formatBanglaCalendar("2026-04-14", { locale: "bn-BD", format: "spoken" });
170
- // → "পহেলা বৈশাখ ১৪৩৩"
171
-
172
- formatBanglaCalendar("2026-04-14", {
173
- locale: "bn-BD",
174
- format: "spoken",
175
- variant: "poyla"
176
- });
177
- // → "পয়লা বৈশাখ ১৪৩৩"
178
-
179
- formatBanglaCalendarDay(21);
180
- // "২১শে"
181
-
182
- formatBanglaCalendarDay(1, { format: "spoken" });
183
- // → "পহেলা"
184
-
185
- formatBanglaCalendarDay(1, { format: "spoken", variant: "poyla" });
186
- // → "পয়লা"
187
-
243
+ 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" });
258
+ // → "১৭ই চৈত্র ১৪৩২ বঙ্গাব্দ"
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" });
264
+ // → "পহেলা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
265
+
266
+ format("2026-04-14", {
267
+ mode: "bangla",
268
+ locale: "bn-BD",
269
+ format: "spoken",
270
+ variant: "poyla"
271
+ });
272
+ // → "পয়লা বৈশাখ ১৪৩৩ বঙ্গাব্দ"
273
+
274
+ // Show today's Bangla date in your app header
275
+ format("2026-03-31", { mode: "bangla", locale: "bn-BD" });
276
+ // "১৭ চৈত্র ১৪৩২ বঙ্গাব্দ" (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
+
188
287
  formatBanglaCalendarDay(1, { format: "spoken", variant: "pohela" });
189
288
  // → "পহেলা"
190
289
  ```
191
290
 
192
- ### Hybrid Formatting
291
+ ### Hijri Calendar
193
292
 
194
- Mix English and Bangla independently for day, month, and year.
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 |
195
301
 
196
302
  ```ts
197
- import { formatHybridDate } from "@coreify/tarikh";
303
+ import { HIJRI_TIME_ZONES, format, toHijriCalendar } from "@coreify/tarikh";
198
304
 
199
- formatHybridDate(new Date());
200
- // → "31 মার্চ 2026"
305
+ const [defaultHijriZone, alternateHijriZone] = HIJRI_TIME_ZONES;
201
306
 
202
- formatHybridDate(new Date(), { digits: "bn", month: "bn", year: "en" });
203
- // → "৩১ মার্চ 2026"
204
- ```
307
+ toHijriCalendar("2026-03-31");
308
+ // → { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
205
309
 
206
- ### Bangla Digits
310
+ toHijriCalendar("2026-03-31", { locale: "bn-BD" });
311
+ // → { day: "১১", month: "শাওয়াল", monthIndex: 10, year: "১৪৪৭" }
207
312
 
208
- ```ts
209
- import { toBanglaDigits, toEnglishDigits } from "@coreify/tarikh";
313
+ toHijriCalendar("2026-03-31", { timeZone: "UTC" });
314
+ // { day: 11, month: "Shawwal", monthIndex: 10, year: 1447 }
210
315
 
211
- toBanglaDigits("31 March 2026");
212
- // → "৩১ March ২০২৬"
316
+ // Supported values: defaultHijriZone === "Asia/Dhaka", alternateHijriZone === "UTC"
213
317
 
214
- toEnglishDigits("৩১ মার্চ ২০২৬");
215
- // → "31 মার্চ 2026"
216
- ```
318
+ format("2026-03-31", { mode: "hijri" });
319
+ // → "12th Shawwal 1447 AH"
217
320
 
218
- ### Relative Time
321
+ format("2026-03-31", { mode: "hijri", timeZone: "UTC" });
322
+ // → "11th Shawwal 1447 AH"
219
323
 
220
- ```ts
221
- import { fromNow } from "@coreify/tarikh";
324
+ format("2026-03-31", { mode: "hijri", locale: "bn-BD" });
325
+ // "১২ই শাওয়াল ১৪৪৭ হিজরি"
326
+ ```
222
327
 
328
+ ### Hybrid Formatting
329
+
330
+ | Mixing rule | Summary |
331
+ | ----------- | ------- |
332
+ | Hybrid formatting | Mix English and Bangla independently for day, month, and year |
333
+
334
+ ```ts
335
+ import { format } from "@coreify/tarikh";
336
+
337
+ format("2026-03-31", { mode: "hybrid" });
338
+ // → "31 মার্চ 2026"
339
+
340
+ 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
+
223
366
  fromNow(new Date(Date.now() - 86400000));
224
- // "1 day ago"
225
-
367
+ // Output depends on the current clock.
368
+
226
369
  fromNow(new Date(Date.now() - 86400000), { locale: "bn-BD" });
227
- // "১ দিন আগে"
228
-
370
+ // Output depends on the current clock.
371
+
229
372
  fromNow(new Date(Date.now() + 3600000));
230
- // "in 1 hour"
231
-
373
+ // Output depends on the current clock.
374
+
232
375
  fromNow(new Date(Date.now() - 86400000), { numeric: "auto" });
233
- // "yesterday"
234
-
376
+ // Output depends on the current clock.
377
+
235
378
  fromNow(new Date(Date.now() + 86400000), {
236
379
  locale: "bn-BD",
237
380
  numeric: "auto"
238
381
  });
239
- // "আগামীকাল"
240
- ```
241
-
242
- ### Parsing
243
-
244
- ```ts
245
- import { parseDate } from "@coreify/tarikh";
246
-
247
- parseDate("৩১ মার্চ ২০২৬");
248
- // → Date object (March 31, 2026)
249
-
250
- parseDate("17 Chaitra 1432", { calendar: "bangla" });
251
- // → Date object (March 31, 2026)
252
-
253
- // Legacy spellings (Boishakh, Joishtho, Choitro, etc.) are still accepted.
254
-
255
- parseDate("১৭ চৈত্র ১৪৩২", { calendar: "bangla" });
256
- // → Date object (March 31, 2026)
257
-
258
- parseDate("31 March 2026");
259
- // → Date object (March 31, 2026)
260
-
261
- parseDate("March 31, 2026");
262
- // → Date object (March 31, 2026)
263
-
264
- parseDate("31-Mar-2026");
265
- // → Date object (March 31, 2026)
266
-
267
- parseDate("2026/03/31");
268
- // → Date object (March 31, 2026)
269
-
270
- parseDate("2026.03.31");
271
- // → Date object (March 31, 2026)
272
-
273
- parseDate("2026-03-31T15:30:00Z");
274
- // → Date object (March 31, 2026, 3:30 PM UTC)
275
-
276
- // `toDate()` accepts the same Gregorian string forms as `parseDate()`,
277
- // plus `Date` objects and timestamps.
278
- // Supported string shapes:
279
- // - `YYYY-MM-DD`
280
- // - `YYYY/MM/DD`
281
- // - `YYYY.MM.DD`
282
- // - `YYYY-M-D`, `YYYY/M/D`, `YYYY.M.D`
283
- // - `YYYY-MM-DDTHH:mm[:ss[.fraction]][Z|±HH:mm]`
284
- // - `DD Month YYYY`
285
- // - `Month DD, YYYY`
286
- // - `DD-Month-YYYY`
287
- // - Bangla calendar strings like `১৭ চৈত্র ১৪৩২`
288
- // - Common Bangla month aliases like `Boishakh`, `Poush`, `Falgun`, `Asharh`
289
- ```
290
-
291
- ### Utilities
292
-
293
- ```ts
294
- import {
295
- isToday,
296
- isYesterday,
297
- isTomorrow,
298
- startOfDay,
299
- endOfDay,
300
- startOfMonth,
301
- endOfMonth,
302
- startOfYear,
303
- endOfYear,
304
- addDays,
305
- subDays,
306
- addMonths,
307
- subMonths,
308
- addYears,
309
- subYears,
310
- getBanglaMonth
311
- } from "@coreify/tarikh";
312
-
313
- isToday(new Date()); // → true
314
- isYesterday(subDays(new Date(), 1)); // → true
315
- isTomorrow(addDays(new Date(), 1)); // → true
316
- startOfMonth(new Date()); // → Date at the start of this month
317
- endOfMonth(new Date()); // → Date at the end of this month
318
- addMonths("2026-01-31", 1); // → 2026-02-28
319
- addYears(new Date(2024, 1, 29), 1); // → 2025-02-28
320
-
321
- getBanglaMonth(3); // → "মার্চ"
322
- getBanglaMonth(3, "short"); // → "মার্চ"
323
- getBanglaMonth(12); // → "ডিসেম্বর"
324
- ```
325
-
326
- ### Constants
327
-
328
- ```ts
329
- import {
330
- BANGLA_MONTHS_FULL,
331
- BANGLA_MONTHS_SHORT,
332
- BANGLA_CALENDAR_MONTHS,
333
- BANGLA_CALENDAR_MONTHS_EN,
334
- BANGLA_WEEKDAYS_FULL,
335
- BANGLA_WEEKDAYS_SHORT,
336
- ENGLISH_WEEKDAYS_FULL,
337
- ENGLISH_WEEKDAYS_SHORT,
338
- BANGLA_DIGITS,
339
- ENGLISH_DIGITS
340
- } from "@coreify/tarikh";
341
- ```
342
-
382
+ // 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
+
343
486
  ## React Components
344
487
 
345
- Optional entry point only included if you import from `@coreify/tarikh/react`.
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 |
346
494
 
347
- ```bash
348
- npm install @coreify/tarikh react
349
- ```
350
-
351
- ### Tarikh
495
+ > Import from `@coreify/tarikh/react` only when you need the React components.
352
496
 
353
497
  ```tsx
354
498
  import { Tarikh } from "@coreify/tarikh/react";
355
499
 
356
- <Tarikh value={new Date()} />
357
- // → <time>31 Mar 2026</time>
358
-
359
- <Tarikh value={new Date()} locale="bn-BD" />
360
- // → <time>৩১ মার্চ ২০২৬</time>
361
-
362
- <Tarikh value={new Date()} month="long" />
363
- // → <time>31 March 2026</time>
364
-
365
- <Tarikh
366
- value={new Date(2026, 2, 31, 15, 4)}
367
- weekday="short"
368
- hour="numeric"
369
- minute="2-digit"
370
- />
371
- // → <time>Tue, 31 Mar 2026, 15:04</time>
372
-
373
- <Tarikh
374
- value={new Date(2026, 2, 31, 15, 4, 9)}
375
- weekday="long"
376
- hour="2-digit"
377
- minute="2-digit"
378
- second="2-digit"
379
- hour12
380
- locale="bn-BD"
381
- />
382
- // → <time>মঙ্গলবার, ৩১ মার্চ ২০২৬, ০৩:০৪:০৯ অপরাহ্ণ</time>
383
-
384
- <Tarikh value="31 March 2026" />
385
- // → <time dateTime="2026-03-31">31 Mar 2026</time>
386
- ```
387
-
388
- ### RelativeTime
500
+ const date = "2026-03-31";
389
501
 
390
- ```tsx
391
- import { RelativeTime } from "@coreify/tarikh/react";
392
-
393
- <RelativeTime value={someDate} />
394
- // → <time>2 days ago</time>
395
-
396
- <RelativeTime value={someDate} locale="bn-BD" />
397
- // → <time>২ দিন আগে</time>
398
-
399
- <RelativeTime value={someDate} numeric="auto" />
400
- // → <time>yesterday</time> (for a 1-day past date)
401
-
402
- <RelativeTime value={someDate} locale="bn-BD" numeric="auto" />
403
- // → <time>আগামীকাল</time> (for a 1-day future date)
502
+ <Tarikh value={date} />
503
+ <Tarikh.Relative value={date} />
504
+ <Tarikh.Bangla value={date} locale="bn-BD" />
505
+ <Tarikh.Hijri value={date} locale="bn-BD" />
404
506
  ```
405
-
406
- ### BanglaDate
407
-
408
- ```tsx
409
- import { BanglaDate } from "@coreify/tarikh/react";
410
-
411
- <BanglaDate value={new Date()} />
412
- // <time>17 Chaitra 1432</time> (example; depends on date)
413
-
414
- <BanglaDate value={new Date()} locale="bn-BD" />
415
- // → <time>১৭ই চৈত্র ১৪৩২</time> (example; depends on date)
416
-
417
- <BanglaDate
418
- value={new Date()}
419
- locale="bn-BD"
420
- format="spoken"
421
- variant="poyla"
422
- />
423
- // → spoken day + Bangla month (e.g. পয়লা বৈশাখ … on Pohela Baishakh)
424
-
425
- <BanglaDate value="31 March 2026" />
426
- // → <time dateTime="2026-03-31">17 Chaitra 1432</time> (example; depends on date)
427
- ```
428
-
429
- All components render semantic `<time>` elements with `dateTime` and `aria-label` attributes. They are SSR-safe, tree-shakeable, and have zero runtime dependencies beyond React.
430
-
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
+
431
518
  ## What `Intl.DateTimeFormat` cannot do
432
519
 
520
+ | Why `Intl` falls short | Summary |
521
+ | --------------------- | ------- |
522
+ | Bangladesh-focused formatting | Needs Bangla calendar and culturally correct output |
523
+
433
524
  | Feature | Intl | @coreify/tarikh |
434
525
  | ------------------------------- | ------- | --------------- |
435
526
  | Bangla calendar (বৈশাখ → চৈত্র) | No | Yes |
527
+ | Hijri calendar | Partial | Yes |
436
528
  | Bangla digits in dates | Partial | Yes |
437
- | Hybrid formatting (mixed en/bn) | No | Yes |
438
- | Bangla calendar date parsing | No | Yes |
439
- | Relative time in Bangla | No | Yes |
440
- | SSR-safe React components | N/A | Yes |
441
-
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
+
442
534
  ## TypeScript
443
535
 
444
- Fully typed with strict mode. Core option interfaces and value types are exported from `@coreify/tarikh`.
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 |
445
542
 
446
543
  ```ts
447
544
  import type {
448
- DateInput,
449
- DayFormat,
450
- MonthFormat,
451
- Locale,
452
- Language,
453
- YearFormat,
454
- WeekdayFormat,
455
- TimeFormat,
456
- BanglaCalendarOptions,
457
- RelativeTimeOptions,
458
- BanglaCalendarFormatOptions,
459
- BanglaCalendarDayFormat,
460
- BanglaCalendarDaySpokenVariant,
461
- BanglaDayFormatOptions,
462
- DateFormatOptions,
463
- BanglaCalendarDate,
464
- HybridDateFormatOptions
465
- } from "@coreify/tarikh";
466
- ```
467
-
468
- ```ts
469
- import type {
470
- BanglaDateProps,
471
- RelativeTimeProps,
472
- TarikhProps
473
- } from "@coreify/tarikh/react";
474
- ```
475
-
476
- ## License
477
-
478
- MIT
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