ts-time-utils 1.1.0 → 3.0.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.
Files changed (92) hide show
  1. package/README.md +567 -12
  2. package/dist/calculate.d.ts +7 -2
  3. package/dist/calculate.d.ts.map +1 -1
  4. package/dist/calculate.js +13 -3
  5. package/dist/calendar.d.ts +103 -0
  6. package/dist/calendar.d.ts.map +1 -1
  7. package/dist/calendar.js +224 -0
  8. package/dist/chain.d.ts +269 -0
  9. package/dist/chain.d.ts.map +1 -0
  10. package/dist/chain.js +422 -0
  11. package/dist/compare.d.ts +217 -0
  12. package/dist/compare.d.ts.map +1 -0
  13. package/dist/compare.js +417 -0
  14. package/dist/cron.d.ts +82 -0
  15. package/dist/cron.d.ts.map +1 -0
  16. package/dist/cron.js +294 -0
  17. package/dist/esm/calculate.d.ts +7 -2
  18. package/dist/esm/calculate.d.ts.map +1 -1
  19. package/dist/esm/calculate.js +13 -3
  20. package/dist/esm/calendar.d.ts +103 -0
  21. package/dist/esm/calendar.d.ts.map +1 -1
  22. package/dist/esm/calendar.js +224 -0
  23. package/dist/esm/chain.d.ts +269 -0
  24. package/dist/esm/chain.d.ts.map +1 -0
  25. package/dist/esm/chain.js +422 -0
  26. package/dist/esm/compare.d.ts +217 -0
  27. package/dist/esm/compare.d.ts.map +1 -0
  28. package/dist/esm/compare.js +417 -0
  29. package/dist/esm/cron.d.ts +82 -0
  30. package/dist/esm/cron.d.ts.map +1 -0
  31. package/dist/esm/cron.js +294 -0
  32. package/dist/esm/fiscal.d.ts +195 -0
  33. package/dist/esm/fiscal.d.ts.map +1 -0
  34. package/dist/esm/fiscal.js +295 -0
  35. package/dist/esm/format.d.ts +65 -0
  36. package/dist/esm/format.d.ts.map +1 -1
  37. package/dist/esm/format.js +202 -0
  38. package/dist/esm/holidays.d.ts +62 -0
  39. package/dist/esm/holidays.d.ts.map +1 -0
  40. package/dist/esm/holidays.js +793 -0
  41. package/dist/esm/index.d.ts +18 -6
  42. package/dist/esm/index.d.ts.map +1 -1
  43. package/dist/esm/index.js +20 -6
  44. package/dist/esm/iterate.d.ts +212 -0
  45. package/dist/esm/iterate.d.ts.map +1 -0
  46. package/dist/esm/iterate.js +409 -0
  47. package/dist/esm/parse.d.ts +45 -0
  48. package/dist/esm/parse.d.ts.map +1 -1
  49. package/dist/esm/parse.js +207 -0
  50. package/dist/esm/plugins.d.ts +129 -0
  51. package/dist/esm/plugins.d.ts.map +1 -0
  52. package/dist/esm/plugins.js +173 -0
  53. package/dist/esm/timezone.d.ts +52 -0
  54. package/dist/esm/timezone.d.ts.map +1 -1
  55. package/dist/esm/timezone.js +171 -0
  56. package/dist/esm/validate.d.ts +51 -0
  57. package/dist/esm/validate.d.ts.map +1 -1
  58. package/dist/esm/validate.js +92 -0
  59. package/dist/esm/workingHours.d.ts +70 -0
  60. package/dist/esm/workingHours.d.ts.map +1 -1
  61. package/dist/esm/workingHours.js +161 -0
  62. package/dist/fiscal.d.ts +195 -0
  63. package/dist/fiscal.d.ts.map +1 -0
  64. package/dist/fiscal.js +295 -0
  65. package/dist/format.d.ts +65 -0
  66. package/dist/format.d.ts.map +1 -1
  67. package/dist/format.js +202 -0
  68. package/dist/holidays.d.ts +62 -0
  69. package/dist/holidays.d.ts.map +1 -0
  70. package/dist/holidays.js +793 -0
  71. package/dist/index.d.ts +18 -6
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +20 -6
  74. package/dist/iterate.d.ts +212 -0
  75. package/dist/iterate.d.ts.map +1 -0
  76. package/dist/iterate.js +409 -0
  77. package/dist/parse.d.ts +45 -0
  78. package/dist/parse.d.ts.map +1 -1
  79. package/dist/parse.js +207 -0
  80. package/dist/plugins.d.ts +129 -0
  81. package/dist/plugins.d.ts.map +1 -0
  82. package/dist/plugins.js +173 -0
  83. package/dist/timezone.d.ts +52 -0
  84. package/dist/timezone.d.ts.map +1 -1
  85. package/dist/timezone.js +171 -0
  86. package/dist/validate.d.ts +51 -0
  87. package/dist/validate.d.ts.map +1 -1
  88. package/dist/validate.js +92 -0
  89. package/dist/workingHours.d.ts +70 -0
  90. package/dist/workingHours.d.ts.map +1 -1
  91. package/dist/workingHours.js +161 -0
  92. package/package.json +40 -1
package/README.md CHANGED
@@ -8,7 +8,7 @@ A lightweight TypeScript utility library for time formatting, calculations, and
8
8
  - **⚡ Fast** - Zero dependencies, pure JavaScript functions
9
9
  - **🔧 TypeScript** - Full type safety and IntelliSense support
10
10
  - **🌳 Tree-shakable** - Import individual functions to minimize bundle size
