chronal 0.0.1-0 β 0.0.1-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/README.md +376 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Chrona
|
|
2
|
+
|
|
3
|
+
A tiny, fast, and modern date utility library for JavaScript/TypeScript with zero dependencies.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- πͺΆ **Lightweight** - Zero dependencies, minimal bundle size
|
|
10
|
+
- π **i18n Support** - Locale-aware formatting with `Intl` API
|
|
11
|
+
- β° **UTC First** - All operations work in UTC by default, avoiding timezone pitfalls
|
|
12
|
+
- π§ **Modern API** - Simple, intuitive function-based API
|
|
13
|
+
- π¦ **Tree-shakeable** - Import only what you need
|
|
14
|
+
- π¦ **Deno Native** - Built for Deno, works everywhere
|
|
15
|
+
- β
**Fully Tested** - Comprehensive test coverage
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Deno
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { format, add, sub } from "jsr:@your-scope/chrona";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Node.js / npm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install chrona
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { format, add, sub } from "chrona";
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { format, add, sub, startOf, endOf } from "chrona";
|
|
39
|
+
|
|
40
|
+
const date = new Date("2024-06-15T14:35:22Z");
|
|
41
|
+
|
|
42
|
+
// Format dates
|
|
43
|
+
format(date, "YYYY-MM-DD"); // '2024-06-15'
|
|
44
|
+
format(date, "YYYY-MM-DD HH:mm:ss"); // '2024-06-15 14:35:22'
|
|
45
|
+
format(date, "DD/MM/YYYY [at] HH:mm"); // '15/06/2024 at 14:35'
|
|
46
|
+
|
|
47
|
+
// Add time
|
|
48
|
+
add(date, { days: 5, hours: 2 }); // 2024-06-20T16:35:22Z
|
|
49
|
+
|
|
50
|
+
// Subtract time
|
|
51
|
+
sub(date, { months: 1, days: 10 }); // 2024-05-05T14:35:22Z
|
|
52
|
+
|
|
53
|
+
// Start/End of period
|
|
54
|
+
startOf(date, "month"); // 2024-06-01T00:00:00.000Z
|
|
55
|
+
endOf(date, "day"); // 2024-06-15T23:59:59.999Z
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API Reference
|
|
59
|
+
|
|
60
|
+
### Formatting
|
|
61
|
+
|
|
62
|
+
#### `format(date, formatString, options?)`
|
|
63
|
+
|
|
64
|
+
Formats a date into a string using the specified format pattern.
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
- `date` (Date) - The date to format
|
|
68
|
+
- `formatString` (string) - Format pattern with tokens
|
|
69
|
+
- `options` (object, optional)
|
|
70
|
+
- `locale` (string) - Locale for internationalization (default: 'en-US')
|
|
71
|
+
- `tz` (string) - Timezone (default: 'UTC')
|
|
72
|
+
|
|
73
|
+
**Format Tokens:**
|
|
74
|
+
|
|
75
|
+
| Token | Output | Description |
|
|
76
|
+
|-------|--------|-------------|
|
|
77
|
+
| `YYYY` | 2024 | 4-digit year |
|
|
78
|
+
| `YY` | 24 | 2-digit year |
|
|
79
|
+
| `MMMM` | June | Full month name |
|
|
80
|
+
| `MMM` | Jun | Short month name |
|
|
81
|
+
| `MM` | 06 | 2-digit month |
|
|
82
|
+
| `M` | 6 | Month number |
|
|
83
|
+
| `DD` | 05 | 2-digit day |
|
|
84
|
+
| `D` | 5 | Day of month |
|
|
85
|
+
| `HH` | 14 | 2-digit hour (24h) |
|
|
86
|
+
| `H` | 14 | Hour (24h) |
|
|
87
|
+
| `mm` | 35 | 2-digit minute |
|
|
88
|
+
| `m` | 35 | Minute |
|
|
89
|
+
| `ss` | 22 | 2-digit second |
|
|
90
|
+
| `s` | 22 | Second |
|
|
91
|
+
|
|
92
|
+
**Literals:**
|
|
93
|
+
Use square brackets to escape literals: `[at]` β "at"
|
|
94
|
+
|
|
95
|
+
**Examples:**
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const date = new Date("2024-06-15T14:35:22Z");
|
|
99
|
+
|
|
100
|
+
format(date, "YYYY-MM-DD"); // '2024-06-15'
|
|
101
|
+
format(date, "DD/MM/YYYY HH:mm"); // '15/06/2024 14:35'
|
|
102
|
+
format(date, "MMMM D, YYYY"); // 'June 15, 2024'
|
|
103
|
+
format(date, "YYYY-MM-DD [at] HH:mm"); // '2024-06-15 at 14:35'
|
|
104
|
+
|
|
105
|
+
// With locale
|
|
106
|
+
format(date, "MMMM D, YYYY", { locale: "pt-BR" }); // 'junho 15, 2024'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Date Manipulation
|
|
110
|
+
|
|
111
|
+
#### `add(date, options)`
|
|
112
|
+
|
|
113
|
+
Adds specified time units to a date.
|
|
114
|
+
|
|
115
|
+
**Parameters:**
|
|
116
|
+
- `date` (Date) - The original date
|
|
117
|
+
- `options` (object) - Time units to add
|
|
118
|
+
- `years` (number)
|
|
119
|
+
- `months` (number)
|
|
120
|
+
- `weeks` (number)
|
|
121
|
+
- `days` (number)
|
|
122
|
+
- `hours` (number)
|
|
123
|
+
- `minutes` (number)
|
|
124
|
+
- `seconds` (number)
|
|
125
|
+
- `milliseconds` (number)
|
|
126
|
+
|
|
127
|
+
**Returns:** New Date object
|
|
128
|
+
|
|
129
|
+
**Examples:**
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const date = new Date("2024-01-31T12:00:00Z");
|
|
133
|
+
|
|
134
|
+
add(date, { days: 5 }); // 2024-02-05T12:00:00.000Z
|
|
135
|
+
add(date, { months: 1 }); // 2024-02-29T12:00:00.000Z (handles leap year)
|
|
136
|
+
add(date, { years: 1, months: 2, days: 3 }); // 2025-04-03T12:00:00.000Z
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### `sub(date, options)`
|
|
140
|
+
|
|
141
|
+
Subtracts specified time units from a date.
|
|
142
|
+
|
|
143
|
+
**Parameters:** Same as `add()`
|
|
144
|
+
|
|
145
|
+
**Examples:**
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const date = new Date("2024-03-31T12:00:00Z");
|
|
149
|
+
|
|
150
|
+
sub(date, { days: 5 }); // 2024-03-26T12:00:00.000Z
|
|
151
|
+
sub(date, { months: 1 }); // 2024-02-29T12:00:00.000Z (handles month overflow)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Start/End of Period
|
|
155
|
+
|
|
156
|
+
#### `startOf(date, unit)`
|
|
157
|
+
|
|
158
|
+
Returns the start of the specified time unit.
|
|
159
|
+
|
|
160
|
+
**Parameters:**
|
|
161
|
+
- `date` (Date) - The original date
|
|
162
|
+
- `unit` ('year' | 'month' | 'day' | 'hour' | 'minute' | 'second')
|
|
163
|
+
|
|
164
|
+
**Examples:**
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const date = new Date("2024-06-15T14:35:22.500Z");
|
|
168
|
+
|
|
169
|
+
startOf(date, "year"); // 2024-01-01T00:00:00.000Z
|
|
170
|
+
startOf(date, "month"); // 2024-06-01T00:00:00.000Z
|
|
171
|
+
startOf(date, "day"); // 2024-06-15T00:00:00.000Z
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### `endOf(date, unit)`
|
|
175
|
+
|
|
176
|
+
Returns the end (last millisecond) of the specified time unit.
|
|
177
|
+
|
|
178
|
+
**Parameters:** Same as `startOf()`
|
|
179
|
+
|
|
180
|
+
**Examples:**
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
const date = new Date("2024-06-15T14:35:22.500Z");
|
|
184
|
+
|
|
185
|
+
endOf(date, "year"); // 2024-12-31T23:59:59.999Z
|
|
186
|
+
endOf(date, "month"); // 2024-06-30T23:59:59.999Z
|
|
187
|
+
endOf(date, "day"); // 2024-06-15T23:59:59.999Z
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Date Comparison
|
|
191
|
+
|
|
192
|
+
#### `isAfter(dateLeft, dateRight)`
|
|
193
|
+
|
|
194
|
+
Checks if the first date is after the second date.
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const date1 = new Date("2024-01-20T12:00:00Z");
|
|
198
|
+
const date2 = new Date("2024-01-15T12:00:00Z");
|
|
199
|
+
|
|
200
|
+
isAfter(date1, date2); // true
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### `isBefore(dateLeft, dateRight)`
|
|
204
|
+
|
|
205
|
+
Checks if the first date is before the second date.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
isBefore(date2, date1); // true
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### `isEqual(dateLeft, dateRight)`
|
|
212
|
+
|
|
213
|
+
Checks if two dates are equal (same exact millisecond).
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const date1 = new Date("2024-01-15T12:00:00.000Z");
|
|
217
|
+
const date2 = new Date("2024-01-15T12:00:00.000Z");
|
|
218
|
+
|
|
219
|
+
isEqual(date1, date2); // true
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### `isSame(dateLeft, dateRight, unit)`
|
|
223
|
+
|
|
224
|
+
Checks if two dates are in the same time unit.
|
|
225
|
+
|
|
226
|
+
**Parameters:**
|
|
227
|
+
- `dateLeft` (Date)
|
|
228
|
+
- `dateRight` (Date)
|
|
229
|
+
- `unit` ('year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second')
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const date1 = new Date("2024-06-15T14:30:00Z");
|
|
233
|
+
const date2 = new Date("2024-06-15T18:45:00Z");
|
|
234
|
+
|
|
235
|
+
isSame(date1, date2, "day"); // true (same day)
|
|
236
|
+
isSame(date1, date2, "hour"); // false (different hours)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Min/Max
|
|
240
|
+
|
|
241
|
+
#### `max(...dates)`
|
|
242
|
+
|
|
243
|
+
Returns the latest date from the given dates.
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const date1 = new Date("2024-01-15T12:00:00Z");
|
|
247
|
+
const date2 = new Date("2024-01-20T12:00:00Z");
|
|
248
|
+
const date3 = new Date("2024-01-10T12:00:00Z");
|
|
249
|
+
|
|
250
|
+
max(date1, date2, date3); // 2024-01-20T12:00:00.000Z
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### `min(...dates)`
|
|
254
|
+
|
|
255
|
+
Returns the earliest date from the given dates.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
min(date1, date2, date3); // 2024-01-10T12:00:00.000Z
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Date Difference
|
|
262
|
+
|
|
263
|
+
#### `difference(dateLeft, dateRight, unit)`
|
|
264
|
+
|
|
265
|
+
Calculates the difference between two dates in the specified unit.
|
|
266
|
+
|
|
267
|
+
**Parameters:**
|
|
268
|
+
- `dateLeft` (Date)
|
|
269
|
+
- `dateRight` (Date)
|
|
270
|
+
- `unit` ('years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds')
|
|
271
|
+
|
|
272
|
+
**Returns:** Number (can be negative)
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
const date1 = new Date("2024-01-20T12:00:00Z");
|
|
276
|
+
const date2 = new Date("2024-01-15T12:00:00Z");
|
|
277
|
+
|
|
278
|
+
difference(date1, date2, "days"); // 5
|
|
279
|
+
difference(date2, date1, "days"); // -5
|
|
280
|
+
difference(date1, date2, "hours"); // 120
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Localization
|
|
284
|
+
|
|
285
|
+
#### `months(locale?, format?)`
|
|
286
|
+
|
|
287
|
+
Returns an array of month names for the specified locale.
|
|
288
|
+
|
|
289
|
+
**Parameters:**
|
|
290
|
+
- `locale` (string, optional) - Default: 'en-US'
|
|
291
|
+
- `format` ('long' | 'short' | 'narrow', optional) - Default: 'long'
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
months("en-US", "long"); // ['January', 'February', ...]
|
|
295
|
+
months("en-US", "short"); // ['Jan', 'Feb', ...]
|
|
296
|
+
months("pt-BR", "long"); // ['janeiro', 'fevereiro', ...]
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### `weekdays(locale?, format?)`
|
|
300
|
+
|
|
301
|
+
Returns an array of weekday names (Monday to Sunday) for the specified locale.
|
|
302
|
+
|
|
303
|
+
**Parameters:** Same as `months()`
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
weekdays("en-US", "long"); // ['Monday', 'Tuesday', ...]
|
|
307
|
+
weekdays("en-US", "short"); // ['Mon', 'Tue', ...]
|
|
308
|
+
weekdays("pt-BR", "long"); // ['segunda-feira', 'terΓ§a-feira', ...]
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Performance
|
|
312
|
+
|
|
313
|
+
Chrona is optimized for performance, especially in formatting operations:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
Benchmark: 1,000,000 iterations of format(date, 'YYYY-MM-DD HH:mm:ss')
|
|
317
|
+
|
|
318
|
+
chrona: 254ms
|
|
319
|
+
dayjs: 1540ms (6x slower)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Key optimizations:
|
|
323
|
+
- Format string caching (no repeated regex parsing)
|
|
324
|
+
- Fast UTC path (avoids expensive Intl.DateTimeFormat for UTC)
|
|
325
|
+
- Optimized padding functions
|
|
326
|
+
- Direct string concatenation
|
|
327
|
+
|
|
328
|
+
## Why Chrona?
|
|
329
|
+
|
|
330
|
+
### vs Day.js
|
|
331
|
+
- **6x faster** for formatting operations
|
|
332
|
+
- Zero dependencies (Day.js requires plugins for many features)
|
|
333
|
+
- UTC-first design prevents timezone bugs
|
|
334
|
+
- Modern ES modules
|
|
335
|
+
|
|
336
|
+
### vs date-fns
|
|
337
|
+
- Simpler API (functional vs modular)
|
|
338
|
+
- Better performance for common operations
|
|
339
|
+
- Smaller bundle size
|
|
340
|
+
- Built-in formatting and localization
|
|
341
|
+
|
|
342
|
+
### vs Moment.js
|
|
343
|
+
- **Much smaller** (Moment.js is no longer maintained)
|
|
344
|
+
- Immutable by default (no mutation footguns)
|
|
345
|
+
- Tree-shakeable
|
|
346
|
+
- Modern codebase
|
|
347
|
+
|
|
348
|
+
## Design Principles
|
|
349
|
+
|
|
350
|
+
1. **UTC First** - All operations work in UTC to avoid timezone surprises
|
|
351
|
+
2. **Immutability** - Functions always return new Date objects
|
|
352
|
+
3. **Zero Dependencies** - Leverages native Intl API for localization
|
|
353
|
+
4. **Performance** - Optimized hot paths with caching
|
|
354
|
+
5. **Type Safety** - Full TypeScript support
|
|
355
|
+
6. **Small API Surface** - Easy to learn, hard to misuse
|
|
356
|
+
|
|
357
|
+
## Browser Support
|
|
358
|
+
|
|
359
|
+
Chrona works in all modern browsers and JavaScript runtimes that support:
|
|
360
|
+
- ES6+ features
|
|
361
|
+
- `Intl.DateTimeFormat` API
|
|
362
|
+
- Native Date object
|
|
363
|
+
|
|
364
|
+
## Contributing
|
|
365
|
+
|
|
366
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
367
|
+
|
|
368
|
+
## License
|
|
369
|
+
|
|
370
|
+
MIT Β© [Your Name]
|
|
371
|
+
|
|
372
|
+
## Links
|
|
373
|
+
|
|
374
|
+
- [Documentation](#api-reference)
|
|
375
|
+
- [GitHub Repository](https://github.com/your-username/chrona)
|
|
376
|
+
- [Report Issues](https://github.com/your-username/chrona/issues)
|