ts-time-utils 4.1.0 → 4.4.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.
Files changed (74) hide show
  1. package/README.md +83 -32
  2. package/dist/{age.js → age.cjs} +14 -6
  3. package/dist/{calculate.js → calculate.cjs} +42 -18
  4. package/dist/calculate.d.ts +7 -0
  5. package/dist/calculate.d.ts.map +1 -1
  6. package/dist/{calendar.js → calendar.cjs} +80 -39
  7. package/dist/{calendars.js → calendars.cjs} +48 -23
  8. package/dist/{chain.js → chain.cjs} +41 -40
  9. package/dist/{compare.js → compare.cjs} +58 -28
  10. package/dist/constants.cjs +19 -0
  11. package/dist/{countdown.js → countdown.cjs} +16 -7
  12. package/dist/{cron.js → cron.cjs} +20 -9
  13. package/dist/{dateRange.js → dateRange.cjs} +42 -26
  14. package/dist/{duration.js → duration.cjs} +56 -44
  15. package/dist/esm/calculate.d.ts +7 -0
  16. package/dist/esm/calculate.d.ts.map +1 -1
  17. package/dist/esm/calculate.js +11 -0
  18. package/dist/esm/chain.js +0 -5
  19. package/dist/esm/format.d.ts.map +1 -1
  20. package/dist/esm/format.js +3 -3
  21. package/dist/esm/index.d.ts +1 -1
  22. package/dist/esm/index.d.ts.map +1 -1
  23. package/dist/esm/index.js +1 -1
  24. package/dist/esm/naturalLanguage.d.ts +1 -3
  25. package/dist/esm/naturalLanguage.d.ts.map +1 -1
  26. package/dist/esm/naturalLanguage.js +9 -2
  27. package/dist/esm/plugins.d.ts +0 -6
  28. package/dist/esm/plugins.d.ts.map +1 -1
  29. package/dist/esm/plugins.js +36 -42
  30. package/dist/esm/recurrence.d.ts.map +1 -1
  31. package/dist/esm/recurrence.js +3 -5
  32. package/dist/esm/timezone.d.ts +6 -1
  33. package/dist/esm/timezone.d.ts.map +1 -1
  34. package/dist/esm/timezone.js +106 -66
  35. package/dist/esm/types.d.ts +0 -4
  36. package/dist/esm/types.d.ts.map +1 -1
  37. package/dist/{finance.js → finance.cjs} +39 -22
  38. package/dist/{fiscal.js → fiscal.cjs} +36 -17
  39. package/dist/{format.js → format.cjs} +85 -72
  40. package/dist/format.d.ts.map +1 -1
  41. package/dist/{healthcare.js → healthcare.cjs} +37 -22
  42. package/dist/{holidays.js → holidays.cjs} +52 -25
  43. package/dist/index.cjs +596 -0
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/{interval.js → interval.cjs} +24 -11
  47. package/dist/{iterate.js → iterate.cjs} +84 -41
  48. package/dist/{locale.js → locale.cjs} +54 -26
  49. package/dist/{naturalLanguage.js → naturalLanguage.cjs} +36 -23
  50. package/dist/naturalLanguage.d.ts +1 -3
  51. package/dist/naturalLanguage.d.ts.map +1 -1
  52. package/dist/{parse.js → parse.cjs} +24 -11
  53. package/dist/{performance.js → performance.cjs} +23 -10
  54. package/dist/{plugins.js → plugins.cjs} +48 -47
  55. package/dist/plugins.d.ts +0 -6
  56. package/dist/plugins.d.ts.map +1 -1
  57. package/dist/{precision.js → precision.cjs} +74 -37
  58. package/dist/{rangePresets.js → rangePresets.cjs} +40 -19
  59. package/dist/{recurrence.js → recurrence.cjs} +27 -21
  60. package/dist/recurrence.d.ts.map +1 -1
  61. package/dist/{scheduling.js → scheduling.cjs} +46 -31
  62. package/dist/{serialize.js → serialize.cjs} +36 -17
  63. package/dist/{temporal.js → temporal.cjs} +28 -13
  64. package/dist/{timezone.js → timezone.cjs} +140 -82
  65. package/dist/timezone.d.ts +6 -1
  66. package/dist/timezone.d.ts.map +1 -1
  67. package/dist/{types.js → types.cjs} +9 -3
  68. package/dist/types.d.ts +0 -4
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/{validate.js → validate.cjs} +54 -26
  71. package/dist/{workingHours.js → workingHours.cjs} +36 -17
  72. package/package.json +41 -38
  73. package/dist/constants.js +0 -16
  74. package/dist/index.js +0 -72
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, 430+ functions across 32 categories.
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
  [![npm version](https://img.shields.io/npm/v/ts-time-utils.svg)](https://www.npmjs.com/package/ts-time-utils)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](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** — 430+ functions across 32 utility categories
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
@@ -69,9 +85,10 @@ parseDuration('1h 30m'); // 5400000 (ms)
69
85
  Date arithmetic, differences, and business day calculations.
70
86
 
71
87
  ```ts
72
- import { differenceInUnits, addTime, startOf, endOf } from 'ts-time-utils/calculate';
88
+ import { differenceInUnits, differenceInCalendarDays, addTime, startOf, endOf } from 'ts-time-utils/calculate';
73
89
 
74
90
  differenceInUnits(date1, date2, 'days'); // 10
91
+ differenceInCalendarDays(date1, date2); // Calendar date boundary count
75
92
  addTime(new Date(), 5, 'hours'); // 5 hours from now
76
93
  startOf(new Date(), 'day'); // 00:00:00 today
77
94
  endOf(new Date(), 'month'); // Last moment of month
@@ -125,18 +142,22 @@ chain(new Date())
125
142
  .format('YYYY-MM-DD'); // Next week Monday
126
143
  ```
127
144
 
145
+ 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.
146
+
128
147
  ### Timezone
129
148
 
130
149
  Timezone conversions, DST handling, and zone comparisons.
131
150
 
132
151
  ```ts
133
- import { formatInTimeZone, isDST, convertTimezone } from 'ts-time-utils/timezone';
152
+ import { formatInTimeZone, isDST, convertBetweenZones } from 'ts-time-utils/timezone';
134
153
 
135
- formatInTimeZone(date, 'America/New_York');
154
+ formatInTimeZone(new Date(), 'America/New_York');
136
155
  isDST(new Date('2025-07-14'), 'America/New_York'); // true
137
- convertTimezone(date, 'UTC', 'Asia/Tokyo');
156
+ convertBetweenZones(new Date(), 'UTC', 'Asia/Tokyo');
138
157
  ```
139
158
 
159
+ `isDST()` uses a yearly-offset heuristic rather than authoritative transition metadata.
160
+
140
161
  ### Calendar
141
162
 
142
163
  ISO weeks, quarters, holidays, and calendar grids.
@@ -191,12 +212,14 @@ recurrenceToString(weekly.rule); // "Every week on Monday, Wednesday, Friday"
191
212
  Parse and match cron expressions.
192
213
 
193
214
  ```ts
194
- import { matchesCron, getNextCronDate, describeCron, CRON_PRESETS } from 'ts-time-utils/cron';
215
+ import { parseCronExpression, matchesCron, getNextCronDate, describeCron } from 'ts-time-utils/cron';
216
+
217
+ const date = new Date();
195
218
 
196
- matchesCron('0 9 * * 1-5', date); // true if weekday 9am
219
+ parseCronExpression('0 9 * * 1-5'); // minute/hour/day/month/day-of-week parts
220
+ matchesCron(date, '0 9 * * 1-5'); // true if weekday 9am
197
221
  getNextCronDate('0 9 * * *'); // Next 9am
198
222
  describeCron('0 9 * * 1-5'); // "At 09:00 on Monday through Friday"
199
- CRON_PRESETS.DAILY; // "0 0 * * *"
200
223
  ```
201
224
 
202
225
  ### Fiscal Year
@@ -204,11 +227,13 @@ CRON_PRESETS.DAILY; // "0 0 * * *"
204
227
  Fiscal year utilities with configurable start month.
205
228
 
206
229
  ```ts
207
- import { getFiscalYear, getFiscalQuarter, FISCAL_PRESETS } from 'ts-time-utils/fiscal';
230
+ import { getFiscalYear, getFiscalQuarter } from 'ts-time-utils/fiscal';
208
231
 
209
- getFiscalYear(date, FISCAL_PRESETS.UK_INDIA); // April start
210
- getFiscalYear(date, FISCAL_PRESETS.AUSTRALIA); // July start
211
- getFiscalYear(date, FISCAL_PRESETS.US_FEDERAL); // October start
232
+ const date = new Date();
233
+
234
+ getFiscalYear(date, { startMonth: 4 }); // April start
235
+ getFiscalYear(date, { startMonth: 7 }); // July start
236
+ getFiscalYear(date, { startMonth: 10 }); // October start
212
237
  getFiscalQuarter(date, { startMonth: 4 }); // Q2 for UK fiscal
213
238
  ```
214
239
 
@@ -254,6 +279,8 @@ extractDatesFromText('Meeting tomorrow at 3pm');
254
279
  // [{ date: Date, text: 'tomorrow at 3pm', confidence: 0.9 }]
255
280
  ```
256
281
 
282
+ `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.
283
+
257
284
  ### International Holidays
258
285
 
259
286
  Public holidays for 20 countries.
@@ -261,10 +288,12 @@ Public holidays for 20 countries.
261
288
  ```ts
262
289
  import { getHolidays, isHoliday, getNextHoliday } from 'ts-time-utils/holidays';
263
290
 
291
+ const today = new Date();
292
+
264
293
  getHolidays(2025, 'UK'); // UK bank holidays
265
294
  getHolidays(2025, 'DE'); // German holidays
266
- isHoliday(date, 'CA'); // Is Canadian holiday?
267
- getNextHoliday(date, 'AU'); // Next Australian holiday
295
+ isHoliday(today, 'CA'); // Is Canadian holiday?
296
+ getNextHoliday(today, 'AU'); // Next Australian holiday
268
297
 
269
298
  // Supported: UK, NL, DE, CA, AU, IT, ES, CN, IN, US,
270
299
  // JP, FR, BR, MX, KR, SG, PL, SE, BE, CH
@@ -277,6 +306,9 @@ Multi-language formatting with 40+ locales.
277
306
  ```ts
278
307
  import { formatRelativeTime, formatDateLocale, detectLocale } from 'ts-time-utils/locale';
279
308
 
309
+ const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000);
310
+ const date = new Date();
311
+
280
312
  formatRelativeTime(pastDate, { locale: 'es' }); // "hace 2 horas"
281
313
  formatRelativeTime(pastDate, { locale: 'de' }); // "vor 2 Stunden"
282
314
  formatDateLocale(date, 'fr', 'long'); // "15 janvier 2024"
@@ -285,14 +317,24 @@ detectLocale(); // Auto-detect system locale
285
317
 
286
318
  ### Working Hours
287
319
 
288
- Business hours calculations with break support.
320
+ Business hours calculations with break support. These helpers use the
321
+ `Date` values you pass in directly; if you need a different timezone's wall
322
+ clock, adapt the instant first with a timezone helper such as
323
+ `convertDateToZone()` or `reinterpretAsZone()`.
289
324
 
290
325
  ```ts
291
326
  import { isWorkingTime, addWorkingDays, workingDaysBetween } from 'ts-time-utils/workingHours';
292
327
 
293
- isWorkingTime(date, config);
294
- addWorkingDays(date, 5, config);
295
- workingDaysBetween(start, end, config);
328
+ const config = {
329
+ workingDays: [1, 2, 3, 4, 5],
330
+ hours: { start: 9, end: 17 },
331
+ breaks: [{ start: 12, end: 13 }]
332
+ };
333
+ const now = new Date();
334
+
335
+ isWorkingTime(now, config);
336
+ addWorkingDays(now, 5, config);
337
+ workingDaysBetween(now, new Date('2025-12-31'), config);
296
338
  ```
297
339
 
298
340
  ### Serialization
@@ -450,12 +492,12 @@ leapSecondsBetween(date1, date2); // Number of leap seconds
450
492
  Date parsing from various formats.
451
493
 
452
494
  ```ts
453
- import { parseDate, parseTime, autoDetectFormat } from 'ts-time-utils/parse';
495
+ import { parseDate, parseTime, guessDateFormat } from 'ts-time-utils/parse';
454
496
 
455
497
  parseDate('Dec 25, 2025');
456
498
  parseDate('25/12/2025', 'DD/MM/YYYY');
457
499
  parseTime('2:30 PM'); // { hour: 14, minute: 30 }
458
- autoDetectFormat('2025-09-14'); // 'YYYY-MM-DD'
500
+ guessDateFormat('2025-09-14'); // 'YYYY-MM-DD'
459
501
  ```
460
502
 
461
503
  ### Scheduling
@@ -471,7 +513,10 @@ import {
471
513
  // Generate 30-min slots for a day
472
514
  const slots = generateSlots(new Date(), {
473
515
  slotDuration: 30,
474
- workingHours: { startTime: { hour: 9, minute: 0 }, endTime: { hour: 17, minute: 0 } }
516
+ workingHours: {
517
+ workingDays: [1, 2, 3, 4, 5],
518
+ hours: { start: 9, end: 17 }
519
+ }
475
520
  });
476
521
 
477
522
  // Find available slots (excluding existing bookings)
@@ -557,21 +602,20 @@ timeUntilDeadline(eventDate, deadline); // Duration remaining
557
602
  Extend ChainedDate with custom functionality.
558
603
 
559
604
  ```ts
560
- import { chain, registerPlugin, createPlugin } from 'ts-time-utils/chain';
605
+ import { chain, ChainedDate } from 'ts-time-utils/chain';
606
+ import { extend } from 'ts-time-utils/plugins';
561
607
 
562
- const businessPlugin = createPlugin('business', {
563
- addBusinessDays(days: number) {
608
+ extend('business', {
609
+ addBusinessDays(this: ChainedDate, days: number) {
564
610
  // Implementation
565
611
  return this;
566
612
  },
567
- isBusinessDay() {
613
+ isBusinessDay(this: ChainedDate) {
568
614
  const day = this.toDate().getDay();
569
615
  return day !== 0 && day !== 6;
570
616
  }
571
617
  });
572
618
 
573
- registerPlugin(businessPlugin);
574
-
575
619
  chain(new Date())
576
620
  .addBusinessDays(5)
577
621
  .isBusinessDay(); // true/false
@@ -628,6 +672,7 @@ For complete API documentation, see the [Playground & Docs](https://ts-time-util
628
672
  npm install # Install dependencies
629
673
  npm run build # Build both CJS and ESM
630
674
  npm test # Run tests
675
+ npm run test:package # Verify built package exports after build
631
676
  npm run lint # Lint code
632
677
  ```
633
678
 
@@ -638,16 +683,22 @@ Releases are automated via GitHub Actions with npm trusted publishing (OIDC).
638
683
  **To release a new version:**
639
684
 
640
685
  ```bash
641
- git tag v4.0.1 # Create tag (use semantic versioning)
642
- git push --tags # Push tag triggers publish workflow
686
+ git tag vX.Y.Z # Create a semantic version tag for the release
687
+ git push --tags # Push tag -> triggers publish workflow
643
688
  ```
644
689
 
645
690
  The workflow automatically:
646
691
  1. Sets `package.json` version from tag
647
- 2. Runs lint, tests, and build
692
+ 2. Runs `npm run release:verify`
648
693
  3. Publishes to npm with provenance
649
694
 
650
- **Version format:** Tags must match `v*` pattern (e.g., `v4.0.0`, `v4.1.0-beta.1`)
695
+ **Version format:** Tags must match `v*` pattern (e.g., `v1.2.3`, `v1.2.3-beta.1`)
696
+
697
+ Before tagging, run:
698
+
699
+ ```bash
700
+ npm run release:verify
701
+ ```
651
702
 
652
703
  ## License
653
704
 
@@ -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
- export function calculateAge(birthDate, referenceDate = new Date()) {
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
- export function getAgeInUnits(birthDate, unit, referenceDate = new Date()) {
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
- export function getLifeStage(birthDate, referenceDate = new Date()) {
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
- export function getNextBirthday(birthDate, referenceDate = new Date()) {
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
- export function getDaysUntilBirthday(birthDate, referenceDate = new Date()) {
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
- export function isBirthday(birthDate, referenceDate = new Date()) {
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,17 @@
1
- import { MILLISECONDS_PER_SECOND, MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_HOUR, MILLISECONDS_PER_DAY, MILLISECONDS_PER_WEEK, MILLISECONDS_PER_MONTH, MILLISECONDS_PER_YEAR } from './constants.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.differenceInUnits = differenceInUnits;
4
+ exports.differenceInCalendarDays = differenceInCalendarDays;
5
+ exports.addTime = addTime;
6
+ exports.subtractTime = subtractTime;
7
+ exports.startOf = startOf;
8
+ exports.endOf = endOf;
9
+ exports.isBetween = isBetween;
10
+ exports.businessDaysBetween = businessDaysBetween;
11
+ exports.roundToNearestUnit = roundToNearestUnit;
12
+ exports.ceilDate = ceilDate;
13
+ exports.floorDate = floorDate;
14
+ const constants_js_1 = require("./constants.cjs");
2
15
  /**
3
16
  * Calculate difference between two dates in specified unit
4
17
  * @param date1 - first date
@@ -6,30 +19,30 @@ import { MILLISECONDS_PER_SECOND, MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_HOUR
6
19
  * @param unit - unit to return the difference in
7
20
  * @param precise - if true, returns decimal values; if false, returns integers
8
21
  */
9
- export function differenceInUnits(date1, date2, unit = 'milliseconds', precise = true) {
22
+ function differenceInUnits(date1, date2, unit = 'milliseconds', precise = true) {
10
23
  const diffMs = Math.abs(date1.getTime() - date2.getTime());
11
24
  let result;
12
25
  switch (unit) {
13
26
  case 'years':
14
- result = diffMs / MILLISECONDS_PER_YEAR;
27
+ result = diffMs / constants_js_1.MILLISECONDS_PER_YEAR;
15
28
  break;
16
29
  case 'months':
17
- result = diffMs / MILLISECONDS_PER_MONTH;
30
+ result = diffMs / constants_js_1.MILLISECONDS_PER_MONTH;
18
31
  break;
19
32
  case 'weeks':
20
- result = diffMs / MILLISECONDS_PER_WEEK;
33
+ result = diffMs / constants_js_1.MILLISECONDS_PER_WEEK;
21
34
  break;
22
35
  case 'days':
23
- result = diffMs / MILLISECONDS_PER_DAY;
36
+ result = diffMs / constants_js_1.MILLISECONDS_PER_DAY;
24
37
  break;
25
38
  case 'hours':
26
- result = diffMs / MILLISECONDS_PER_HOUR;
39
+ result = diffMs / constants_js_1.MILLISECONDS_PER_HOUR;
27
40
  break;
28
41
  case 'minutes':
29
- result = diffMs / MILLISECONDS_PER_MINUTE;
42
+ result = diffMs / constants_js_1.MILLISECONDS_PER_MINUTE;
30
43
  break;
31
44
  case 'seconds':
32
- result = diffMs / MILLISECONDS_PER_SECOND;
45
+ result = diffMs / constants_js_1.MILLISECONDS_PER_SECOND;
33
46
  break;
34
47
  case 'milliseconds':
35
48
  default:
@@ -38,13 +51,24 @@ export function differenceInUnits(date1, date2, unit = 'milliseconds', precise =
38
51
  }
39
52
  return precise ? result : Math.floor(result);
40
53
  }
54
+ /**
55
+ * Calculate the difference in local calendar days between two dates.
56
+ *
57
+ * Unlike differenceInUnits(date1, date2, 'days'), this ignores the time of day
58
+ * and counts date boundaries, so late today to midnight two dates from now is 2.
59
+ */
60
+ function differenceInCalendarDays(date1, date2) {
61
+ const start1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
62
+ const start2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
63
+ return Math.round(Math.abs(start1 - start2) / constants_js_1.MILLISECONDS_PER_DAY);
64
+ }
41
65
  /**
42
66
  * Add time to a date
43
67
  * @param date - base date
44
68
  * @param amount - amount to add
45
69
  * @param unit - unit of the amount
46
70
  */
47
- export function addTime(date, amount, unit) {
71
+ function addTime(date, amount, unit) {
48
72
  const result = new Date(date);
49
73
  switch (unit) {
50
74
  case 'year':
@@ -97,7 +121,7 @@ export function addTime(date, amount, unit) {
97
121
  * @param amount - amount to subtract
98
122
  * @param unit - unit of the amount
99
123
  */
100
- export function subtractTime(date, amount, unit) {
124
+ function subtractTime(date, amount, unit) {
101
125
  return addTime(date, -amount, unit);
102
126
  }
103
127
  /**
@@ -105,7 +129,7 @@ export function subtractTime(date, amount, unit) {
105
129
  * @param date - input date
106
130
  * @param unit - time unit to get the start of
107
131
  */
108
- export function startOf(date, unit) {
132
+ function startOf(date, unit) {
109
133
  const result = new Date(date);
110
134
  switch (unit) {
111
135
  case 'minute':
@@ -137,7 +161,7 @@ export function startOf(date, unit) {
137
161
  * @param date - input date
138
162
  * @param unit - time unit to get the end of
139
163
  */
140
- export function endOf(date, unit) {
164
+ function endOf(date, unit) {
141
165
  const result = new Date(date);
142
166
  switch (unit) {
143
167
  case 'minute':
@@ -175,7 +199,7 @@ export function endOf(date, unit) {
175
199
  * @param end - end date
176
200
  * @param inclusive - whether boundaries are inclusive (default: true)
177
201
  */
178
- export function isBetween(date, start, end, inclusive = true) {
202
+ function isBetween(date, start, end, inclusive = true) {
179
203
  const time = date.getTime();
180
204
  const startTime = start.getTime();
181
205
  const endTime = end.getTime();
@@ -189,7 +213,7 @@ export function isBetween(date, start, end, inclusive = true) {
189
213
  * @param startDate - start date
190
214
  * @param endDate - end date
191
215
  */
192
- export function businessDaysBetween(startDate, endDate) {
216
+ function businessDaysBetween(startDate, endDate) {
193
217
  let count = 0;
194
218
  const current = new Date(startDate);
195
219
  while (current <= endDate) {
@@ -209,7 +233,7 @@ export function businessDaysBetween(startDate, endDate) {
209
233
  * roundToNearestUnit(new Date('2024-03-15T14:37:00'), 'hour') // 15:00
210
234
  * roundToNearestUnit(new Date('2024-03-15T14:22:00'), 'hour') // 14:00
211
235
  */
212
- export function roundToNearestUnit(date, unit) {
236
+ function roundToNearestUnit(date, unit) {
213
237
  const d = new Date(date);
214
238
  switch (unit) {
215
239
  case 'second':
@@ -263,7 +287,7 @@ export function roundToNearestUnit(date, unit) {
263
287
  * @example
264
288
  * ceilDate(new Date('2024-03-15T14:01:00'), 'hour') // 15:00
265
289
  */
266
- export function ceilDate(date, unit) {
290
+ function ceilDate(date, unit) {
267
291
  const floored = floorDate(date, unit);
268
292
  if (floored.getTime() === date.getTime())
269
293
  return new Date(date);
@@ -297,7 +321,7 @@ export function ceilDate(date, unit) {
297
321
  * @example
298
322
  * floorDate(new Date('2024-03-15T14:59:00'), 'hour') // 14:00
299
323
  */
300
- export function floorDate(date, unit) {
324
+ function floorDate(date, unit) {
301
325
  const d = new Date(date);
302
326
  switch (unit) {
303
327
  case 'second':
@@ -7,6 +7,13 @@ import { TimeUnit } from './constants.js';
7
7
  * @param precise - if true, returns decimal values; if false, returns integers
8
8
  */
9
9
  export declare function differenceInUnits(date1: Date, date2: Date, unit?: TimeUnit, precise?: boolean): number;
10
+ /**
11
+ * Calculate the difference in local calendar days between two dates.
12
+ *
13
+ * Unlike differenceInUnits(date1, date2, 'days'), this ignores the time of day
14
+ * and counts date boundaries, so late today to midnight two dates from now is 2.
15
+ */
16
+ export declare function differenceInCalendarDays(date1: Date, date2: Date): number;
10
17
  /**
11
18
  * Add time to a date
12
19
  * @param date - base date
@@ -1 +1 @@
1
- {"version":3,"file":"calculate.d.ts","sourceRoot":"","sources":["../src/calculate.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAExB;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,EACX,IAAI,GAAE,QAAyB,EAC/B,OAAO,GAAE,OAAc,GACtB,MAAM,CAkCR;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAgDxE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CA4BrG;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CA4BnG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,GAAE,OAAc,GAAG,OAAO,CAShG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,MAAM,CAa1E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA0BN;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA8BN"}
1
+ {"version":3,"file":"calculate.d.ts","sourceRoot":"","sources":["../src/calculate.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAExB;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,EACX,IAAI,GAAE,QAAyB,EAC/B,OAAO,GAAE,OAAc,GACtB,MAAM,CAkCR;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,CAKzE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAgDxE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CA4BrG;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CA4BnG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,GAAE,OAAc,GAAG,OAAO,CAShG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,MAAM,CAa1E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA0BN;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAC5D,IAAI,CA8BN"}