11
- - **📚 Comprehensive** - 19 utility categories with 150+ functions
11
+ - **📚 Comprehensive** - 26 utility categories with 320+ functions
12
12
 
13
13
  ### 🔄 Recurrence utilities **(NEW!)**
14
14
 
@@ -70,6 +70,9 @@ A lightweight TypeScript utility library for time formatting, calculations, and
70
70
  - Get human-friendly "time ago" strings
71
71
  - Parse duration strings back to milliseconds
72
72
  - Format time in 12h/24h/ISO formats
73
+ - Custom date formatting with pattern strings (YYYY-MM-DD, etc.)
74
+ - Format date ranges and ordinals
75
+ - Calendar-friendly date formatting ("Today", "Tomorrow", "Monday")
73
76
 
74
77
  ### 🧮 Calculation utilities
75
78
 
@@ -83,7 +86,10 @@ A lightweight TypeScript utility library for time formatting, calculations, and
83
86
 
84
87
  - Validate dates and time strings
85
88
  - Check for leap years, weekends, past/future dates
86
- - Compare dates (same day, today, yesterday, etc.)
89
+ - Compare dates (same day, same week, same month, same year)
90
+ - Check relative periods (isThisWeek, isThisMonth, isThisYear)
91
+ - Business day validation with holiday support
92
+ - Check if date is within last/next N days
87
93
 
88
94
  ### 🎂 Age utilities
89
95
 
@@ -96,8 +102,12 @@ A lightweight TypeScript utility library for time formatting, calculations, and
96
102
 
97
103
  - ISO week numbers and week-based calculations
98
104
  - Quarter operations and fiscal year support
99
- - Holiday calculations (Easter, Thanksgiving, etc.)
105
+ - Holiday calculations (Easter, US federal holidays)
100
106
  - Days in month/year calculations
107
+ - Get nth occurrence of weekday in month
108
+ - US holiday functions (Thanksgiving, Memorial Day, Labor Day, etc.)
109
+ - Week start/end calculations
110
+ - Calendar grid generation
101
111
 
102
112
  ### 🔍 Parse utilities
103
113
 
@@ -105,6 +115,10 @@ A lightweight TypeScript utility library for time formatting, calculations, and
105
115
  - Relative date parsing ("tomorrow", "next week")
106
116
  - Custom format parsing with flexible patterns
107
117
  - Smart date interpretation
118
+ - ISO 8601 duration parsing (P1Y2M3DT4H5M6S)
119
+ - Time string parsing (14:30, 2:30 PM)
120
+ - Auto-detect date format
121
+ - Parse range endpoints ("end of month", "start of year")
108
122
 
109
123
  ### ⚡ Performance utilities
110
124
 
@@ -127,14 +141,22 @@ A lightweight TypeScript utility library for time formatting, calculations, and
127
141
  - Format in specific timezone
128
142
  - Convert absolute moment to zone components
129
143
  - Reinterpret wall-clock times
144
+ - Daylight Saving Time detection
145
+ - Find next DST transition
146
+ - Find common working hours across timezones
147
+ - Convert dates between timezones
130
148
 
131
149
  ### 🕘 Working hours utilities
132
150
 
133
151
  - Define working day patterns and breaks
134
152
  - Check working day/time
135
153
  - Compute working time between dates
136
- - Add working hours across days
137
- - Find next working time
154
+ - Add/subtract working hours and days
155
+ - Find next/previous working day
156
+ - Get working days in month
157
+ - Count working days between dates
158
+ - Break time detection
159
+ - Work day start/end times
138
160
 
139
161
  ### 🎯 Range preset utilities
140
162
 
@@ -153,6 +175,75 @@ A lightweight TypeScript utility library for time formatting, calculations, and
153
175
  - Internationalization (i18n) support
154
176
  - **Locale conversions** - Convert between different locales and detect locale from text
155
177
 
