ts-time-utils 4.0.1 → 4.4.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 +175 -30
- package/dist/{age.js → age.cjs} +14 -6
- package/dist/{calculate.js → calculate.cjs} +30 -18
- package/dist/{calendar.js → calendar.cjs} +80 -39
- package/dist/{calendars.js → calendars.cjs} +48 -23
- package/dist/{chain.js → chain.cjs} +41 -40
- package/dist/{compare.js → compare.cjs} +58 -28
- package/dist/constants.cjs +19 -0
- package/dist/{countdown.js → countdown.cjs} +16 -7
- package/dist/{cron.js → cron.cjs} +20 -9
- package/dist/{dateRange.js → dateRange.cjs} +42 -26
- package/dist/{duration.js → duration.cjs} +56 -44
- package/dist/esm/chain.js +0 -5
- package/dist/esm/finance.d.ts +236 -0
- package/dist/esm/finance.d.ts.map +1 -0
- package/dist/esm/finance.js +495 -0
- package/dist/esm/healthcare.d.ts +260 -0
- package/dist/esm/healthcare.d.ts.map +1 -0
- package/dist/esm/healthcare.js +447 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/naturalLanguage.d.ts +1 -3
- package/dist/esm/naturalLanguage.d.ts.map +1 -1
- package/dist/esm/naturalLanguage.js +9 -2
- package/dist/esm/plugins.d.ts +0 -6
- package/dist/esm/plugins.d.ts.map +1 -1
- package/dist/esm/plugins.js +36 -42
- package/dist/esm/recurrence.d.ts.map +1 -1
- package/dist/esm/recurrence.js +3 -5
- package/dist/esm/scheduling.d.ts +206 -0
- package/dist/esm/scheduling.d.ts.map +1 -0
- package/dist/esm/scheduling.js +329 -0
- package/dist/esm/timezone.d.ts +6 -1
- package/dist/esm/timezone.d.ts.map +1 -1
- package/dist/esm/timezone.js +106 -66
- package/dist/esm/types.d.ts +0 -4
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/finance.cjs +512 -0
- package/dist/finance.d.ts +236 -0
- package/dist/finance.d.ts.map +1 -0
- package/dist/{fiscal.js → fiscal.cjs} +36 -17
- package/dist/{format.js → format.cjs} +83 -70
- package/dist/healthcare.cjs +462 -0
- package/dist/healthcare.d.ts +260 -0
- package/dist/healthcare.d.ts.map +1 -0
- package/dist/{holidays.js → holidays.cjs} +52 -25
- package/dist/index.cjs +595 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/{interval.js → interval.cjs} +24 -11
- package/dist/{iterate.js → iterate.cjs} +84 -41
- package/dist/{locale.js → locale.cjs} +54 -26
- package/dist/{naturalLanguage.js → naturalLanguage.cjs} +36 -23
- package/dist/naturalLanguage.d.ts +1 -3
- package/dist/naturalLanguage.d.ts.map +1 -1
- package/dist/{parse.js → parse.cjs} +24 -11
- package/dist/{performance.js → performance.cjs} +23 -10
- package/dist/{plugins.js → plugins.cjs} +48 -47
- package/dist/plugins.d.ts +0 -6
- package/dist/plugins.d.ts.map +1 -1
- package/dist/{precision.js → precision.cjs} +74 -37
- package/dist/{rangePresets.js → rangePresets.cjs} +40 -19
- package/dist/{recurrence.js → recurrence.cjs} +27 -21
- package/dist/recurrence.d.ts.map +1 -1
- package/dist/scheduling.cjs +344 -0
- package/dist/scheduling.d.ts +206 -0
- package/dist/scheduling.d.ts.map +1 -0
- package/dist/{serialize.js → serialize.cjs} +36 -17
- package/dist/{temporal.js → temporal.cjs} +28 -13
- package/dist/{timezone.js → timezone.cjs} +140 -82
- package/dist/timezone.d.ts +6 -1
- package/dist/timezone.d.ts.map +1 -1
- package/dist/{types.js → types.cjs} +9 -3
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/{validate.js → validate.cjs} +54 -26
- package/dist/{workingHours.js → workingHours.cjs} +36 -17
- package/package.json +52 -34
- package/dist/constants.js +0 -16
- package/dist/index.js +0 -66
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ts-time-utils
|
|
2
2
|
|
|
3
|
-
A comprehensive TypeScript utility library for time, dates, durations, and calendar operations. Zero dependencies, full tree-shaking support,
|
|
3
|
+
A comprehensive TypeScript utility library for time, dates, durations, and calendar operations. Zero dependencies, full tree-shaking support, 430+ functions across 32 public modules.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/ts-time-utils)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -12,10 +12,16 @@ A comprehensive TypeScript utility library for time, dates, durations, and calen
|
|
|
12
12
|
- **Lightweight** — Import only what you need with tree-shaking support
|
|
13
13
|
- **Zero dependencies** — Pure TypeScript, no external packages
|
|
14
14
|
- **Type-safe** — Full TypeScript support with IntelliSense
|
|
15
|
-
- **Comprehensive** —
|
|
15
|
+
- **Comprehensive** — 430+ functions across 32 public modules
|
|
16
16
|
- **Fluent API** — Chain operations with the `chain()` API
|
|
17
17
|
- **Extensible** — Plugin system for custom functionality
|
|
18
18
|
|
|
19
|
+
## When Not To Use This Library
|
|
20
|
+
|
|
21
|
+
- You only need a single built-in `Date` helper or one `Intl` formatter.
|
|
22
|
+
- You want the standardized Temporal API rather than a utility library.
|
|
23
|
+
- You need a mutable Moment-style wrapper with implicit global locale state.
|
|
24
|
+
|
|
19
25
|
## Installation
|
|
20
26
|
|
|
21
27
|
```bash
|
|
@@ -47,6 +53,16 @@ import { differenceInUnits } from 'ts-time-utils/calculate';
|
|
|
47
53
|
import { isValidDate } from 'ts-time-utils/validate';
|
|
48
54
|
```
|
|
49
55
|
|
|
56
|
+
Every public module is also available as a subpath import such as
|
|
57
|
+
`ts-time-utils/timezone`, `ts-time-utils/workingHours`, or
|
|
58
|
+
`ts-time-utils/naturalLanguage`.
|
|
59
|
+
|
|
60
|
+
### Module Selection
|
|
61
|
+
|
|
62
|
+
- Use `ts-time-utils` when you need a few core utilities from different areas.
|
|
63
|
+
- Use `ts-time-utils/format` or `ts-time-utils/calculate` when one module is enough.
|
|
64
|
+
- Use dedicated subpaths like `ts-time-utils/chain`, `ts-time-utils/plugins`, `ts-time-utils/locale`, or `ts-time-utils/workingHours` for those feature areas.
|
|
65
|
+
|
|
50
66
|
---
|
|
51
67
|
|
|
52
68
|
## Utility Categories
|
|
@@ -125,18 +141,22 @@ chain(new Date())
|
|
|
125
141
|
.format('YYYY-MM-DD'); // Next week Monday
|
|
126
142
|
```
|
|
127
143
|
|
|
144
|
+
Plugin extensions are imported from `ts-time-utils/plugins`, and that module now loads the chain class directly. You can import `plugins` before or after `chain` without any hidden global setup.
|
|
145
|
+
|
|
128
146
|
### Timezone
|
|
129
147
|
|
|
130
148
|
Timezone conversions, DST handling, and zone comparisons.
|
|
131
149
|
|
|
132
150
|
```ts
|
|
133
|
-
import { formatInTimeZone, isDST,
|
|
151
|
+
import { formatInTimeZone, isDST, convertBetweenZones } from 'ts-time-utils/timezone';
|
|
134
152
|
|
|
135
|
-
formatInTimeZone(
|
|
153
|
+
formatInTimeZone(new Date(), 'America/New_York');
|
|
136
154
|
isDST(new Date('2025-07-14'), 'America/New_York'); // true
|
|
137
|
-
|
|
155
|
+
convertBetweenZones(new Date(), 'UTC', 'Asia/Tokyo');
|
|
138
156
|
```
|
|
139
157
|
|
|
158
|
+
`isDST()` uses a yearly-offset heuristic rather than authoritative transition metadata.
|
|
159
|
+
|
|
140
160
|
### Calendar
|
|
141
161
|
|
|
142
162
|
ISO weeks, quarters, holidays, and calendar grids.
|
|
@@ -191,12 +211,14 @@ recurrenceToString(weekly.rule); // "Every week on Monday, Wednesday, Friday"
|
|
|
191
211
|
Parse and match cron expressions.
|
|
192
212
|
|
|
193
213
|
```ts
|
|
194
|
-
import { matchesCron, getNextCronDate, describeCron
|
|
214
|
+
import { parseCronExpression, matchesCron, getNextCronDate, describeCron } from 'ts-time-utils/cron';
|
|
195
215
|
|
|
196
|
-
|
|
216
|
+
const date = new Date();
|
|
217
|
+
|
|
218
|
+
parseCronExpression('0 9 * * 1-5'); // minute/hour/day/month/day-of-week parts
|
|
219
|
+
matchesCron(date, '0 9 * * 1-5'); // true if weekday 9am
|
|
197
220
|
getNextCronDate('0 9 * * *'); // Next 9am
|
|
198
221
|
describeCron('0 9 * * 1-5'); // "At 09:00 on Monday through Friday"
|
|
199
|
-
CRON_PRESETS.DAILY; // "0 0 * * *"
|
|
200
222
|
```
|
|
201
223
|
|
|
202
224
|
### Fiscal Year
|
|
@@ -204,11 +226,13 @@ CRON_PRESETS.DAILY; // "0 0 * * *"
|
|
|
204
226
|
Fiscal year utilities with configurable start month.
|
|
205
227
|
|
|
206
228
|
```ts
|
|
207
|
-
import { getFiscalYear, getFiscalQuarter
|
|
229
|
+
import { getFiscalYear, getFiscalQuarter } from 'ts-time-utils/fiscal';
|
|
230
|
+
|
|
231
|
+
const date = new Date();
|
|
208
232
|
|
|
209
|
-
getFiscalYear(date,
|
|
210
|
-
getFiscalYear(date,
|
|
211
|
-
getFiscalYear(date,
|
|
233
|
+
getFiscalYear(date, { startMonth: 4 }); // April start
|
|
234
|
+
getFiscalYear(date, { startMonth: 7 }); // July start
|
|
235
|
+
getFiscalYear(date, { startMonth: 10 }); // October start
|
|
212
236
|
getFiscalQuarter(date, { startMonth: 4 }); // Q2 for UK fiscal
|
|
213
237
|
```
|
|
214
238
|
|
|
@@ -254,6 +278,8 @@ extractDatesFromText('Meeting tomorrow at 3pm');
|
|
|
254
278
|
// [{ date: Date, text: 'tomorrow at 3pm', confidence: 0.9 }]
|
|
255
279
|
```
|
|
256
280
|
|
|
281
|
+
`parseNaturalDate` accepts `referenceDate`, `defaultTime`, and `strict`. When `strict` is `true`, the parser only returns the library's recognized patterns and skips the permissive `Date` fallback.
|
|
282
|
+
|
|
257
283
|
### International Holidays
|
|
258
284
|
|
|
259
285
|
Public holidays for 20 countries.
|
|
@@ -261,10 +287,12 @@ Public holidays for 20 countries.
|
|
|
261
287
|
```ts
|
|
262
288
|
import { getHolidays, isHoliday, getNextHoliday } from 'ts-time-utils/holidays';
|
|
263
289
|
|
|
290
|
+
const today = new Date();
|
|
291
|
+
|
|
264
292
|
getHolidays(2025, 'UK'); // UK bank holidays
|
|
265
293
|
getHolidays(2025, 'DE'); // German holidays
|
|
266
|
-
isHoliday(
|
|
267
|
-
getNextHoliday(
|
|
294
|
+
isHoliday(today, 'CA'); // Is Canadian holiday?
|
|
295
|
+
getNextHoliday(today, 'AU'); // Next Australian holiday
|
|
268
296
|
|
|
269
297
|
// Supported: UK, NL, DE, CA, AU, IT, ES, CN, IN, US,
|
|
270
298
|
// JP, FR, BR, MX, KR, SG, PL, SE, BE, CH
|
|
@@ -277,6 +305,9 @@ Multi-language formatting with 40+ locales.
|
|
|
277
305
|
```ts
|
|
278
306
|
import { formatRelativeTime, formatDateLocale, detectLocale } from 'ts-time-utils/locale';
|
|
279
307
|
|
|
308
|
+
const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000);
|
|
309
|
+
const date = new Date();
|
|
310
|
+
|
|
280
311
|
formatRelativeTime(pastDate, { locale: 'es' }); // "hace 2 horas"
|
|
281
312
|
formatRelativeTime(pastDate, { locale: 'de' }); // "vor 2 Stunden"
|
|
282
313
|
formatDateLocale(date, 'fr', 'long'); // "15 janvier 2024"
|
|
@@ -285,14 +316,24 @@ detectLocale(); // Auto-detect system locale
|
|
|
285
316
|
|
|
286
317
|
### Working Hours
|
|
287
318
|
|
|
288
|
-
Business hours calculations with break support.
|
|
319
|
+
Business hours calculations with break support. These helpers use the
|
|
320
|
+
`Date` values you pass in directly; if you need a different timezone's wall
|
|
321
|
+
clock, adapt the instant first with a timezone helper such as
|
|
322
|
+
`convertDateToZone()` or `reinterpretAsZone()`.
|
|
289
323
|
|
|
290
324
|
```ts
|
|
291
325
|
import { isWorkingTime, addWorkingDays, workingDaysBetween } from 'ts-time-utils/workingHours';
|
|
292
326
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
327
|
+
const config = {
|
|
328
|
+
workingDays: [1, 2, 3, 4, 5],
|
|
329
|
+
hours: { start: 9, end: 17 },
|
|
330
|
+
breaks: [{ start: 12, end: 13 }]
|
|
331
|
+
};
|
|
332
|
+
const now = new Date();
|
|
333
|
+
|
|
334
|
+
isWorkingTime(now, config);
|
|
335
|
+
addWorkingDays(now, 5, config);
|
|
336
|
+
workingDaysBetween(now, new Date('2025-12-31'), config);
|
|
296
337
|
```
|
|
297
338
|
|
|
298
339
|
### Serialization
|
|
@@ -450,12 +491,107 @@ leapSecondsBetween(date1, date2); // Number of leap seconds
|
|
|
450
491
|
Date parsing from various formats.
|
|
451
492
|
|
|
452
493
|
```ts
|
|
453
|
-
import { parseDate, parseTime,
|
|
494
|
+
import { parseDate, parseTime, guessDateFormat } from 'ts-time-utils/parse';
|
|
454
495
|
|
|
455
496
|
parseDate('Dec 25, 2025');
|
|
456
497
|
parseDate('25/12/2025', 'DD/MM/YYYY');
|
|
457
498
|
parseTime('2:30 PM'); // { hour: 14, minute: 30 }
|
|
458
|
-
|
|
499
|
+
guessDateFormat('2025-09-14'); // 'YYYY-MM-DD'
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Scheduling
|
|
503
|
+
|
|
504
|
+
Appointment slots, availability, and booking conflict detection.
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
import {
|
|
508
|
+
generateSlots, getAvailableSlots, findNextAvailable,
|
|
509
|
+
hasConflict, findConflicts, mergeBookings
|
|
510
|
+
} from 'ts-time-utils/scheduling';
|
|
511
|
+
|
|
512
|
+
// Generate 30-min slots for a day
|
|
513
|
+
const slots = generateSlots(new Date(), {
|
|
514
|
+
slotDuration: 30,
|
|
515
|
+
workingHours: {
|
|
516
|
+
workingDays: [1, 2, 3, 4, 5],
|
|
517
|
+
hours: { start: 9, end: 17 }
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// Find available slots (excluding existing bookings)
|
|
522
|
+
const available = getAvailableSlots(new Date(), existingBookings, config);
|
|
523
|
+
|
|
524
|
+
// Find next available slot of specific duration
|
|
525
|
+
findNextAvailable(new Date(), bookings, 60, config); // 60-min slot
|
|
526
|
+
|
|
527
|
+
// Check for conflicts
|
|
528
|
+
hasConflict(bookings, proposedSlot); // true/false
|
|
529
|
+
findConflicts(bookings, proposedSlot); // Array of conflicting bookings
|
|
530
|
+
|
|
531
|
+
// Merge adjacent bookings
|
|
532
|
+
mergeBookings(bookings);
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Finance
|
|
536
|
+
|
|
537
|
+
Market hours, trading days, and settlement date calculations.
|
|
538
|
+
|
|
539
|
+
```ts
|
|
540
|
+
import {
|
|
541
|
+
isMarketOpen, isTradingDay, getMarketHours,
|
|
542
|
+
getNextMarketOpen, addTradingDays, getSettlementDate,
|
|
543
|
+
eachTradingDay, getOptionsExpiration
|
|
544
|
+
} from 'ts-time-utils/finance';
|
|
545
|
+
|
|
546
|
+
// Check market status
|
|
547
|
+
isMarketOpen(new Date(), 'NYSE'); // Is NYSE open right now?
|
|
548
|
+
isTradingDay(new Date(), 'NASDAQ'); // Is today a trading day?
|
|
549
|
+
getMarketHours('NYSE'); // { open: {hour:9,minute:30}, close: {hour:16,minute:0} }
|
|
550
|
+
|
|
551
|
+
// Market timing
|
|
552
|
+
getNextMarketOpen(new Date()); // Next market open time
|
|
553
|
+
addTradingDays(new Date(), 5); // 5 trading days from now
|
|
554
|
+
|
|
555
|
+
// Settlement (T+2, etc.)
|
|
556
|
+
getSettlementDate(tradeDate, 2); // T+2 settlement date
|
|
557
|
+
|
|
558
|
+
// Iterate trading days
|
|
559
|
+
eachTradingDay(start, end); // Array of trading days
|
|
560
|
+
|
|
561
|
+
// Options expiration (3rd Friday)
|
|
562
|
+
getOptionsExpiration(2025, 3); // March 2025 expiration
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Healthcare
|
|
566
|
+
|
|
567
|
+
Medication scheduling, shift patterns, and compliance windows.
|
|
568
|
+
|
|
569
|
+
```ts
|
|
570
|
+
import {
|
|
571
|
+
getMedicationTimes, getNextMedicationTime, parseMedicationFrequency,
|
|
572
|
+
generateShiftSchedule, getShiftForTime, isOnShift,
|
|
573
|
+
createOnCallRotation, getOnCallStaff,
|
|
574
|
+
getComplianceDeadline, timeUntilDeadline
|
|
575
|
+
} from 'ts-time-utils/healthcare';
|
|
576
|
+
|
|
577
|
+
// Medication times (BID = twice daily, TID = 3x daily, etc.)
|
|
578
|
+
getMedicationTimes(new Date(), 'BID'); // [8am, 8pm] (default wake/sleep times)
|
|
579
|
+
getMedicationTimes(new Date(), 'q6h'); // Every 6 hours
|
|
580
|
+
getNextMedicationTime(now, 'TID'); // Next scheduled dose
|
|
581
|
+
parseMedicationFrequency('twice daily'); // 'BID'
|
|
582
|
+
|
|
583
|
+
// Shift scheduling
|
|
584
|
+
generateShiftSchedule(start, end, { pattern: '12hr', startTime: { hour: 7, minute: 0 } });
|
|
585
|
+
getShiftForTime(now, shiftConfig); // Current shift
|
|
586
|
+
isOnShift(now, shiftStart, config); // Is within shift?
|
|
587
|
+
|
|
588
|
+
// On-call rotations
|
|
589
|
+
const rotation = createOnCallRotation(start, end, ['Dr. Smith', 'Dr. Jones'], 24);
|
|
590
|
+
getOnCallStaff(now, rotation); // Who's on call?
|
|
591
|
+
|
|
592
|
+
// Compliance windows
|
|
593
|
+
getComplianceDeadline(eventDate, 72); // 72-hour window
|
|
594
|
+
timeUntilDeadline(eventDate, deadline); // Duration remaining
|
|
459
595
|
```
|
|
460
596
|
|
|
461
597
|
---
|
|
@@ -465,21 +601,20 @@ autoDetectFormat('2025-09-14'); // 'YYYY-MM-DD'
|
|
|
465
601
|
Extend ChainedDate with custom functionality.
|
|
466
602
|
|
|
467
603
|
```ts
|
|
468
|
-
import { chain,
|
|
604
|
+
import { chain, ChainedDate } from 'ts-time-utils/chain';
|
|
605
|
+
import { extend } from 'ts-time-utils/plugins';
|
|
469
606
|
|
|
470
|
-
|
|
471
|
-
addBusinessDays(days: number) {
|
|
607
|
+
extend('business', {
|
|
608
|
+
addBusinessDays(this: ChainedDate, days: number) {
|
|
472
609
|
// Implementation
|
|
473
610
|
return this;
|
|
474
611
|
},
|
|
475
|
-
isBusinessDay() {
|
|
612
|
+
isBusinessDay(this: ChainedDate) {
|
|
476
613
|
const day = this.toDate().getDay();
|
|
477
614
|
return day !== 0 && day !== 6;
|
|
478
615
|
}
|
|
479
616
|
});
|
|
480
617
|
|
|
481
|
-
registerPlugin(businessPlugin);
|
|
482
|
-
|
|
483
618
|
chain(new Date())
|
|
484
619
|
.addBusinessDays(5)
|
|
485
620
|
.isBusinessDay(); // true/false
|
|
@@ -522,6 +657,9 @@ For complete API documentation, see the [Playground & Docs](https://ts-time-util
|
|
|
522
657
|
| `interval` | Time interval operations |
|
|
523
658
|
| `rangePresets` | Common date range presets |
|
|
524
659
|
| `parse` | Date parsing from various formats |
|
|
660
|
+
| `scheduling` | Appointment slots, availability, booking |
|
|
661
|
+
| `finance` | Market hours, trading days, settlement |
|
|
662
|
+
| `healthcare` | Medication schedules, shifts, on-call |
|
|
525
663
|
| `plugins` | Plugin system for extensions |
|
|
526
664
|
| `constants` | Time constants and types |
|
|
527
665
|
|
|
@@ -533,6 +671,7 @@ For complete API documentation, see the [Playground & Docs](https://ts-time-util
|
|
|
533
671
|
npm install # Install dependencies
|
|
534
672
|
npm run build # Build both CJS and ESM
|
|
535
673
|
npm test # Run tests
|
|
674
|
+
npm run test:package # Verify built package exports after build
|
|
536
675
|
npm run lint # Lint code
|
|
537
676
|
```
|
|
538
677
|
|
|
@@ -543,16 +682,22 @@ Releases are automated via GitHub Actions with npm trusted publishing (OIDC).
|
|
|
543
682
|
**To release a new version:**
|
|
544
683
|
|
|
545
684
|
```bash
|
|
546
|
-
git tag
|
|
547
|
-
git push --tags # Push tag
|
|
685
|
+
git tag vX.Y.Z # Create a semantic version tag for the release
|
|
686
|
+
git push --tags # Push tag -> triggers publish workflow
|
|
548
687
|
```
|
|
549
688
|
|
|
550
689
|
The workflow automatically:
|
|
551
690
|
1. Sets `package.json` version from tag
|
|
552
|
-
2. Runs
|
|
691
|
+
2. Runs `npm run release:verify`
|
|
553
692
|
3. Publishes to npm with provenance
|
|
554
693
|
|
|
555
|
-
**Version format:** Tags must match `v*` pattern (e.g., `
|
|
694
|
+
**Version format:** Tags must match `v*` pattern (e.g., `v1.2.3`, `v1.2.3-beta.1`)
|
|
695
|
+
|
|
696
|
+
Before tagging, run:
|
|
697
|
+
|
|
698
|
+
```bash
|
|
699
|
+
npm run release:verify
|
|
700
|
+
```
|
|
556
701
|
|
|
557
702
|
## License
|
|
558
703
|
|
package/dist/{age.js → age.cjs}
RENAMED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateAge = calculateAge;
|
|
4
|
+
exports.getAgeInUnits = getAgeInUnits;
|
|
5
|
+
exports.getLifeStage = getLifeStage;
|
|
6
|
+
exports.getNextBirthday = getNextBirthday;
|
|
7
|
+
exports.getDaysUntilBirthday = getDaysUntilBirthday;
|
|
8
|
+
exports.isBirthday = isBirthday;
|
|
1
9
|
/**
|
|
2
10
|
* Calculate detailed age from birth date
|
|
3
11
|
* @param birthDate - date of birth
|
|
4
12
|
* @param referenceDate - date to calculate age from (defaults to now)
|
|
5
13
|
*/
|
|
6
|
-
|
|
14
|
+
function calculateAge(birthDate, referenceDate = new Date()) {
|
|
7
15
|
const birth = new Date(birthDate);
|
|
8
16
|
const reference = new Date(referenceDate);
|
|
9
17
|
let years = reference.getFullYear() - birth.getFullYear();
|
|
@@ -30,7 +38,7 @@ export function calculateAge(birthDate, referenceDate = new Date()) {
|
|
|
30
38
|
* @param unit - unit to return age in
|
|
31
39
|
* @param referenceDate - date to calculate from (defaults to now)
|
|
32
40
|
*/
|
|
33
|
-
|
|
41
|
+
function getAgeInUnits(birthDate, unit, referenceDate = new Date()) {
|
|
34
42
|
const diffMs = referenceDate.getTime() - birthDate.getTime();
|
|
35
43
|
switch (unit) {
|
|
36
44
|
case 'years':
|
|
@@ -57,7 +65,7 @@ export function getAgeInUnits(birthDate, unit, referenceDate = new Date()) {
|
|
|
57
65
|
* @param birthDate - date of birth
|
|
58
66
|
* @param referenceDate - date to calculate from (defaults to now)
|
|
59
67
|
*/
|
|
60
|
-
|
|
68
|
+
function getLifeStage(birthDate, referenceDate = new Date()) {
|
|
61
69
|
const ageInYears = getAgeInUnits(birthDate, 'years', referenceDate);
|
|
62
70
|
if (ageInYears < 2)
|
|
63
71
|
return 'infant';
|
|
@@ -74,7 +82,7 @@ export function getLifeStage(birthDate, referenceDate = new Date()) {
|
|
|
74
82
|
* @param birthDate - date of birth
|
|
75
83
|
* @param referenceDate - date to calculate from (defaults to now)
|
|
76
84
|
*/
|
|
77
|
-
|
|
85
|
+
function getNextBirthday(birthDate, referenceDate = new Date()) {
|
|
78
86
|
const birth = new Date(birthDate);
|
|
79
87
|
const reference = new Date(referenceDate);
|
|
80
88
|
const nextBirthday = new Date(reference.getFullYear(), birth.getMonth(), birth.getDate());
|
|
@@ -89,7 +97,7 @@ export function getNextBirthday(birthDate, referenceDate = new Date()) {
|
|
|
89
97
|
* @param birthDate - date of birth
|
|
90
98
|
* @param referenceDate - date to calculate from (defaults to now)
|
|
91
99
|
*/
|
|
92
|
-
|
|
100
|
+
function getDaysUntilBirthday(birthDate, referenceDate = new Date()) {
|
|
93
101
|
const nextBirthday = getNextBirthday(birthDate, referenceDate);
|
|
94
102
|
return Math.ceil((nextBirthday.getTime() - referenceDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
95
103
|
}
|
|
@@ -98,7 +106,7 @@ export function getDaysUntilBirthday(birthDate, referenceDate = new Date()) {
|
|
|
98
106
|
* @param birthDate - date of birth
|
|
99
107
|
* @param referenceDate - date to check (defaults to now)
|
|
100
108
|
*/
|
|
101
|
-
|
|
109
|
+
function isBirthday(birthDate, referenceDate = new Date()) {
|
|
102
110
|
const birth = new Date(birthDate);
|
|
103
111
|
const reference = new Date(referenceDate);
|
|
104
112
|
return (birth.getMonth() === reference.getMonth() &&
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.differenceInUnits = differenceInUnits;
|
|
4
|
+
exports.addTime = addTime;
|
|
5
|
+
exports.subtractTime = subtractTime;
|
|
6
|
+
exports.startOf = startOf;
|
|
7
|
+
exports.endOf = endOf;
|
|
8
|
+
exports.isBetween = isBetween;
|
|
9
|
+
exports.businessDaysBetween = businessDaysBetween;
|
|
10
|
+
exports.roundToNearestUnit = roundToNearestUnit;
|
|
11
|
+
exports.ceilDate = ceilDate;
|
|
12
|
+
exports.floorDate = floorDate;
|
|
13
|
+
const constants_js_1 = require("./constants.cjs");
|
|
2
14
|
/**
|
|
3
15
|
* Calculate difference between two dates in specified unit
|
|
4
16
|
* @param date1 - first date
|
|
@@ -6,30 +18,30 @@ import { MILLISECONDS_PER_SECOND, MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_HOUR
|
|
|
6
18
|
* @param unit - unit to return the difference in
|
|
7
19
|
* @param precise - if true, returns decimal values; if false, returns integers
|
|
8
20
|
*/
|
|
9
|
-
|
|
21
|
+
function differenceInUnits(date1, date2, unit = 'milliseconds', precise = true) {
|
|
10
22
|
const diffMs = Math.abs(date1.getTime() - date2.getTime());
|
|
11
23
|
let result;
|
|
12
24
|
switch (unit) {
|
|
13
25
|
case 'years':
|
|
14
|
-
result = diffMs / MILLISECONDS_PER_YEAR;
|
|
26
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_YEAR;
|
|
15
27
|
break;
|
|
16
28
|
case 'months':
|
|
17
|
-
result = diffMs / MILLISECONDS_PER_MONTH;
|
|
29
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_MONTH;
|
|
18
30
|
break;
|
|
19
31
|
case 'weeks':
|
|
20
|
-
result = diffMs / MILLISECONDS_PER_WEEK;
|
|
32
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_WEEK;
|
|
21
33
|
break;
|
|
22
34
|
case 'days':
|
|
23
|
-
result = diffMs / MILLISECONDS_PER_DAY;
|
|
35
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_DAY;
|
|
24
36
|
break;
|
|
25
37
|
case 'hours':
|
|
26
|
-
result = diffMs / MILLISECONDS_PER_HOUR;
|
|
38
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_HOUR;
|
|
27
39
|
break;
|
|
28
40
|
case 'minutes':
|
|
29
|
-
result = diffMs / MILLISECONDS_PER_MINUTE;
|
|
41
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_MINUTE;
|
|
30
42
|
break;
|
|
31
43
|
case 'seconds':
|
|
32
|
-
result = diffMs / MILLISECONDS_PER_SECOND;
|
|
44
|
+
result = diffMs / constants_js_1.MILLISECONDS_PER_SECOND;
|
|
33
45
|
break;
|
|
34
46
|
case 'milliseconds':
|
|
35
47
|
default:
|
|
@@ -44,7 +56,7 @@ export function differenceInUnits(date1, date2, unit = 'milliseconds', precise =
|
|
|
44
56
|
* @param amount - amount to add
|
|
45
57
|
* @param unit - unit of the amount
|
|
46
58
|
*/
|
|
47
|
-
|
|
59
|
+
function addTime(date, amount, unit) {
|
|
48
60
|
const result = new Date(date);
|
|
49
61
|
switch (unit) {
|
|
50
62
|
case 'year':
|
|
@@ -97,7 +109,7 @@ export function addTime(date, amount, unit) {
|
|
|
97
109
|
* @param amount - amount to subtract
|
|
98
110
|
* @param unit - unit of the amount
|
|
99
111
|
*/
|
|
100
|
-
|
|
112
|
+
function subtractTime(date, amount, unit) {
|
|
101
113
|
return addTime(date, -amount, unit);
|
|
102
114
|
}
|
|
103
115
|
/**
|
|
@@ -105,7 +117,7 @@ export function subtractTime(date, amount, unit) {
|
|
|
105
117
|
* @param date - input date
|
|
106
118
|
* @param unit - time unit to get the start of
|
|
107
119
|
*/
|
|
108
|
-
|
|
120
|
+
function startOf(date, unit) {
|
|
109
121
|
const result = new Date(date);
|
|
110
122
|
switch (unit) {
|
|
111
123
|
case 'minute':
|
|
@@ -137,7 +149,7 @@ export function startOf(date, unit) {
|
|
|
137
149
|
* @param date - input date
|
|
138
150
|
* @param unit - time unit to get the end of
|
|
139
151
|
*/
|
|
140
|
-
|
|
152
|
+
function endOf(date, unit) {
|
|
141
153
|
const result = new Date(date);
|
|
142
154
|
switch (unit) {
|
|
143
155
|
case 'minute':
|
|
@@ -175,7 +187,7 @@ export function endOf(date, unit) {
|
|
|
175
187
|
* @param end - end date
|
|
176
188
|
* @param inclusive - whether boundaries are inclusive (default: true)
|
|
177
189
|
*/
|
|
178
|
-
|
|
190
|
+
function isBetween(date, start, end, inclusive = true) {
|
|
179
191
|
const time = date.getTime();
|
|
180
192
|
const startTime = start.getTime();
|
|
181
193
|
const endTime = end.getTime();
|
|
@@ -189,7 +201,7 @@ export function isBetween(date, start, end, inclusive = true) {
|
|
|
189
201
|
* @param startDate - start date
|
|
190
202
|
* @param endDate - end date
|
|
191
203
|
*/
|
|
192
|
-
|
|
204
|
+
function businessDaysBetween(startDate, endDate) {
|
|
193
205
|
let count = 0;
|
|
194
206
|
const current = new Date(startDate);
|
|
195
207
|
while (current <= endDate) {
|
|
@@ -209,7 +221,7 @@ export function businessDaysBetween(startDate, endDate) {
|
|
|
209
221
|
* roundToNearestUnit(new Date('2024-03-15T14:37:00'), 'hour') // 15:00
|
|
210
222
|
* roundToNearestUnit(new Date('2024-03-15T14:22:00'), 'hour') // 14:00
|
|
211
223
|
*/
|
|
212
|
-
|
|
224
|
+
function roundToNearestUnit(date, unit) {
|
|
213
225
|
const d = new Date(date);
|
|
214
226
|
switch (unit) {
|
|
215
227
|
case 'second':
|
|
@@ -263,7 +275,7 @@ export function roundToNearestUnit(date, unit) {
|
|
|
263
275
|
* @example
|
|
264
276
|
* ceilDate(new Date('2024-03-15T14:01:00'), 'hour') // 15:00
|
|
265
277
|
*/
|
|
266
|
-
|
|
278
|
+
function ceilDate(date, unit) {
|
|
267
279
|
const floored = floorDate(date, unit);
|
|
268
280
|
if (floored.getTime() === date.getTime())
|
|
269
281
|
return new Date(date);
|
|
@@ -297,7 +309,7 @@ export function ceilDate(date, unit) {
|
|
|
297
309
|
* @example
|
|
298
310
|
* floorDate(new Date('2024-03-15T14:59:00'), 'hour') // 14:00
|
|
299
311
|
*/
|
|
300
|
-
|
|
312
|
+
function floorDate(date, unit) {
|
|
301
313
|
const d = new Date(date);
|
|
302
314
|
switch (unit) {
|
|
303
315
|
case 'second':
|