178
+ ### ⏰ Cron utilities **(NEW!)**
179
+
180
+ - Parse and validate cron expressions (5-field format)
181
+ - Check if a date matches a cron expression
182
+ - Get next/previous occurrence dates
183
+ - Get multiple future occurrences
184
+ - Human-readable cron descriptions
185
+ - Common cron presets (every minute, hourly, daily, weekly, etc.)
186
+ - Support for wildcards, ranges, steps, and lists
187
+
188
+ ### 📅 Fiscal Year utilities **(NEW!)**
189
+
190
+ - Configurable fiscal year start month (calendar, UK/India April, Australia July, US Federal October)
191
+ - Get fiscal year, quarter, month, and week for any date
192
+ - Calculate fiscal year/quarter start and end dates
193
+ - Track fiscal year progress and days elapsed/remaining
194
+ - Format fiscal years and quarters (FY2024, Q1 FY2024, FY2023/24)
195
+ - Common fiscal presets: CALENDAR, UK_INDIA, AUSTRALIA, US_FEDERAL
196
+
197
+ ### 🔄 Date Comparison & Sorting **(NEW!)**
198
+
199
+ - Sort date arrays ascending or descending
200
+ - Find min/max/median/average dates in arrays
201
+ - Find closest/farthest dates from target
202
+ - Remove duplicate dates
203
+ - Group dates by year/month/day/weekday
204
+ - Snap dates to grid and round to nearest unit
205
+ - Validate chronological order
206
+ - Get date span and partition into groups
207
+ - Select nth dates from sorted arrays
208
+
209
+ ### ⏭️ Date Iteration & Counting **(NEW!)**
210
+
211
+ - Iterate through date sequences: days, weekdays, weekends, weeks, months, quarters, years
212
+ - Count dates in ranges: count all days, weekdays, weekend days, weeks, months
213
+ - Lazy iteration with generators for memory efficiency
214
+ - Filter dates by custom conditions
215
+ - Iterate specific day patterns (e.g., all Mondays)
216
+ - Get month-end dates in range
217
+ - Get nth day of each month in range
218
+
219
+ ### 🌍 International Holidays **(NEW!)**
220
+
221
+ - Calculate public holidays for 9 countries: UK, Netherlands, Germany, Canada, Australia, Italy, Spain, China, India
222
+ - Fixed holidays (New Year, Christmas, National Days)
223
+ - Easter-based holidays (Good Friday, Easter Monday, Whit Monday)
224
+ - Movable holidays (Victoria Day, Thanksgiving, Spring Bank Holiday)
225
+ - Unified API: check if date is holiday, get holiday name, find next holiday
226
+ - Weekend adjustment for substitute holidays
227
+ - Get upcoming holidays within timeframe
228
+ - Support for both federal and regional observances
229
+ - Find closest date to a target (past, future, or any)
230
+ - Clamp dates to ranges
231
+ - Remove duplicate dates with precision control
232
+ - Group dates by year, month, day, or day of week
233
+ - Round and snap dates to intervals (e.g., nearest 15 minutes)
234
+ - Check if dates are in chronological order
235
+ - Partition dates by predicate
236
+
237
+ ### 🔁 Date Iteration utilities **(NEW!)**
238
+
239
+ - Generate arrays of dates: `eachDay()`, `eachWeekday()`, `eachWeekend()`
240
+ - Iterate by period: `eachWeek()`, `eachMonth()`, `eachQuarter()`, `eachYear()`
241
+ - Time iteration: `eachHour()`, `eachMinute()`, `eachInterval()`
242
+ - Get specific days: `eachDayOfWeek()`, `eachNthDayOfMonth()`, `eachMonthEnd()`
243
+ - Count functions: `countDays()`, `countWeekdays()`, `countWeekendDays()`
244
+ - Lazy iterators for memory efficiency: `iterateDays()`, `iterateWeekdays()`, `iterateMonths()`
245
+ - Custom filtering with `filterDays()`
246
+
156
247
  ### 🧱 Constants
157
248
 
158
249
  - Milliseconds & seconds per unit
@@ -175,16 +266,20 @@ import { formatDuration, timeAgo, isValidDate } from "ts-time-utils";
175
266
  ### Import by category (better for tree-shaking)
176
267
 
177
268
  ```ts
178
- import { formatDuration, timeAgo } from "ts-time-utils/format";
269
+ import { formatDuration, timeAgo, formatDate } from "ts-time-utils/format";
179
270
  import { differenceInUnits, addTime } from "ts-time-utils/calculate";
180
- import { isValidDate, isLeapYear } from "ts-time-utils/validate";
271
+ import { isValidDate, isLeapYear, isSameWeek } from "ts-time-utils/validate";
181
272
  import { calculateAge, getNextBirthday } from "ts-time-utils/age";
182
- import { getWeekNumber, getQuarter } from "ts-time-utils/calendar";
183
- import { parseDate, parseRelativeDate } from "ts-time-utils/parse";
273
+ import {
274
+ getWeekNumber,
275
+ getQuarter,
276
+ getUSHolidays,
277
+ } from "ts-time-utils/calendar";
278
+ import { parseDate, parseRelativeDate, parseTime } from "ts-time-utils/parse";
184
279
  import { sleep, benchmark, Stopwatch } from "ts-time-utils/performance";
185
280
  import { createInterval, mergeIntervals } from "ts-time-utils/interval";
186
- import { formatInTimeZone } from "ts-time-utils/timezone";
187
- import { isWorkingTime, addWorkingHours } from "ts-time-utils/workingHours";
281
+ import { formatInTimeZone, isDST } from "ts-time-utils/timezone";
282
+ import { isWorkingTime, addWorkingDays } from "ts-time-utils/workingHours";
188
283
  import { today, lastNDays } from "ts-time-utils/rangePresets";
189
284
  import { Duration, createDuration } from "ts-time-utils/duration";
190
285
  import { serializeDate, parseJSONWithDates } from "ts-time-utils/serialize";
@@ -193,7 +288,6 @@ import {
193
288
  formatDateLocale,
194
289
  detectLocale,
195
290
  } from "ts-time-utils/locale";
196
- // New modules!
197
291
  import { createRecurrence, getNextOccurrence } from "ts-time-utils/recurrence";
198
292
  import { createCountdown, getRemainingTime } from "ts-time-utils/countdown";
199
293
  import { mergeDateRanges, findGaps } from "ts-time-utils/dateRange";
@@ -201,6 +295,41 @@ import {
201
295
  parseNaturalDate,
202
296
  extractDatesFromText,
203
297
  } from "ts-time-utils/naturalLanguage";
298
+ // NEW: Cron utilities
299
+ import {
300
+ matchesCron,
301
+ getNextCronDate,
302
+ isValidCron,
303
+ CRON_PRESETS,
304
+ } from "ts-time-utils/cron";
305
+ // NEW: Fiscal year utilities
306
+ import {
307
+ getFiscalYear,
308
+ getFiscalQuarter,
309
+ getFiscalPeriodInfo,
310
+ FISCAL_PRESETS,
311
+ } from "ts-time-utils/fiscal";
312
+ // NEW: Date comparison & sorting
313
+ import {
314
+ sortDates,
315
+ closestDate,
316
+ groupDatesByMonth,
317
+ snapDate,
318
+ } from "ts-time-utils/compare";
319
+ // NEW: Date iteration
320
+ import {
321
+ eachDay,
322
+ eachWeekday,
323
+ countWeekdays,
324
+ iterateDays,
325
+ } from "ts-time-utils/iterate";
326
+ // NEW: International holidays
327
+ import {
328
+ getHolidays,
329
+ isHoliday,
330
+ getNextHoliday,
331
+ getSupportedCountries,
332
+ } from "ts-time-utils/holidays";
204
333
  ```
205
334
 
206
335
  ## 📖 Examples
@@ -653,6 +782,240 @@ const week = thisWeek();
653
782
  const quarter = quarterRange();
654
783
  ```
655
784
 
785
+ ### Cron Utilities
786
+
787
+ ```ts
788
+ import {
789
+ parseCronExpression,
790
+ matchesCron,
791
+ getNextCronDate,
792
+ getNextCronDates,
793
+ describeCron,
794
+ isValidCron,
795
+ CRON_PRESETS,
796
+ } from "ts-time-utils/cron";
797
+
798
+ // Parse a cron expression
799
+ const parsed = parseCronExpression("0 9 * * 1-5"); // 9 AM weekdays
800
+ // { minute: [0], hour: [9], dayOfMonth: [1-31], month: [1-12], dayOfWeek: [1,2,3,4,5] }
801
+
802
+ // Check if a date matches a cron expression
803
+ matchesCron("0 9 * * *", new Date("2024-01-15T09:00:00")); // true (9 AM daily)
804
+ matchesCron("0 9 * * *", new Date("2024-01-15T10:00:00")); // false
805
+
806
+ // Get next scheduled date
807
+ getNextCronDate("0 9 * * *"); // Next 9 AM
808
+ getNextCronDate("0 0 1 * *"); // Next 1st of month at midnight
809
+
810
+ // Get multiple upcoming dates
811
+ getNextCronDates("0 9 * * 1-5", 5); // Next 5 weekday 9 AMs
812
+
813
+ // Human-readable descriptions
814
+ describeCron("0 9 * * *"); // "At 09:00"
815
+ describeCron("0 9 * * 1-5"); // "At 09:00 on Monday through Friday"
816
+ describeCron("0 0 1 * *"); // "At 00:00 on day 1 of every month"
817
+
818
+ // Validate cron expressions
819
+ isValidCron("0 9 * * *"); // true
820
+ isValidCron("invalid"); // false
821
+
822
+ // Common presets
823
+ CRON_PRESETS.EVERY_MINUTE; // "* * * * *"
824
+ CRON_PRESETS.HOURLY; // "0 * * * *"
825
+ CRON_PRESETS.DAILY; // "0 0 * * *"
826
+ CRON_PRESETS.WEEKLY; // "0 0 * * 0"
827
+ CRON_PRESETS.MONTHLY; // "0 0 1 * *"
828
+ CRON_PRESETS.WEEKDAYS; // "0 0 * * 1-5"
829
+ ```
830
+
831
+ ### Fiscal Year Utilities (NEW!)
832
+
833
+ ```ts
834
+ import {
835
+ getFiscalYear,
836
+ getFiscalQuarter,
837
+ getFiscalYearStart,
838
+ getFiscalYearEnd,
839
+ getFiscalPeriodInfo,
840
+ formatFiscalYear,
841
+ FISCAL_PRESETS,
842
+ } from "ts-time-utils/fiscal";
843
+
844
+ // Default calendar year (January start)
845
+ getFiscalYear(new Date("2024-06-15")); // 2024
846
+ getFiscalQuarter(new Date("2024-06-15")); // 2
847
+
848
+ // UK/India fiscal year (April start)
849
+ getFiscalYear(new Date("2024-03-15"), FISCAL_PRESETS.UK_INDIA); // 2023
850
+ getFiscalYear(new Date("2024-04-15"), FISCAL_PRESETS.UK_INDIA); // 2024
851
+
852
+ // Australian fiscal year (July start)
853
+ getFiscalYear(new Date("2024-06-30"), FISCAL_PRESETS.AUSTRALIA); // 2023
854
+ getFiscalYear(new Date("2024-07-01"), FISCAL_PRESETS.AUSTRALIA); // 2024
855
+
856
+ // US Federal fiscal year (October start)
857
+ getFiscalYear(new Date("2024-09-30"), FISCAL_PRESETS.US_FEDERAL); // 2023
858
+ getFiscalYear(new Date("2024-10-01"), FISCAL_PRESETS.US_FEDERAL); // 2024
859
+
860
+ // Get fiscal year boundaries
861
+ getFiscalYearStart(2024, FISCAL_PRESETS.UK_INDIA); // April 1, 2024
862
+ getFiscalYearEnd(2024, FISCAL_PRESETS.UK_INDIA); // March 31, 2025
863
+
864
+ // Format fiscal years
865
+ formatFiscalYear(2024); // "FY2024"
866
+ formatFiscalYear(2024, FISCAL_PRESETS.UK_INDIA, "long"); // "FY2024/25"
867
+
868
+ // Get comprehensive fiscal info
869
+ const info = getFiscalPeriodInfo(new Date("2024-06-15"));
870
+ // { fiscalYear: 2024, fiscalQuarter: 2, fiscalMonth: 6, progress: 45.2, ... }
871
+ ```
872
+
873
+ ### Date Comparison & Sorting (NEW!)
874
+
875
+ ```ts
876
+ import {
877
+ sortDates,
878
+ minDate,
879
+ maxDate,
880
+ closestDate,
881
+ uniqueDates,
882
+ groupDatesByMonth,
883
+ snapDate,
884
+ roundDate,
885
+ medianDate,
886
+ } from "ts-time-utils/compare";
887
+
888
+ const dates = [
889
+ new Date("2024-03-15"),
890
+ new Date("2024-01-10"),
891
+ new Date("2024-06-20"),
892
+ ];
893
+
894
+ // Sort dates
895
+ sortDates(dates); // [Jan 10, Mar 15, Jun 20]
896
+ sortDates(dates, "desc"); // [Jun 20, Mar 15, Jan 10]
897
+
898
+ // Find extremes
899
+ minDate(dates); // Jan 10, 2024
900
+ maxDate(dates); // Jun 20, 2024
901
+ medianDate(dates); // Mar 15, 2024
902
+
903
+ // Find closest to target
904
+ const target = new Date("2024-04-01");
905
+ closestDate(target, dates); // Mar 15, 2024
906
+
907
+ // Remove duplicates
908
+ uniqueDates([date1, date1Copy, date2]); // [date1, date2]
909
+ uniqueDates(dates, "day"); // Unique by day precision
910
+
911
+ // Group dates
912
+ groupDatesByMonth(dates);
913
+ // Map { "2024-01" => [Jan 10], "2024-03" => [Mar 15], "2024-06" => [Jun 20] }
914
+
915
+ // Snap to intervals (e.g., 15-minute blocks)
916
+ snapDate(new Date("2024-01-15T10:37:00"), 15); // 10:30:00
917
+ snapDate(new Date("2024-01-15T10:37:00"), 15, "ceil"); // 10:45:00
918
+
919
+ // Round to nearest unit
920
+ roundDate(new Date("2024-01-15T10:37:00"), "hour"); // 11:00:00
921
+ ```
922
+
923
+ ### Date Iteration (NEW!)
924
+
925
+ ```ts
926
+ import {
927
+ eachDay,
928
+ eachWeekday,
929
+ eachWeek,
930
+ eachMonth,
931
+ countWeekdays,
932
+ eachDayOfWeek,
933
+ iterateDays,
934
+ filterDays,
935
+ } from "ts-time-utils/iterate";
936
+
937
+ const start = new Date("2024-01-01");
938
+ const end = new Date("2024-01-31");
939
+
940
+ // Generate arrays of dates
941
+ eachDay(start, end); // [Jan 1, Jan 2, ..., Jan 31] (31 dates)
942
+ eachWeekday(start, end); // All Mon-Fri dates (23 dates)
943
+ eachWeek(start, end); // [Jan 7, Jan 14, Jan 21, Jan 28] (Sundays)
944
+ eachMonth(start, new Date("2024-06-30")); // [Feb 1, Mar 1, Apr 1, May 1, Jun 1]
945
+
946
+ // Count dates
947
+ countWeekdays(start, end); // 23
948
+
949
+ // Get specific weekdays
950
+ eachDayOfWeek(start, end, 1); // All Mondays in January
951
+
952
+ // Lazy iteration (memory efficient for large ranges)
953
+ for (const date of iterateDays(start, end)) {
954
+ console.log(date);
955
+ }
956
+
957
+ // Filter days by custom predicate
958
+ filterDays(start, end, (d) => d.getDate() === 15); // [Jan 15]
959
+
960
+ // Custom intervals
961
+ eachInterval(start, end, { days: 7 }); // Every 7 days
962
+ eachInterval(start, end, { hours: 6 }); // Every 6 hours
963
+ ```
964
+
965
+ ### International Holidays (NEW!)
966
+
967
+ ```ts
968
+ import {
969
+ getHolidays,
970
+ isHoliday,
971
+ getHolidayName,
972
+ getNextHoliday,
973
+ getUpcomingHolidays,
974
+ getSupportedCountries,
975
+ getUKHolidays,
976
+ getCanadaHolidays,
977
+ } from "ts-time-utils/holidays";
978
+
979
+ // Get all holidays for a country and year
980
+ const ukHolidays2024 = getHolidays(2024, "UK");
981
+ console.log(ukHolidays2024);
982
+ // [
983
+ // { name: "New Year's Day", date: Date, countryCode: "UK", type: "bank" },
984
+ // { name: "Good Friday", date: Date, countryCode: "UK", type: "bank" },
985
+ // { name: "Easter Monday", date: Date, countryCode: "UK", type: "bank" },
986
+ // ...
987
+ // ]
988
+
989
+ // Check if a date is a holiday
990
+ const christmas = new Date(2024, 11, 25);
991
+ isHoliday(christmas, "UK"); // true
992
+ isHoliday(new Date(2024, 5, 15), "UK"); // false
993
+
994
+ // Get holiday name for a date
995
+ getHolidayName(christmas, "UK"); // "Christmas Day"
996
+ getHolidayName(new Date(2024, 0, 1), "CA"); // "New Year's Day"
997
+
998
+ // Find next holiday from a date
999
+ const today = new Date();
1000
+ const nextHoliday = getNextHoliday(today, "CA");
1001
+ console.log(`Next holiday: ${nextHoliday?.name} on ${nextHoliday?.date}`);
1002
+
1003
+ // Get upcoming holidays in the next 90 days
1004
+ const upcoming = getUpcomingHolidays(today, 90, "AU");
1005
+ upcoming.forEach((h) => {
1006
+ console.log(`${h.name} - ${h.date.toDateString()}`);
1007
+ });
1008
+
1009
+ // Get supported countries
1010
+ getSupportedCountries(); // ["UK", "NL", "DE", "CA", "AU", "IT", "ES", "CN", "IN", "US"]
1011
+
1012
+ // Country-specific functions
1013
+ const nlHolidays = getHolidays(2024, "NL"); // Netherlands holidays (includes King's Day)
1014
+ const deHolidays = getHolidays(2024, "DE"); // German holidays (includes German Unity Day)
1015
+ const itHolidays = getHolidays(2024, "IT"); // Italian holidays (includes Republic Day)
1016
+ const esHolidays = getHolidays(2024, "ES"); // Spanish holidays (includes Constitution Day)
1017
+ ```
1018
+
656
1019
  ### Locale Utilities
657
1020
 
658
1021
  ```ts
@@ -848,10 +1211,193 @@ console.log(comparison.weekStartsOn);
848
1211
  ### Format Functions
849
1212
 
850
1213
  - `formatDuration(ms, options?)` - Format milliseconds to readable duration
1214
+ - `formatDurationCompact(ms)` - Format milliseconds as HH:MM:SS
851
1215
  - `timeAgo(date, options?)` - Get "time ago" string for past/future dates
852
1216
  - `formatTime(date, format?)` - Format time as 12h/24h/ISO
1217
+ - `formatDate(date, pattern?)` - Format date using patterns (YYYY-MM-DD, etc.)
1218
+ - `formatRelativeTime(date, locale?, options?)` - Format as relative time ("2 days ago")
1219
+ - `formatDateRange(start, end, options?)` - Format date ranges ("Jan 1-5, 2024")
1220
+ - `formatOrdinal(n)` - Format number as ordinal ("1st", "2nd", "3rd")
1221
+ - `formatDayOrdinal(date)` - Format day with ordinal ("1st", "15th")
1222
+ - `formatCalendarDate(date)` - Format as "Today", "Tomorrow", or day name
853
1223
  - `parseDuration(duration)` - Parse duration string to milliseconds
854
1224
 
1225
+ ### Parse Functions
1226
+
1227
+ - `parseISO8601Duration(duration)` - Parse ISO 8601 duration to object (P1Y2M3DT4H5M6S)
1228
+ - `parseISO8601DurationToMs(duration)` - Parse ISO 8601 duration to milliseconds
1229
+ - `parseTime(timeString)` - Parse time string ("14:30", "2:30 PM") to Date
1230
+ - `guessDateFormat(dateString)` - Guess the format of a date string
1231
+ - `parseAutoFormat(dateString)` - Auto-detect and parse date string
1232
+ - `parseRangeEndpoint(endpoint)` - Parse range endpoint (date string, Date, or number)
1233
+
1234
+ ### Calendar Functions
1235
+
1236
+ - `getCalendarDays(year, month)` - Get array of days for a calendar month
1237
+ - `getWeekNumber(date)` - Get ISO week number (1-53)
1238
+ - `getQuarter(date)` - Get quarter (1-4)
1239
+ - `getFirstDayOfMonth(date)` / `getLastDayOfMonth(date)` - Month boundaries
1240
+ - `getFirstDayOfWeek(date)` / `getLastDayOfWeek(date)` - Week boundaries
1241
+ - `getNthDayOfMonth(year, month, dayOfWeek, n)` - Get nth occurrence of weekday in month
1242
+ - `getStartOfWeek(date, startDay?)` - Get start of week (configurable start day)
1243
+ - `getEndOfWeek(date, startDay?)` - Get end of week (configurable start day)
1244
+ - `getWeeksInMonth(year, month)` - Count weeks in a month
1245
+
1246
+ #### US Federal Holidays
1247
+
1248
+ - `getNewYearsDay(year)` - Get New Year's Day
1249
+ - `getMLKDay(year)` - Get Martin Luther King Jr. Day (3rd Monday of January)
1250
+ - `getPresidentsDay(year)` - Get Presidents Day (3rd Monday of February)
1251
+ - `getMemorialDay(year)` - Get Memorial Day (last Monday of May)
1252
+ - `getIndependenceDay(year)` - Get Independence Day (July 4th)
1253
+ - `getLaborDay(year)` - Get Labor Day (1st Monday of September)
1254
+ - `getColumbusDay(year)` - Get Columbus Day (2nd Monday of October)
1255
+ - `getVeteransDay(year)` - Get Veterans Day (November 11th)
1256
+ - `getThanksgivingDay(year)` - Get Thanksgiving Day (4th Thursday of November)
1257
+ - `getChristmasDay(year)` - Get Christmas Day
1258
+ - `getGoodFriday(year)` - Get Good Friday
1259
+ - `getUSHolidays(year)` - Get all US federal holidays for a year
1260
+ - `isUSHoliday(date)` - Check if date is a US federal holiday
1261
+ - `getUSHolidayName(date)` - Get name of US holiday (or null)
1262
+
1263
+ ### Timezone Functions
1264
+
1265
+ - `getTimezoneOffset(timezone, date?)` - Get timezone offset in minutes
1266
+ - `convertTimezone(date, fromTz, toTz)` - Convert date between timezones
1267
+ - `getTimezoneNames()` - Get array of valid timezone names
1268
+ - `formatWithTimezone(date, timezone, format?)` - Format date in specific timezone
1269
+ - `isDST(date, timezone?)` - Check if DST is in effect
1270
+ - `getNextDSTTransition(date?, timezone?)` - Get next DST transition date
1271
+ - `findCommonWorkingHours(tz1, tz2, workStart?, workEnd?)` - Find overlapping work hours
1272
+ - `getTimezoneAbbreviation(date, timezone?)` - Get timezone abbreviation (EST, PST, etc.)
1273
+ - `convertBetweenZones(date, fromTz, toTz)` - Convert date between zones (returns new Date)
1274
+ - `getTimezoneDifferenceHours(tz1, tz2, date?)` - Get hour difference between timezones
1275
+ - `isSameTimezone(tz1, tz2, date?)` - Check if two timezones have same offset
1276
+
1277
+ ### Working Hours Functions
1278
+
1279
+ - `isWithinWorkingHours(date, config?)` - Check if time is within working hours
1280
+ - `getNextWorkingHour(date, config?)` - Get next available working hour
1281
+ - `addWorkingMinutes(date, minutes, config?)` - Add minutes within working hours
1282
+ - `workingMinutesBetween(start, end, config?)` - Count working minutes between dates
1283
+ - `addWorkingDays(date, days, config?)` - Add working days to date
1284
+ - `subtractWorkingDays(date, days, config?)` - Subtract working days from date
1285
+ - `getNextWorkingDay(date, config?)` - Get next working day
1286
+ - `getPreviousWorkingDay(date, config?)` - Get previous working day
1287
+ - `getWorkingDaysInMonth(year, month, config?)` - Count working days in month
1288
+ - `getWorkingDaysInMonthArray(year, month, config?)` - Get array of working days
1289
+ - `workingDaysBetween(start, end, config?)` - Count working days between dates
1290
+ - `isBreakTime(date, breakStart?, breakEnd?)` - Check if time is during break
1291
+ - `getWorkDayStart(date, config?)` - Get start time of work day
1292
+ - `getWorkDayEnd(date, config?)` - Get end time of work day
1293
+ - `getWorkingHoursPerDay(config?)` - Get working hours per day
1294
+
1295
+ ### Cron Functions
1296
+
1297
+ - `parseCronExpression(expression)` - Parse cron expression to object
1298
+ - `matchesCron(expression, date?)` - Check if date matches cron expression
1299
+ - `getNextCronDate(expression, after?)` - Get next date matching cron
1300
+ - `getNextCronDates(expression, count, after?)` - Get multiple future cron dates
1301
+ - `getPreviousCronDate(expression, before?)` - Get previous date matching cron
1302
+ - `isValidCron(expression)` - Validate cron expression syntax
1303
+ - `describeCron(expression)` - Get human-readable cron description
1304
+ - `CRON_PRESETS` - Common cron expressions (EVERY_MINUTE, HOURLY, DAILY, etc.)
1305
+
1306
+ ### Fiscal Year Functions
1307
+
1308
+ - `getFiscalYear(date, config?)` - Get fiscal year for a date
1309
+ - `getFiscalQuarter(date, config?)` - Get fiscal quarter (1-4)
1310
+ - `getFiscalMonth(date, config?)` - Get fiscal month (1-12 within fiscal year)
1311
+ - `getFiscalWeek(date, config?)` - Get fiscal week number
1312
+ - `getFiscalYearStart(year, config?)` - Get start date of fiscal year
1313
+ - `getFiscalYearEnd(year, config?)` - Get end date of fiscal year
1314
+ - `getFiscalQuarterStart(year, quarter, config?)` - Get start of fiscal quarter
1315
+ - `getFiscalQuarterEnd(year, quarter, config?)` - Get end of fiscal quarter
1316
+ - `isSameFiscalYear(date1, date2, config?)` - Check if dates are in same fiscal year
1317
+ - `isSameFiscalQuarter(date1, date2, config?)` - Check if dates are in same fiscal quarter
1318
+ - `getDaysElapsedInFiscalYear(date, config?)` - Days elapsed in fiscal year
1319
+ - `getDaysRemainingInFiscalYear(date, config?)` - Days remaining in fiscal year
1320
+ - `getFiscalYearProgress(date, config?)` - Percentage of fiscal year completed
1321
+ - `formatFiscalYear(year, config?, format?)` - Format as "FY2024" or "FY2023/24"
1322
+ - `formatFiscalQuarter(year, quarter, config?)` - Format as "Q1 FY2024"
1323
+ - `getFiscalPeriodInfo(date, config?)` - Get comprehensive fiscal period info
1324
+ - `FISCAL_PRESETS` - CALENDAR, UK_INDIA, AUSTRALIA, US_FEDERAL
1325
+
1326
+ ### Compare Functions
1327
+
1328
+ - `compareDates(a, b)` - Compare function for sorting dates
1329
+ - `compareDatesDesc(a, b)` - Compare function for reverse sorting
1330
+ - `sortDates(dates, direction?)` - Sort date array (asc/desc)
1331
+ - `minDate(dates)` - Find earliest date
1332
+ - `maxDate(dates)` - Find latest date
1333
+ - `dateExtent(dates)` - Get { min, max } from date array
1334
+ - `uniqueDates(dates, precision?)` - Remove duplicate dates
1335
+ - `closestDate(target, candidates)` - Find closest date to target
1336
+ - `closestFutureDate(target, candidates)` - Find closest future date
1337
+ - `closestPastDate(target, candidates)` - Find closest past date
1338
+ - `clampDate(date, min, max)` - Constrain date to range
1339
+ - `isDateInRange(date, min, max)` - Check if date is in range
1340
+ - `filterDatesInRange(dates, min, max)` - Filter dates in range
1341
+ - `groupDates(dates, keyFn)` - Group dates by custom key
1342
+ - `groupDatesByYear(dates)` - Group by year
1343
+ - `groupDatesByMonth(dates)` - Group by month (YYYY-MM)
1344
+ - `groupDatesByDay(dates)` - Group by day (YYYY-MM-DD)
1345
+ - `groupDatesByDayOfWeek(dates)` - Group by day of week (0-6)
1346
+ - `medianDate(dates)` - Calculate median date
1347
+ - `averageDate(dates)` - Calculate average/mean date
1348
+ - `roundDate(date, unit)` - Round to nearest minute/hour/day
1349
+ - `snapDate(date, intervalMinutes, mode?)` - Snap to interval grid
1350
+ - `isChronological(dates, strict?)` - Check if dates are in order
1351
+ - `dateSpan(dates)` - Get duration between min and max
1352
+ - `partitionDates(dates, predicate)` - Split into [matching, non-matching]
1353
+ - `nthDate(dates, n)` - Get nth date (supports negative indices)
1354
+
1355
+ ### Iterate Functions
1356
+
1357
+ - `eachDay(start, end)` - Array of each day in range
1358
+ - `eachWeekday(start, end)` - Array of weekdays (Mon-Fri)
1359
+ - `eachWeekend(start, end)` - Array of weekend days (Sat-Sun)
1360
+ - `eachWeek(start, end, weekStartsOn?)` - Array of week starts
1361
+ - `eachMonth(start, end)` - Array of month starts
1362
+ - `eachMonthEnd(start, end)` - Array of month ends
1363
+ - `eachQuarter(start, end)` - Array of quarter starts
1364
+ - `eachYear(start, end)` - Array of year starts
1365
+ - `eachHour(start, end, step?)` - Array of hourly intervals
1366
+ - `eachMinute(start, end, step?)` - Array of minute intervals
1367
+ - `eachDayOfWeek(start, end, dayOfWeek)` - Array of specific weekday
1368
+ - `eachNthDayOfMonth(start, end, day)` - Array of nth day of each month
1369
+ - `eachInterval(start, end, interval)` - Array at custom intervals
1370
+ - `countDays(start, end)` - Count days in range
1371
+ - `countWeekdays(start, end)` - Count weekdays in range
1372
+ - `countWeekendDays(start, end)` - Count weekend days
1373
+ - `countWeeks(start, end)` - Count weeks in range
1374
+ - `countMonths(start, end)` - Count months in range
1375
+ - `iterateDates(start, end, step?)` - Lazy date generator
1376
+ - `iterateDays(start, end)` - Lazy day iterator
1377
+ - `iterateWeekdays(start, end)` - Lazy weekday iterator
1378
+ - `iterateMonths(start, end)` - Lazy month iterator
1379
+ - `filterDays(start, end, filter)` - Filter days by predicate
1380
+
1381
+ ### Holidays Functions
1382
+
1383
+ - `getHolidays(year, countryCode)` - Get all holidays for a country and year
1384
+ - `isHoliday(date, countryCode)` - Check if date is a holiday
1385
+ - `getHolidayName(date, countryCode)` - Get holiday name for date (or null)
1386
+ - `getNextHoliday(date, countryCode)` - Find next holiday after date
1387
+ - `getUpcomingHolidays(date, days, countryCode)` - Get holidays in next N days
1388
+ - `getSupportedCountries()` - Get array of supported country codes
1389
+ - `getUKHolidays(year)` - Get UK bank holidays (New Year, Easter, Spring/Summer Bank Holiday, Christmas)
1390
+ - `getNetherlandsHolidays(year)` - Get Netherlands holidays (King's Day, Liberation Day, Easter, Ascension, Whit)
1391
+ - `getGermanyHolidays(year)` - Get German holidays (Unity Day, Labour Day, Easter, Ascension, Whit, Christmas)
1392
+ - `getCanadaHolidays(year)` - Get Canadian federal holidays (Victoria Day, Canada Day, Labour Day, Thanksgiving)
1393
+ - `getAustraliaHolidays(year)` - Get Australian holidays (Australia Day, Anzac Day, Queen's Birthday)
1394
+ - `getItalyHolidays(year)` - Get Italian holidays (Epiphany, Liberation Day, Republic Day, Assumption)
1395
+ - `getSpainHolidays(year)` - Get Spanish holidays (National Day, Constitution Day, Immaculate Conception)
1396
+ - `getChinaHolidays(year)` - Get Chinese holidays (Spring Festival, National Day, New Year) - simplified
1397
+ - `getIndiaHolidays(year)` - Get Indian holidays (Republic Day, Independence Day, Gandhi Jayanti) - simplified
1398
+ - **Types**: `CountryCode` = "UK" | "NL" | "DE" | "CA" | "AU" | "IT" | "ES" | "CN" | "IN" | "US"
1399
+ - **Holiday Interface**: `{ name: string, date: Date, countryCode: CountryCode, type: string }`
1400
+
855
1401
  ### Calculate Functions
856
1402
 
857
1403
  - `differenceInUnits(date1, date2, unit?, precise?)` - Calculate difference between dates
@@ -869,7 +1415,16 @@ console.log(comparison.weekStartsOn);
869
1415
  - `isPast(date)` / `isFuture(date)` - Check if date is past/future
870
1416
  - `isToday(date)` / `isYesterday(date)` / `isTomorrow(date)` - Date comparisons
871
1417
  - `isSameDay(date1, date2)` - Check if dates are same day
1418
+ - `isSameWeek(date1, date2)` - Check if dates are in same week
1419
+ - `isSameMonth(date1, date2)` - Check if dates are in same month
1420
+ - `isSameYear(date1, date2)` - Check if dates are in same year
1421
+ - `isThisWeek(date)` - Check if date is in current week
1422
+ - `isThisMonth(date)` - Check if date is in current month
1423
+ - `isThisYear(date)` - Check if date is in current year
872
1424
  - `isWeekend(date)` / `isWeekday(date)` - Check day type
1425
+ - `isBusinessDay(date)` - Check if date is a business day (weekday, not a US holiday)
1426
+ - `isInLastNDays(date, n)` - Check if date is within last N days
1427
+ - `isInNextNDays(date, n)` - Check if date is within next N days
873
1428
  - `isValidTimeString(time)` - Validate HH:MM time format
874
1429
  - `isValidISOString(dateString)` - Validate ISO 8601 date string
875
1430