ts-time-utils 2.0.0 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,1378 +1,474 @@
1
1
  # ts-time-utils
2
2
 
3
- A lightweight TypeScript utility library for time formatting, calculations, and validation with full tree-shaking support.
4
-
5
- ## 🚀 Features
6
-
7
- - **📦 Lightweight** - Import only what you need with tree-shaking support
8
- - **⚡ Fast** - Zero dependencies, pure JavaScript functions
9
- - **🔧 TypeScript** - Full type safety and IntelliSense support
10
- - **🌳 Tree-shakable** - Import individual functions to minimize bundle size
11
- - **📚 Comprehensive** - 25 utility categories with 287+ functions
12
-
13
- ### 🔄 Recurrence utilities **(NEW!)**
14
-
15
- - RRULE-inspired recurring event patterns
16
- - Daily, weekly, monthly, and yearly recurrences
17
- - Complex recurrence rules with byWeekday, byMonthDay, byMonth
18
- - Get next occurrence, all occurrences, or occurrences within range
19
- - Human-readable recurrence descriptions
20
- - Full support for count and until limits
21
-
22
- ### ⏲️ Countdown & Timer utilities **(NEW!)**
23
-
24
- - Real-time countdown timers with callbacks
25
- - Get remaining time broken down by units
26
- - Format countdowns as human-readable strings
27
- - Check if dates are expired
28
- - Calculate progress percentage between dates
29
- - Deadline tracking with helper methods
30
-
31
- ### 📊 Date Range utilities **(NEW!)**
32
-
33
- - Advanced range operations (overlap, intersection, union)
34
- - Merge overlapping ranges
35
- - Find gaps between ranges
36
- - Split ranges into chunks
37
- - Expand and shrink ranges
38
- - Subtract ranges from each other
39
- - Check containment and sort ranges
40
-
41
- ### 💬 Natural Language Parsing **(NEW!)**
42
-
43
- - Parse human-friendly date strings ("tomorrow", "next Friday", "in 2 weeks")
44
- - Extract dates from text automatically
45
- - Context-aware date suggestions ("end of month", "EOY")
46
- - Support for relative phrases and absolute dates
47
- - Confidence scoring for extracted dates
48
-
49
- ### ⏱️ Duration utilities
50
-
51
- - Immutable Duration class with arithmetic operations
52
- - Create durations from various units and string formats
53
- - Add, subtract, multiply, divide durations
54
- - Compare durations and check relationships
55
- - Format to human-readable strings
56
- - Utility functions for arrays of durations
57
-
58
- ### 💾 Serialization utilities
59
-
60
- - Safe JSON date serialization and deserialization
61
- - Multiple format support (ISO, epoch, object, custom)
62
- - Automatic date reviver and replacer functions
63
- - Timezone-aware serialization options
64
- - Cross-platform date interchange utilities
65
- - Validation for ISO strings and epoch timestamps
66
-
67
- ### 🎨 Format utilities
68
-
69
- - Format milliseconds to human-readable durations
70
- - Get human-friendly "time ago" strings
71
- - Parse duration strings back to milliseconds
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")
76
-
77
- ### 🧮 Calculation utilities
78
-
79
- - Calculate difference between dates in any unit
80
- - Add/subtract time from dates
81
- - Get start/end of time periods
82
- - Business days calculations
83
- - Check if date is between two dates
84
-
85
- ### ✅ Validation utilities
86
-
87
- - Validate dates and time strings
88
- - Check for leap years, weekends, past/future dates
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
93
-
94
- ### 🎂 Age utilities
95
-
96
- - Calculate precise age with years, months, and days
97
- - Get life stage classifications (infant, child, adult, etc.)
98
- - Birthday calculations and next birthday finder
99
- - Check if today is someone's birthday
100
-
101
- ### 📅 Calendar utilities
102
-
103
- - ISO week numbers and week-based calculations
104
- - Quarter operations and fiscal year support
105
- - Holiday calculations (Easter, US federal holidays)
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
111
-
112
- ### 🔍 Parse utilities
113
-
114
- - Advanced date parsing from multiple formats
115
- - Relative date parsing ("tomorrow", "next week")
116
- - Custom format parsing with flexible patterns
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")
122
-
123
- ### ⚡ Performance utilities
124
-
125
- - Async utilities (sleep, timeout, retry)
126
- - Performance measurement and benchmarking
127
- - Stopwatch for timing operations
128
- - Function utilities (debounce, throttle, memoize)
129
-
130
- ### 📏 Interval utilities
131
-
132
- - Create and validate intervals
133
- - Overlap, intersection, merge, subtraction
134
- - Split by day and total coverage
135
- - Normalize and compute durations
136
-
137
- ### 🌐 Timezone utilities
138
-
139
- - Validate IANA timezones
140
- - Get offsets and compare zones
141
- - Format in specific timezone
142
- - Convert absolute moment to zone components
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
148
-
149
- ### 🕘 Working hours utilities
150
-
151
- - Define working day patterns and breaks
152
- - Check working day/time
153
- - Compute working time between dates
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
160
-
161
- ### 🎯 Range preset utilities
162
-
163
- - Today / yesterday / tomorrow
164
- - Last/next N days windows
165
- - This/last/next week, month, quarter, year
166
- - Rolling windows and quarter helpers
167
-
168
- ### 🌍 Locale utilities
169
-
170
- - Multi-language relative time formatting
171
- - Locale-specific date and time formatting
172
- - Support for 40+ locales with built-in configurations
173
- - Auto-detection of system/browser locale
174
- - Custom locale registration
175
- - Internationalization (i18n) support
176
- - **Locale conversions** - Convert between different locales and detect locale from text
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 date to a target (past, future, or any)
202
- - Clamp dates to ranges
203
- - Remove duplicate dates with precision control
204
- - Group dates by year, month, day, or day of week
205
- - Round and snap dates to intervals (e.g., nearest 15 minutes)
206
- - Check if dates are in chronological order
207
- - Partition dates by predicate
208
-
209
- ### 🔁 Date Iteration utilities **(NEW!)**
210
-
211
- - Generate arrays of dates: `eachDay()`, `eachWeekday()`, `eachWeekend()`
212
- - Iterate by period: `eachWeek()`, `eachMonth()`, `eachQuarter()`, `eachYear()`
213
- - Time iteration: `eachHour()`, `eachMinute()`, `eachInterval()`
214
- - Get specific days: `eachDayOfWeek()`, `eachNthDayOfMonth()`, `eachMonthEnd()`
215
- - Count functions: `countDays()`, `countWeekdays()`, `countWeekendDays()`
216
- - Lazy iterators for memory efficiency: `iterateDays()`, `iterateWeekdays()`, `iterateMonths()`
217
- - Custom filtering with `filterDays()`
218
-
219
- ### 🧱 Constants
220
-
221
- - Milliseconds & seconds per unit
222
- - Time unit and formatting option types
223
-
224
- ## 📦 Installation
3
+ A comprehensive TypeScript utility library for time, dates, durations, and calendar operations. Zero dependencies, full tree-shaking support, 320+ functions across 26 categories.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/ts-time-utils.svg)](https://www.npmjs.com/package/ts-time-utils)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ **[Live Playground & Docs](https://ts-time-utils.h8frad.work)** | [GitHub](https://github.com/hatefrad/ts-time-utils)
9
+
10
+ ## Features
11
+
12
+ - **Lightweight** — Import only what you need with tree-shaking support
13
+ - **Zero dependencies** — Pure TypeScript, no external packages
14
+ - **Type-safe** — Full TypeScript support with IntelliSense
15
+ - **Comprehensive** — 320+ functions across 26 utility categories
16
+ - **Fluent API** — Chain operations with the `chain()` API
17
+ - **Extensible** — Plugin system for custom functionality
18
+
19
+ ## Installation
225
20
 
226
21
  ```bash
227
22
  npm install ts-time-utils
228
23
  ```
229
24
 
230
- ## 🔧 Usage
231
-
232
- ### Import everything (not recommended for production)
25
+ ## Quick Start
233
26
 
234
27
  ```ts
235
- import { formatDuration, timeAgo, isValidDate } from "ts-time-utils";
236
- ```
28
+ import { formatDuration, timeAgo, Duration } from 'ts-time-utils';
237
29
 
238
- ### Import by category (better for tree-shaking)
30
+ // Format milliseconds to readable duration
31
+ formatDuration(3661000); // "1 hour, 1 minute, 1 second"
239
32
 
240
- ```ts
241
- import { formatDuration, timeAgo, formatDate } from "ts-time-utils/format";
242
- import { differenceInUnits, addTime } from "ts-time-utils/calculate";
243
- import { isValidDate, isLeapYear, isSameWeek } from "ts-time-utils/validate";
244
- import { calculateAge, getNextBirthday } from "ts-time-utils/age";
245
- import {
246
- getWeekNumber,
247
- getQuarter,
248
- getUSHolidays,
249
- } from "ts-time-utils/calendar";
250
- import { parseDate, parseRelativeDate, parseTime } from "ts-time-utils/parse";
251
- import { sleep, benchmark, Stopwatch } from "ts-time-utils/performance";
252
- import { createInterval, mergeIntervals } from "ts-time-utils/interval";
253
- import { formatInTimeZone, isDST } from "ts-time-utils/timezone";
254
- import { isWorkingTime, addWorkingDays } from "ts-time-utils/workingHours";
255
- import { today, lastNDays } from "ts-time-utils/rangePresets";
256
- import { Duration, createDuration } from "ts-time-utils/duration";
257
- import { serializeDate, parseJSONWithDates } from "ts-time-utils/serialize";
258
- import {
259
- formatRelativeTime,
260
- formatDateLocale,
261
- detectLocale,
262
- } from "ts-time-utils/locale";
263
- import { createRecurrence, getNextOccurrence } from "ts-time-utils/recurrence";
264
- import { createCountdown, getRemainingTime } from "ts-time-utils/countdown";
265
- import { mergeDateRanges, findGaps } from "ts-time-utils/dateRange";
266
- import {
267
- parseNaturalDate,
268
- extractDatesFromText,
269
- } from "ts-time-utils/naturalLanguage";
270
- // NEW: Cron utilities
271
- import {
272
- matchesCron,
273
- getNextCronDate,
274
- isValidCron,
275
- CRON_PRESETS,
276
- } from "ts-time-utils/cron";
277
- // NEW: Fiscal year utilities
278
- import {
279
- getFiscalYear,
280
- getFiscalQuarter,
281
- getFiscalPeriodInfo,
282
- FISCAL_PRESETS,
283
- } from "ts-time-utils/fiscal";
284
- // NEW: Date comparison & sorting
285
- import {
286
- sortDates,
287
- closestDate,
288
- groupDatesByMonth,
289
- snapDate,
290
- } from "ts-time-utils/compare";
291
- // NEW: Date iteration
292
- import {
293
- eachDay,
294
- eachWeekday,
295
- countWeekdays,
296
- iterateDays,
297
- } from "ts-time-utils/iterate";
298
- ```
33
+ // Get "time ago" strings
34
+ timeAgo(new Date(Date.now() - 3600000)); // "1 hour ago"
299
35
 
300
- ## 📖 Examples
36
+ // Duration arithmetic
37
+ const meeting = Duration.fromMinutes(45);
38
+ const buffer = Duration.fromMinutes(15);
39
+ meeting.add(buffer).toString(); // "1h"
40
+ ```
301
41
 
302
- ### Recurrence Utilities (NEW!)
42
+ ### Tree-shaking (recommended)
303
43
 
304
44
  ```ts
305
- import { createRecurrence, recurrenceToString } from "ts-time-utils/recurrence";
306
-
307
- // Daily recurrence
308
- const daily = createRecurrence({
309
- frequency: "daily",
310
- interval: 2,
311
- startDate: new Date("2024-01-01"),
312
- count: 10,
313
- });
45
+ import { formatDuration } from 'ts-time-utils/format';
46
+ import { differenceInUnits } from 'ts-time-utils/calculate';
47
+ import { isValidDate } from 'ts-time-utils/validate';
48
+ ```
314
49
 
315
- const next = daily.getNextOccurrence(new Date());
316
- const allOccurrences = daily.getAllOccurrences();
50
+ ---
317
51
 
318
- // Weekly on specific days
319
- const weekly = createRecurrence({
320
- frequency: "weekly",
321
- interval: 1,
322
- startDate: new Date("2024-01-01"),
323
- byWeekday: [1, 3, 5], // Monday, Wednesday, Friday
324
- });
52
+ ## Utility Categories
325
53
 
326
- const description = recurrenceToString(weekly.rule);
327
- // "Every week on Monday, Wednesday, Friday"
54
+ ### Format
328
55
 
329
- // Monthly on the 15th
330
- const monthly = createRecurrence({
331
- frequency: "monthly",
332
- interval: 1,
333
- startDate: new Date("2024-01-01"),
334
- byMonthDay: [15],
335
- until: new Date("2024-12-31"),
336
- });
56
+ Format durations, time ago strings, and custom date formats.
337
57
 
338
- const occurrencesInRange = monthly.getOccurrencesBetween(
339
- new Date("2024-03-01"),
340
- new Date("2024-06-30")
341
- );
58
+ ```ts
59
+ import { formatDuration, timeAgo, parseDuration } from 'ts-time-utils/format';
60
+
61
+ formatDuration(65000); // "1 minute, 5 seconds"
62
+ formatDuration(65000, { short: true }); // "1m 5s"
63
+ timeAgo(new Date(Date.now() - 60000)); // "1 minute ago"
64
+ parseDuration('1h 30m'); // 5400000 (ms)
342
65
  ```
343
66
 
344
- ### Countdown & Timer Utilities (NEW!)
67
+ ### Calculate
68
+
69
+ Date arithmetic, differences, and business day calculations.
345
70
 
346
71
  ```ts
347
- import {
348
- createCountdown,
349
- getRemainingTime,
350
- formatCountdown,
351
- } from "ts-time-utils/countdown";
352
-
353
- // Create a countdown timer
354
- const countdown = createCountdown(new Date("2024-12-31T23:59:59"), {
355
- onTick: (remaining) => {
356
- console.log(`${remaining.days}d ${remaining.hours}h ${remaining.minutes}m`);
357
- },
358
- onComplete: () => {
359
- console.log("Happy New Year!");
360
- },
361
- interval: 1000, // Update every second
362
- });
72
+ import { differenceInUnits, addTime, startOf, endOf } from 'ts-time-utils/calculate';
363
73
 
364
- countdown.start();
365
- // Later...
366
- countdown.stop();
74
+ differenceInUnits(date1, date2, 'days'); // 10
75
+ addTime(new Date(), 5, 'hours'); // 5 hours from now
76
+ startOf(new Date(), 'day'); // 00:00:00 today
77
+ endOf(new Date(), 'month'); // Last moment of month
78
+ ```
367
79
 
368
- // Get remaining time
369
- const remaining = getRemainingTime(new Date("2024-12-31"));
370
- console.log(`${remaining.days} days, ${remaining.hours} hours remaining`);
80
+ ### Validate
371
81
 
372
- // Format countdown
373
- const formatted = formatCountdown(new Date("2024-12-31"), {
374
- units: ["days", "hours", "minutes"],
375
- short: true,
376
- });
377
- // "45d 12h 30m"
82
+ Date validation, checks, and comparisons.
378
83
 
379
- // Progress tracking
380
- import { getProgressPercentage } from "ts-time-utils/countdown";
84
+ ```ts
85
+ import { isValidDate, isLeapYear, isWeekend, isSameDay } from 'ts-time-utils/validate';
381
86
 
382
- const progress = getProgressPercentage(
383
- new Date("2024-01-01"),
384
- new Date("2024-12-31"),
385
- new Date("2024-07-01")
386
- );
387
- console.log(`${progress}% complete`); // ~50%
87
+ isValidDate(new Date('2025-13-01')); // false
88
+ isLeapYear(2024); // true
89
+ isWeekend(new Date('2025-09-13')); // true (Saturday)
90
+ isSameDay(date1, date2); // boolean
388
91
  ```
389
92
 
390
- ### Date Range Utilities (NEW!)
93
+ ### Duration
94
+
95
+ Immutable Duration class with arithmetic operations.
391
96
 
392
97
  ```ts
393
- import {
394
- mergeDateRanges,
395
- findGaps,
396
- dateRangeOverlap,
397
- splitRange,
398
- } from "ts-time-utils/dateRange";
399
-
400
- // Merge overlapping ranges
401
- const ranges = [
402
- { start: new Date("2024-01-01"), end: new Date("2024-01-10") },
403
- { start: new Date("2024-01-05"), end: new Date("2024-01-15") },
404
- { start: new Date("2024-01-20"), end: new Date("2024-01-25") },
405
- ];
98
+ import { Duration } from 'ts-time-utils/duration';
406
99
 
407
- const merged = mergeDateRanges(ranges);
408
- // [
409
- // { start: Date('2024-01-01'), end: Date('2024-01-15') },
410
- // { start: Date('2024-01-20'), end: Date('2024-01-25') }
411
- // ]
100
+ const d1 = Duration.fromHours(2.5);
101
+ const d2 = Duration.fromString('1h 30m 45s');
102
+ const d3 = Duration.between(startDate, endDate);
412
103
 
413
- // Find gaps between busy times
414
- const busyTimes = [
415
- { start: new Date("2024-01-01T09:00"), end: new Date("2024-01-01T11:00") },
416
- { start: new Date("2024-01-01T14:00"), end: new Date("2024-01-01T16:00") },
417
- ];
418
-
419
- const gaps = findGaps(busyTimes, {
420
- start: new Date("2024-01-01T08:00"),
421
- end: new Date("2024-01-01T18:00"),
422
- });
423
- // Returns available time slots
424
-
425
- // Split into chunks
426
- const range = {
427
- start: new Date("2024-01-01"),
428
- end: new Date("2024-01-31"),
429
- };
430
-
431
- const weeks = splitRange(range, 1, "week");
432
- // Splits January into weekly chunks
433
-
434
- // Check overlap
435
- const overlap = dateRangeOverlap(
436
- { start: new Date("2024-01-01"), end: new Date("2024-01-15") },
437
- { start: new Date("2024-01-10"), end: new Date("2024-01-20") }
438
- ); // true
104
+ d1.add(d2).toString(); // "4h 0m 45s"
105
+ d1.greaterThan(d2); // true
106
+ d1.multiply(2).hours; // 5
439
107
  ```
440
108
 
441
- ### Natural Language Parsing (NEW!)
109
+ ### Chain API
442
110
 
443
- ```ts
444
- import {
445
- parseNaturalDate,
446
- extractDatesFromText,
447
- suggestDateFromContext,
448
- } from "ts-time-utils/naturalLanguage";
449
-
450
- // Parse natural language dates
451
- parseNaturalDate("tomorrow at 3pm");
452
- // Returns Date for tomorrow at 15:00
453
-
454
- parseNaturalDate("next Friday");
455
- // Returns Date for next Friday
456
-
457
- parseNaturalDate("in 2 weeks");
458
- // Returns Date 2 weeks from now
459
-
460
- parseNaturalDate("3 days ago");
461
- // Returns Date 3 days ago
462
-
463
- // Extract dates from text
464
- const text = "Meeting tomorrow at 3pm and lunch next Friday at noon";
465
- const dates = extractDatesFromText(text);
466
- // [
467
- // { date: Date(...), text: 'tomorrow at 3pm', index: 8, confidence: 0.9 },
468
- // { date: Date(...), text: 'next Friday at noon', index: 35, confidence: 0.85 }
469
- // ]
470
-
471
- // Context-aware suggestions
472
- const suggestions = suggestDateFromContext("deadline is end of month");
473
- // [{ date: Date(last day of current month), text: 'end of month', confidence: 0.85 }]
474
-
475
- // Supported phrases:
476
- // - "tomorrow", "yesterday", "today"
477
- // - "next Monday", "last Friday"
478
- // - "in 2 hours", "5 days ago"
479
- // - "end of month/week/year" (or EOM/EOW/EOY)
480
- // - "beginning of month/year"
481
- ```
482
-
483
- ### Duration Utilities
111
+ Fluent chainable API for date operations.
484
112
 
485
113
  ```ts
486
- import {
487
- Duration,
488
- createDuration,
489
- formatDurationString,
490
- } from "ts-time-utils/duration";
491
-
492
- // Create durations
493
- const duration1 = Duration.fromHours(2.5); // 2.5 hours
494
- const duration2 = new Duration({ hours: 1, minutes: 30 }); // 1.5 hours
495
- const duration3 = Duration.fromString("1h 30m 45s"); // Parse from string
496
- const duration4 = Duration.between(startDate, endDate); // From date range
497
-
498
- // Arithmetic operations
499
- const sum = duration1.add(duration2); // 4 hours
500
- const diff = duration1.subtract(duration2); // 1 hour
501
- const doubled = duration1.multiply(2); // 5 hours
502
- const half = duration1.divide(2); // 1.25 hours
503
-
504
- // Comparisons
505
- duration1.equals(duration2); // false
506
- duration1.greaterThan(duration2); // true
507
- duration1.compareTo(duration2); // 1
508
-
509
- // Conversions and formatting
510
- duration1.hours; // 2.5
511
- duration1.minutes; // 150
512
- duration1.toString(); // "2h 30m"
513
- formatDurationString(duration1, { long: true }); // "2 hours, 30 minutes"
514
-
515
- // Utility functions with arrays
516
- const durations = [duration1, duration2, duration3];
517
- const max = maxDuration(...durations);
518
- const total = sumDurations(...durations);
519
- const average = averageDuration(...durations);
114
+ import { chain } from 'ts-time-utils/chain';
115
+
116
+ chain(new Date())
117
+ .startOf('day')
118
+ .add(9, 'hours')
119
+ .add(30, 'minutes')
120
+ .toDate(); // Today at 9:30am
121
+
122
+ chain(new Date())
123
+ .add(1, 'week')
124
+ .startOf('week')
125
+ .format('YYYY-MM-DD'); // Next week Monday
520
126
  ```
521
127
 
522
- ### Serialization Utilities
128
+ ### Timezone
129
+
130
+ Timezone conversions, DST handling, and zone comparisons.
523
131
 
524
132
  ```ts
525
- import {
526
- serializeDate,
527
- deserializeDate,
528
- parseJSONWithDates,
529
- stringifyWithDates,
530
- toEpochTimestamp,
531
- fromEpochTimestamp,
532
- toDateObject,
533
- fromDateObject,
534
- } from "ts-time-utils/serialize";
535
-
536
- // Serialize dates in different formats
537
- const date = new Date("2025-09-14T12:30:45.123Z");
538
-
539
- const isoString = serializeDate(date, { format: "iso" }); // "2025-09-14T12:30:45.123Z"
540
- const epochMs = serializeDate(date, { format: "epoch" }); // 1757853045123
541
- const dateObj = serializeDate(date, { format: "object" }); // {year: 2025, month: 9, ...}
542
- const custom = serializeDate(date, {
543
- format: "custom",
544
- customFormat: "YYYY-MM-DD HH:mm:ss",
545
- }); // "2025-09-14 12:30:45"
546
-
547
- // Deserialize from various formats
548
- const fromISO = deserializeDate("2025-09-14T12:30:45.123Z");
549
- const fromEpoch = deserializeDate(1757853045123);
550
- const fromObj = deserializeDate({
551
- year: 2025,
552
- month: 9,
553
- day: 14,
554
- hour: 12,
555
- minute: 30,
556
- second: 45,
557
- millisecond: 123,
558
- });
133
+ import { formatInTimeZone, isDST, convertTimezone } from 'ts-time-utils/timezone';
559
134
 
560
- // Safe JSON handling with automatic date conversion
561
- const data = {
562
- name: "User",
563
- createdAt: new Date(),
564
- updatedAt: new Date(),
565
- metadata: "other data",
566
- };
567
-
568
- // Stringify with automatic date serialization
569
- const jsonString = stringifyWithDates(data, ["createdAt", "updatedAt"], {
570
- format: "epoch",
571
- });
572
- // {"name":"User","createdAt":1757853045123,"updatedAt":1757853045123,"metadata":"other data"}
135
+ formatInTimeZone(date, 'America/New_York');
136
+ isDST(new Date('2025-07-14'), 'America/New_York'); // true
137
+ convertTimezone(date, 'UTC', 'Asia/Tokyo');
138
+ ```
573
139
 
574
- // Parse with automatic date restoration
575
- const parsed = parseJSONWithDates(jsonString, ["createdAt", "updatedAt"]);
576
- // parsed.createdAt and parsed.updatedAt are Date objects
140
+ ### Calendar
577
141
 
578
- // Epoch timestamp utilities
579
- const timestamp = toEpochTimestamp(date, "seconds"); // 1757853045
580
- const restoredDate = fromEpochTimestamp(timestamp, "seconds");
142
+ ISO weeks, quarters, holidays, and calendar grids.
581
143
 
582
- // Date object utilities (UTC-based)
583
- const dateObject = toDateObject(date, true); // includes timezone
584
- const reconstructed = fromDateObject(dateObject);
144
+ ```ts
145
+ import { getWeekNumber, getQuarter, getEaster, getUSHolidays } from 'ts-time-utils/calendar';
146
+
147
+ getWeekNumber(new Date('2025-09-14')); // 37
148
+ getQuarter(new Date('2025-07-15')); // 3
149
+ getEaster(2025); // Easter Sunday 2025
150
+ getUSHolidays(2025); // Array of US federal holidays
585
151
  ```
586
152
 
587
- ### Format Utilities
153
+ ### Date Range
588
154
 
589
- ```ts
590
- import { formatDuration, timeAgo, parseDuration } from "ts-time-utils/format";
155
+ Date range operations: overlap, gaps, merge, split.
591
156
 
592
- // Format durations
593
- formatDuration(65000); // "1 minute, 5 seconds"
594
- formatDuration(65000, { short: true }); // "1m 5s"
595
- formatDuration(90061000, { maxUnits: 2 }); // "1 day, 1 hour"
157
+ ```ts
158
+ import { mergeDateRanges, findGaps, dateRangeOverlap } from 'ts-time-utils/dateRange';
596
159
 
597
- // Time ago strings
598
- timeAgo(new Date(Date.now() - 60000)); // "1 minute ago"
599
- timeAgo(new Date(Date.now() + 60000)); // "in 1 minute"
160
+ const ranges = [
161
+ { start: new Date('2024-01-01'), end: new Date('2024-01-10') },
162
+ { start: new Date('2024-01-05'), end: new Date('2024-01-15') },
163
+ ];
600
164
 
601
- // Parse duration strings
602
- parseDuration("1h 30m"); // 5400000 (milliseconds)
603
- parseDuration("2 days 3 hours"); // 183600000
165
+ mergeDateRanges(ranges); // Merged into single range
166
+ findGaps(busyTimes, workday); // Available time slots
167
+ dateRangeOverlap(range1, range2); // true/false
604
168
  ```
605
169
 
606
- ### Calculate Utilities
170
+ ### Recurrence
171
+
172
+ RRULE-inspired recurring event patterns.
607
173
 
608
174
  ```ts
609
- import { differenceInUnits, addTime, startOf } from "ts-time-utils/calculate";
175
+ import { createRecurrence, recurrenceToString } from 'ts-time-utils/recurrence';
610
176
 
611
- // Date calculations
612
- differenceInUnits(new Date("2025-09-01"), new Date("2025-09-11"), "days"); // 10
177
+ const weekly = createRecurrence({
178
+ frequency: 'weekly',
179
+ interval: 1,
180
+ startDate: new Date('2025-01-01'),
181
+ byWeekday: [1, 3, 5], // Mon, Wed, Fri
182
+ });
613
183
 
614
- addTime(new Date(), 5, "hours"); // 5 hours from now
615
- startOf(new Date(), "day"); // Start of today (00:00:00)
184
+ weekly.getNextOccurrence(new Date());
185
+ weekly.getAllOccurrences();
186
+ recurrenceToString(weekly.rule); // "Every week on Monday, Wednesday, Friday"
616
187
  ```
617
188
 
618
- ### Validation Utilities
189
+ ### Cron
190
+
191
+ Parse and match cron expressions.
619
192
 
620
193
  ```ts
621
- import { isValidDate, isLeapYear, isWeekend } from "ts-time-utils/validate";
194
+ import { matchesCron, getNextCronDate, describeCron, CRON_PRESETS } from 'ts-time-utils/cron';
622
195
 
623
- // Validations
624
- isValidDate(new Date("2025-13-01")); // false
625
- isLeapYear(2024); // true
626
- isWeekend(new Date("2025-09-13")); // true (Saturday)
196
+ matchesCron('0 9 * * 1-5', date); // true if weekday 9am
197
+ getNextCronDate('0 9 * * *'); // Next 9am
198
+ describeCron('0 9 * * 1-5'); // "At 09:00 on Monday through Friday"
199
+ CRON_PRESETS.DAILY; // "0 0 * * *"
627
200
  ```
628
201
 
629
- ### Age Utilities
202
+ ### Fiscal Year
203
+
204
+ Fiscal year utilities with configurable start month.
630
205
 
631
206
  ```ts
632
- import {
633
- calculateAge,
634
- getLifeStage,
635
- getNextBirthday,
636
- isBirthday,
637
- } from "ts-time-utils/age";
638
-
639
- // Age calculations
640
- calculateAge(new Date("1990-05-15")); // { years: 34, months: 4, days: 2 }
641
- getLifeStage(25); // "adult"
642
- getNextBirthday(new Date("1990-05-15")); // Next May 15th
643
- isBirthday(new Date("1990-05-15"), new Date("2025-05-15")); // true
207
+ import { getFiscalYear, getFiscalQuarter, FISCAL_PRESETS } from 'ts-time-utils/fiscal';
208
+
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
212
+ getFiscalQuarter(date, { startMonth: 4 }); // Q2 for UK fiscal
644
213
  ```
645
214
 
646
- ### Calendar Utilities
215
+ ### Compare & Sort
216
+
217
+ Sort, group, and analyze date arrays.
647
218
 
648
219
  ```ts
649
- import {
650
- getWeekNumber,
651
- getQuarter,
652
- getEaster,
653
- getDaysInMonth,
654
- } from "ts-time-utils/calendar";
655
-
656
- // Calendar operations
657
- getWeekNumber(new Date("2025-01-15")); // 3
658
- getQuarter(new Date("2025-07-15")); // 3
659
- getEaster(2025); // Date object for Easter Sunday 2025
660
- getDaysInMonth(2, 2024); // 29 (leap year)
220
+ import { sortDates, closestDate, groupDatesByMonth, snapDate } from 'ts-time-utils/compare';
221
+
222
+ sortDates(dates, 'desc');
223
+ closestDate(target, candidates);
224
+ groupDatesByMonth(dates); // Map by YYYY-MM
225
+ snapDate(date, 15, 'minutes'); // Snap to 15-min grid
661
226
  ```
662
227
 
663
- ### Parse Utilities
228
+ ### Iterate
229
+
230
+ Iterate through date sequences and count dates.
664
231
 
665
232
  ```ts
666
- import {
667
- parseDate,
668
- parseRelativeDate,
669
- parseCustomFormat,
670
- } from "ts-time-utils/parse";
671
-
672
- // Advanced parsing
673
- parseDate("2025-02-30"); // null (invalid date)
674
- parseDate("Dec 25, 2025"); // Date object
675
- parseRelativeDate("tomorrow"); // Date for tomorrow
676
- parseCustomFormat("25/12/2025", "DD/MM/YYYY"); // Date object
233
+ import { eachDay, eachWeekday, countWeekdays, filterDays } from 'ts-time-utils/iterate';
234
+
235
+ eachDay(start, end); // Array of each day
236
+ eachWeekday(start, end); // Weekdays only (Mon-Fri)
237
+ countWeekdays(start, end); // Number of weekdays
238
+ filterDays(start, end, d => d.getDate() === 15); // 15th of each month
677
239
  ```
678
240
 
679
- ### Performance Utilities
241
+ ### Natural Language
242
+
243
+ Parse human-friendly date strings.
680
244
 
681
245
  ```ts
682
- import {
683
- sleep,
684
- timeout,
685
- benchmark,
686
- Stopwatch,
687
- debounce,
688
- } from "ts-time-utils/performance";
689
-
690
- // Async utilities
691
- await sleep(1000); // Wait 1 second
692
- await timeout(promise, 5000); // Timeout after 5 seconds
693
-
694
- // Performance measurement
695
- const result = await benchmark(() => heavyOperation(), 10); // Run 10 times
696
- const stopwatch = new Stopwatch();
697
- stopwatch.start();
698
- // ... operations
699
- console.log(stopwatch.getElapsed()); // Get elapsed time
246
+ import { parseNaturalDate, extractDatesFromText } from 'ts-time-utils/naturalLanguage';
247
+
248
+ parseNaturalDate('tomorrow');
249
+ parseNaturalDate('next Friday');
250
+ parseNaturalDate('in 2 weeks');
251
+ parseNaturalDate('end of month');
700
252
 
701
- // Function utilities
702
- const debouncedFn = debounce(() => console.log("Called!"), 300);
253
+ extractDatesFromText('Meeting tomorrow at 3pm');
254
+ // [{ date: Date, text: 'tomorrow at 3pm', confidence: 0.9 }]
703
255
  ```
704
256
 
705
- ### Interval Utilities
257
+ ### International Holidays
258
+
259
+ Public holidays for 10 countries.
706
260
 
707
261
  ```ts
708
- import {
709
- createInterval,
710
- intervalsOverlap,
711
- mergeIntervals,
712
- } from "ts-time-utils/interval";
713
-
714
- const a = createInterval("2025-01-01", "2025-01-05");
715
- const b = createInterval("2025-01-04", "2025-01-10");
716
- intervalsOverlap(a!, b!); // true
717
- const merged = mergeIntervals([a!, b!]);
262
+ import { getHolidays, isHoliday, getNextHoliday } from 'ts-time-utils/holidays';
263
+
264
+ getHolidays(2025, 'UK'); // UK bank holidays
265
+ getHolidays(2025, 'DE'); // German holidays
266
+ isHoliday(date, 'CA'); // Is Canadian holiday?
267
+ getNextHoliday(date, 'AU'); // Next Australian holiday
268
+
269
+ // Supported: UK, NL, DE, CA, AU, IT, ES, CN, IN, US
718
270
  ```
719
271
 
720
- ### Timezone Utilities
272
+ ### Locale
273
+
274
+ Multi-language formatting with 40+ locales.
721
275
 
722
276
  ```ts
723
- import { formatInTimeZone, getTimezoneOffset } from "ts-time-utils/timezone";
724
- formatInTimeZone(new Date(), "Europe/Paris", {
725
- hour: "2-digit",
726
- minute: "2-digit",
727
- });
728
- getTimezoneOffset("America/New_York"); // e.g. -300 (minutes)
277
+ import { formatRelativeTime, formatDateLocale, detectLocale } from 'ts-time-utils/locale';
278
+
279
+ formatRelativeTime(pastDate, { locale: 'es' }); // "hace 2 horas"
280
+ formatRelativeTime(pastDate, { locale: 'de' }); // "vor 2 Stunden"
281
+ formatDateLocale(date, 'fr', 'long'); // "15 janvier 2024"
282
+ detectLocale(); // Auto-detect system locale
729
283
  ```
730
284
 
731
- ### Working Hours Utilities
285
+ ### Working Hours
286
+
287
+ Business hours calculations with break support.
732
288
 
733
289
  ```ts
734
- import { isWorkingTime, addWorkingHours } from "ts-time-utils/workingHours";
290
+ import { isWorkingTime, addWorkingDays, workingDaysBetween } from 'ts-time-utils/workingHours';
735
291
 
736
- isWorkingTime(new Date()); // depends on config
737
- addWorkingHours(new Date(), 10); // adds 10 working hours, skipping off-hours
292
+ isWorkingTime(date, config);
293
+ addWorkingDays(date, 5, config);
294
+ workingDaysBetween(start, end, config);
738
295
  ```
739
296
 
740
- ### Range Preset Utilities
297
+ ### Serialization
298
+
299
+ Safe JSON date serialization and deserialization.
741
300
 
742
301
  ```ts
743
- import { lastNDays, thisWeek, quarterRange } from "ts-time-utils/rangePresets";
302
+ import { serializeDate, parseJSONWithDates, stringifyWithDates } from 'ts-time-utils/serialize';
744
303
 
745
- const last7 = lastNDays(7);
746
- const week = thisWeek();
747
- const quarter = quarterRange();
304
+ serializeDate(date, { format: 'iso' }); // "2025-09-14T12:30:45.123Z"
305
+ serializeDate(date, { format: 'epoch' }); // 1757853045123
306
+
307
+ const json = stringifyWithDates(data, ['createdAt']);
308
+ const parsed = parseJSONWithDates(json, ['createdAt']);
748
309
  ```
749
310
 
750
- ### Cron Utilities
311
+ ### Performance
312
+
313
+ Async utilities, benchmarking, and timing.
751
314
 
752
315
  ```ts
753
- import {
754
- parseCronExpression,
755
- matchesCron,
756
- getNextCronDate,
757
- getNextCronDates,
758
- describeCron,
759
- isValidCron,
760
- CRON_PRESETS,
761
- } from "ts-time-utils/cron";
762
-
763
- // Parse a cron expression
764
- const parsed = parseCronExpression("0 9 * * 1-5"); // 9 AM weekdays
765
- // { minute: [0], hour: [9], dayOfMonth: [1-31], month: [1-12], dayOfWeek: [1,2,3,4,5] }
766
-
767
- // Check if a date matches a cron expression
768
- matchesCron("0 9 * * *", new Date("2024-01-15T09:00:00")); // true (9 AM daily)
769
- matchesCron("0 9 * * *", new Date("2024-01-15T10:00:00")); // false
770
-
771
- // Get next scheduled date
772
- getNextCronDate("0 9 * * *"); // Next 9 AM
773
- getNextCronDate("0 0 1 * *"); // Next 1st of month at midnight
774
-
775
- // Get multiple upcoming dates
776
- getNextCronDates("0 9 * * 1-5", 5); // Next 5 weekday 9 AMs
777
-
778
- // Human-readable descriptions
779
- describeCron("0 9 * * *"); // "At 09:00"
780
- describeCron("0 9 * * 1-5"); // "At 09:00 on Monday through Friday"
781
- describeCron("0 0 1 * *"); // "At 00:00 on day 1 of every month"
782
-
783
- // Validate cron expressions
784
- isValidCron("0 9 * * *"); // true
785
- isValidCron("invalid"); // false
786
-
787
- // Common presets
788
- CRON_PRESETS.EVERY_MINUTE; // "* * * * *"
789
- CRON_PRESETS.HOURLY; // "0 * * * *"
790
- CRON_PRESETS.DAILY; // "0 0 * * *"
791
- CRON_PRESETS.WEEKLY; // "0 0 * * 0"
792
- CRON_PRESETS.MONTHLY; // "0 0 1 * *"
793
- CRON_PRESETS.WEEKDAYS; // "0 0 * * 1-5"
316
+ import { sleep, benchmark, Stopwatch, debounce } from 'ts-time-utils/performance';
317
+
318
+ await sleep(1000);
319
+ await benchmark(() => heavyOperation(), 10);
320
+
321
+ const stopwatch = new Stopwatch();
322
+ stopwatch.start();
323
+ // ... operations
324
+ stopwatch.getElapsed();
325
+
326
+ const debouncedFn = debounce(fn, 300);
794
327
  ```
795
328
 
796
- ### Fiscal Year Utilities (NEW!)
329
+ ### Age
330
+
331
+ Age calculations and birthday utilities.
797
332
 
798
333
  ```ts
799
- import {
800
- getFiscalYear,
801
- getFiscalQuarter,
802
- getFiscalYearStart,
803
- getFiscalYearEnd,
804
- getFiscalPeriodInfo,
805
- formatFiscalYear,
806
- FISCAL_PRESETS,
807
- } from "ts-time-utils/fiscal";
808
-
809
- // Default calendar year (January start)
810
- getFiscalYear(new Date("2024-06-15")); // 2024
811
- getFiscalQuarter(new Date("2024-06-15")); // 2
812
-
813
- // UK/India fiscal year (April start)
814
- getFiscalYear(new Date("2024-03-15"), FISCAL_PRESETS.UK_INDIA); // 2023
815
- getFiscalYear(new Date("2024-04-15"), FISCAL_PRESETS.UK_INDIA); // 2024
816
-
817
- // Australian fiscal year (July start)
818
- getFiscalYear(new Date("2024-06-30"), FISCAL_PRESETS.AUSTRALIA); // 2023
819
- getFiscalYear(new Date("2024-07-01"), FISCAL_PRESETS.AUSTRALIA); // 2024
820
-
821
- // US Federal fiscal year (October start)
822
- getFiscalYear(new Date("2024-09-30"), FISCAL_PRESETS.US_FEDERAL); // 2023
823
- getFiscalYear(new Date("2024-10-01"), FISCAL_PRESETS.US_FEDERAL); // 2024
824
-
825
- // Get fiscal year boundaries
826
- getFiscalYearStart(2024, FISCAL_PRESETS.UK_INDIA); // April 1, 2024
827
- getFiscalYearEnd(2024, FISCAL_PRESETS.UK_INDIA); // March 31, 2025
828
-
829
- // Format fiscal years
830
- formatFiscalYear(2024); // "FY2024"
831
- formatFiscalYear(2024, FISCAL_PRESETS.UK_INDIA, "long"); // "FY2024/25"
832
-
833
- // Get comprehensive fiscal info
834
- const info = getFiscalPeriodInfo(new Date("2024-06-15"));
835
- // { fiscalYear: 2024, fiscalQuarter: 2, fiscalMonth: 6, progress: 45.2, ... }
334
+ import { calculateAge, getLifeStage, getNextBirthday } from 'ts-time-utils/age';
335
+
336
+ calculateAge(new Date('1990-05-15')); // { years: 34, months: 4, days: 2 }
337
+ getLifeStage(25); // "adult"
338
+ getNextBirthday(birthDate); // Next birthday date
836
339
  ```
837
340
 
838
- ### Date Comparison & Sorting (NEW!)
341
+ ### Countdown
342
+
343
+ Timer and countdown utilities.
839
344
 
840
345
  ```ts
841
- import {
842
- sortDates,
843
- minDate,
844
- maxDate,
845
- closestDate,
846
- uniqueDates,
847
- groupDatesByMonth,
848
- snapDate,
849
- roundDate,
850
- medianDate,
851
- } from "ts-time-utils/compare";
852
-
853
- const dates = [
854
- new Date("2024-03-15"),
855
- new Date("2024-01-10"),
856
- new Date("2024-06-20"),
857
- ];
346
+ import { createCountdown, getRemainingTime, formatCountdown } from 'ts-time-utils/countdown';
858
347
 
859
- // Sort dates
860
- sortDates(dates); // [Jan 10, Mar 15, Jun 20]
861
- sortDates(dates, "desc"); // [Jun 20, Mar 15, Jan 10]
348
+ const countdown = createCountdown(targetDate, {
349
+ onTick: (remaining) => console.log(remaining.days, 'd'),
350
+ onComplete: () => console.log('Done!'),
351
+ });
352
+ countdown.start();
862
353
 
863
- // Find extremes
864
- minDate(dates); // Jan 10, 2024
865
- maxDate(dates); // Jun 20, 2024
866
- medianDate(dates); // Mar 15, 2024
354
+ getRemainingTime(targetDate); // { days, hours, minutes, seconds }
355
+ formatCountdown(targetDate, { units: ['days', 'hours'] }); // "45d 12h"
356
+ ```
867
357
 
868
- // Find closest to target
869
- const target = new Date("2024-04-01");
870
- closestDate(target, dates); // Mar 15, 2024
358
+ ### Interval
871
359
 
872
- // Remove duplicates
873
- uniqueDates([date1, date1Copy, date2]); // [date1, date2]
874
- uniqueDates(dates, "day"); // Unique by day precision
360
+ Time interval operations.
875
361
 
876
- // Group dates
877
- groupDatesByMonth(dates);
878
- // Map { "2024-01" => [Jan 10], "2024-03" => [Mar 15], "2024-06" => [Jun 20] }
362
+ ```ts
363
+ import { createInterval, intervalsOverlap, mergeIntervals } from 'ts-time-utils/interval';
879
364
 
880
- // Snap to intervals (e.g., 15-minute blocks)
881
- snapDate(new Date("2024-01-15T10:37:00"), 15); // 10:30:00
882
- snapDate(new Date("2024-01-15T10:37:00"), 15, "ceil"); // 10:45:00
365
+ const a = createInterval('2025-01-01', '2025-01-05');
366
+ const b = createInterval('2025-01-04', '2025-01-10');
367
+ intervalsOverlap(a, b); // true
368
+ mergeIntervals([a, b]); // Single merged interval
369
+ ```
370
+
371
+ ### Range Presets
372
+
373
+ Common date range presets.
883
374
 
884
- // Round to nearest unit
885
- roundDate(new Date("2024-01-15T10:37:00"), "hour"); // 11:00:00
375
+ ```ts
376
+ import { today, lastNDays, thisWeek, thisMonth } from 'ts-time-utils/rangePresets';
377
+
378
+ today(); // { start, end } for today
379
+ lastNDays(7); // Last 7 days
380
+ thisWeek(); // Current week
381
+ thisMonth(); // Current month
886
382
  ```
887
383
 
888
- ### Date Iteration (NEW!)
384
+ ### Parse
385
+
386
+ Date parsing from various formats.
889
387
 
890
388
  ```ts
891
- import {
892
- eachDay,
893
- eachWeekday,
894
- eachWeek,
895
- eachMonth,
896
- countWeekdays,
897
- eachDayOfWeek,
898
- iterateDays,
899
- filterDays,
900
- } from "ts-time-utils/iterate";
901
-
902
- const start = new Date("2024-01-01");
903
- const end = new Date("2024-01-31");
904
-
905
- // Generate arrays of dates
906
- eachDay(start, end); // [Jan 1, Jan 2, ..., Jan 31] (31 dates)
907
- eachWeekday(start, end); // All Mon-Fri dates (23 dates)
908
- eachWeek(start, end); // [Jan 7, Jan 14, Jan 21, Jan 28] (Sundays)
909
- eachMonth(start, new Date("2024-06-30")); // [Feb 1, Mar 1, Apr 1, May 1, Jun 1]
910
-
911
- // Count dates
912
- countWeekdays(start, end); // 23
913
-
914
- // Get specific weekdays
915
- eachDayOfWeek(start, end, 1); // All Mondays in January
916
-
917
- // Lazy iteration (memory efficient for large ranges)
918
- for (const date of iterateDays(start, end)) {
919
- console.log(date);
920
- }
921
-
922
- // Filter days by custom predicate
923
- filterDays(start, end, (d) => d.getDate() === 15); // [Jan 15]
924
-
925
- // Custom intervals
926
- eachInterval(start, end, { days: 7 }); // Every 7 days
927
- eachInterval(start, end, { hours: 6 }); // Every 6 hours
389
+ import { parseDate, parseTime, autoDetectFormat } from 'ts-time-utils/parse';
390
+
391
+ parseDate('Dec 25, 2025');
392
+ parseDate('25/12/2025', 'DD/MM/YYYY');
393
+ parseTime('2:30 PM'); // { hour: 14, minute: 30 }
394
+ autoDetectFormat('2025-09-14'); // 'YYYY-MM-DD'
928
395
  ```
929
396
 
930
- ### Locale Utilities
397
+ ---
398
+
399
+ ## Plugin System
400
+
401
+ Extend ChainedDate with custom functionality.
931
402
 
932
403
  ```ts
933
- import {
934
- formatRelativeTime,
935
- formatDateLocale,
936
- formatTimeLocale,
937
- formatDateTimeLocale,
938
- registerLocale,
939
- getLocaleConfig,
940
- detectLocale,
941
- getSupportedLocales,
942
- } from "ts-time-utils/locale";
943
-
944
- // Relative time formatting in multiple languages
945
- const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
946
- formatRelativeTime(pastDate, { locale: "en" }); // "2 hours ago"
947
- formatRelativeTime(pastDate, { locale: "es" }); // "hace 2 horas"
948
- formatRelativeTime(pastDate, { locale: "fr" }); // "il y a 2 heures"
949
- formatRelativeTime(pastDate, { locale: "de" }); // "vor 2 Stunden"
950
- formatRelativeTime(pastDate, { locale: "nl" }); // "2 uur geleden"
951
- formatRelativeTime(pastDate, { locale: "it" }); // "2 ore fa"
952
- formatRelativeTime(pastDate, { locale: "zh" }); // "2小时前"
953
- formatRelativeTime(pastDate, { locale: "ja" }); // "2時間前"
954
- formatRelativeTime(pastDate, { locale: "fa" }); // "2 ساعت پیش"
955
-
956
- // Future dates
957
- const futureDate = new Date(Date.now() + 3 * 24 * 60 * 60 * 1000);
958
- formatRelativeTime(futureDate, { locale: "en" }); // "in 3 days"
959
- formatRelativeTime(futureDate, { locale: "es" }); // "en 3 dĂ­as"
960
- formatRelativeTime(futureDate, { locale: "nl" }); // "over 3 dagen"
961
- formatRelativeTime(futureDate, { locale: "it" }); // "tra 3 giorni"
962
- formatRelativeTime(futureDate, { locale: "fa" }); // "3 روز دیگر"
963
-
964
- // Relative time options
965
- formatRelativeTime(pastDate, {
966
- locale: "en",
967
- maxUnit: "days", // Don't use units larger than days
968
- minUnit: "minutes", // Don't use units smaller than minutes
969
- precision: 1, // Show 1 decimal place: "2.0 hours ago"
970
- short: true, // Use abbreviated format: "2h ago"
971
- numeric: "auto", // Use words when appropriate: "yesterday"
972
- });
404
+ import { chain, registerPlugin, createPlugin } from 'ts-time-utils/chain';
973
405
 
974
- // Date formatting
975
- const date = new Date("2024-01-15T14:30:45Z");
976
- formatDateLocale(date, "en", "medium"); // "Jan 15, 2024"
977
- formatDateLocale(date, "es", "medium"); // "15 ene 2024"
978
- formatDateLocale(date, "fr", "long"); // "15 janvier 2024"
979
- formatDateLocale(date, "de", "short"); // "15.1.2024"
980
-
981
- // Time formatting
982
- formatTimeLocale(date, "en", "short"); // "2:30 PM"
983
- formatTimeLocale(date, "de", "medium"); // "14:30:45"
984
- formatTimeLocale(date, "fr", "long"); // "14:30:45 UTC"
985
-
986
- // Combined date and time
987
- formatDateTimeLocale(date, "en"); // "Jan 15, 2024 2:30:45 PM"
988
-
989
- // Auto-detect locale from browser/system
990
- const userLocale = detectLocale(); // e.g., 'en-US' or 'fr-FR'
991
- formatRelativeTime(pastDate, { locale: userLocale });
992
-
993
- // Get supported locales
994
- const locales = getSupportedLocales();
995
- // ['en', 'es', 'fr', 'de', 'zh', 'ja', ...]
996
-
997
- // Register custom locale
998
- registerLocale("custom", {
999
- locale: "custom",
1000
- dateFormats: {
1001
- short: "M/d/yyyy",
1002
- medium: "MMM d, yyyy",
1003
- long: "MMMM d, yyyy",
1004
- full: "EEEE, MMMM d, yyyy",
1005
- },
1006
- timeFormats: {
1007
- short: "h:mm a",
1008
- medium: "h:mm:ss a",
1009
- long: "h:mm:ss a z",
1010
- full: "h:mm:ss a zzzz",
1011
- },
1012
- relativeTime: {
1013
- future: "in {0}",
1014
- past: "{0} ago",
1015
- units: {
1016
- second: "sec",
1017
- seconds: "secs",
1018
- minute: "min",
1019
- minutes: "mins",
1020
- hour: "hr",
1021
- hours: "hrs",
1022
- day: "day",
1023
- days: "days",
1024
- week: "wk",
1025
- weeks: "wks",
1026
- month: "mo",
1027
- months: "mos",
1028
- year: "yr",
1029
- years: "yrs",
1030
- },
1031
- },
1032
- calendar: {
1033
- weekStartsOn: 0, // Sunday
1034
- monthNames: ["Jan", "Feb", "Mar" /* ... */],
1035
- monthNamesShort: ["J", "F", "M" /* ... */],
1036
- dayNames: ["Sun", "Mon", "Tue" /* ... */],
1037
- dayNamesShort: ["S", "M", "T" /* ... */],
1038
- },
1039
- numbers: {
1040
- decimal: ".",
1041
- thousands: ",",
406
+ const businessPlugin = createPlugin('business', {
407
+ addBusinessDays(days: number) {
408
+ // Implementation
409
+ return this;
1042
410
  },
411
+ isBusinessDay() {
412
+ const day = this.toDate().getDay();
413
+ return day !== 0 && day !== 6;
414
+ }
1043
415
  });
1044
416
 
1045
- // Locale Conversion Utilities
1046
- import {
1047
- convertRelativeTime,
1048
- detectLocaleFromRelativeTime,
1049
- convertFormatPattern,
1050
- convertFormattedDate,
1051
- convertRelativeTimeArray,
1052
- compareLocaleFormats,
1053
- } from "ts-time-utils/locale";
1054
-
1055
- // Convert relative time between locales
1056
- convertRelativeTime("2 hours ago", "en", "es"); // "hace 2 horas"
1057
- convertRelativeTime("hace 3 dĂ­as", "es", "fr"); // "il y a 3 jours"
1058
- convertRelativeTime("2h ago", "en", "de"); // "vor 2h"
1059
- convertRelativeTime("2 hours ago", "en", "nl"); // "2 uur geleden"
1060
- convertRelativeTime("2 hours ago", "en", "it"); // "2 ore fa"
1061
- convertRelativeTime("2 hours ago", "en", "fa"); // "2 ساعت پیش"
1062
- convertRelativeTime("2 ساعت پیش", "fa", "en"); // "2 hours ago"
1063
-
1064
- // Detect locale from formatted text
1065
- detectLocaleFromRelativeTime("2 hours ago"); // "en"
1066
- detectLocaleFromRelativeTime("hace 2 horas"); // "es"
1067
- detectLocaleFromRelativeTime("il y a 2 heures"); // "fr"
1068
- detectLocaleFromRelativeTime("2 uur geleden"); // "nl"
1069
- detectLocaleFromRelativeTime("2 ore fa"); // "it"
1070
- detectLocaleFromRelativeTime("2 ساعت پیش"); // "fa"
1071
- detectLocaleFromRelativeTime("vor 2 Stunden"); // "de"
1072
-
1073
- // Convert date format patterns between locales
1074
- convertFormatPattern("M/d/yyyy", "en", "de"); // "dd.MM.yyyy"
1075
- convertFormatPattern("MMM d, yyyy", "en", "fr", "long"); // "d MMMM yyyy"
1076
-
1077
- // Convert formatted dates between locales
1078
- convertFormattedDate("Jan 15, 2024", "en", "es"); // "15 ene 2024"
1079
- convertFormattedDate("15. Januar 2024", "de", "en"); // "Jan 15, 2024"
1080
-
1081
- // Bulk conversion of relative time arrays
1082
- const englishTimes = ["2 hours ago", "in 3 days", "1 week ago"];
1083
- convertRelativeTimeArray(englishTimes, "en", "es");
1084
- // ["hace 2 horas", "en 3 dĂ­as", "hace 1 semana"]
1085
-
1086
- // Compare format differences between locales
1087
- const comparison = compareLocaleFormats("en", "de");
1088
- console.log(comparison.dateFormats.short);
1089
- // { locale1: "M/d/yyyy", locale2: "dd.MM.yyyy" }
1090
- console.log(comparison.weekStartsOn);
1091
- // { locale1: 0, locale2: 1 } // Sunday vs Monday
417
+ registerPlugin(businessPlugin);
418
+
419
+ chain(new Date())
420
+ .addBusinessDays(5)
421
+ .isBusinessDay(); // true/false
1092
422
  ```
1093
423
 
1094
- ## 📊 API Reference
1095
-
1096
- ### Duration Functions
1097
-
1098
- - `Duration` class - Immutable duration with full arithmetic support
1099
- - `createDuration(input)` - Create duration from number, object, or string
1100
- - `Duration.fromHours/Minutes/Seconds/Days/Weeks(n)` - Create from specific units
1101
- - `Duration.fromString(str)` - Parse from string like "1h 30m 45s"
1102
- - `Duration.between(start, end)` - Create from date range
1103
- - `duration.add/subtract/multiply/divide()` - Arithmetic operations
1104
- - `duration.equals/greaterThan/lessThan()` - Comparison methods
1105
- - `formatDurationString(duration, options?)` - Format to readable string
1106
- - `maxDuration/minDuration(...durations)` - Find extremes
1107
- - `sumDurations/averageDuration(...durations)` - Aggregate operations
1108
-
1109
- ### Serialization Functions
1110
-
1111
- - `serializeDate(date, options?)` - Serialize date to various formats (ISO, epoch, object, custom)
1112
- - `deserializeDate(serialized, options?)` - Deserialize from string, number, or object
1113
- - `parseJSONWithDates(jsonString, dateKeys?, options?)` - Parse JSON with automatic date conversion
1114
- - `stringifyWithDates(obj, dateKeys?, options?)` - Stringify JSON with automatic date serialization
1115
- - `createDateReviver/createDateReplacer(dateKeys?, options?)` - Create JSON reviver/replacer functions
1116
- - `toEpochTimestamp/fromEpochTimestamp(input, precision?)` - Convert to/from epoch timestamps
1117
- - `toDateObject/fromDateObject(input)` - Convert to/from safe object representation
1118
- - `isValidISODateString/isValidEpochTimestamp(input)` - Validation utilities
1119
- - `cloneDate(date)` - Safe date cloning
1120
- - `datesEqual(date1, date2, precision?)` - Compare dates with precision control
1121
-
1122
- ### Format Functions
1123
-
1124
- - `formatDuration(ms, options?)` - Format milliseconds to readable duration
1125
- - `formatDurationCompact(ms)` - Format milliseconds as HH:MM:SS
1126
- - `timeAgo(date, options?)` - Get "time ago" string for past/future dates
1127
- - `formatTime(date, format?)` - Format time as 12h/24h/ISO
1128
- - `formatDate(date, pattern?)` - Format date using patterns (YYYY-MM-DD, etc.)
1129
- - `formatRelativeTime(date, locale?, options?)` - Format as relative time ("2 days ago")
1130
- - `formatDateRange(start, end, options?)` - Format date ranges ("Jan 1-5, 2024")
1131
- - `formatOrdinal(n)` - Format number as ordinal ("1st", "2nd", "3rd")
1132
- - `formatDayOrdinal(date)` - Format day with ordinal ("1st", "15th")
1133
- - `formatCalendarDate(date)` - Format as "Today", "Tomorrow", or day name
1134
- - `parseDuration(duration)` - Parse duration string to milliseconds
1135
-
1136
- ### Parse Functions
1137
-
1138
- - `parseISO8601Duration(duration)` - Parse ISO 8601 duration to object (P1Y2M3DT4H5M6S)
1139
- - `parseISO8601DurationToMs(duration)` - Parse ISO 8601 duration to milliseconds
1140
- - `parseTime(timeString)` - Parse time string ("14:30", "2:30 PM") to Date
1141
- - `guessDateFormat(dateString)` - Guess the format of a date string
1142
- - `parseAutoFormat(dateString)` - Auto-detect and parse date string
1143
- - `parseRangeEndpoint(endpoint)` - Parse range endpoint (date string, Date, or number)
1144
-
1145
- ### Calendar Functions
1146
-
1147
- - `getCalendarDays(year, month)` - Get array of days for a calendar month
1148
- - `getWeekNumber(date)` - Get ISO week number (1-53)
1149
- - `getQuarter(date)` - Get quarter (1-4)
1150
- - `getFirstDayOfMonth(date)` / `getLastDayOfMonth(date)` - Month boundaries
1151
- - `getFirstDayOfWeek(date)` / `getLastDayOfWeek(date)` - Week boundaries
1152
- - `getNthDayOfMonth(year, month, dayOfWeek, n)` - Get nth occurrence of weekday in month
1153
- - `getStartOfWeek(date, startDay?)` - Get start of week (configurable start day)
1154
- - `getEndOfWeek(date, startDay?)` - Get end of week (configurable start day)
1155
- - `getWeeksInMonth(year, month)` - Count weeks in a month
1156
-
1157
- #### US Federal Holidays
1158
-
1159
- - `getNewYearsDay(year)` - Get New Year's Day
1160
- - `getMLKDay(year)` - Get Martin Luther King Jr. Day (3rd Monday of January)
1161
- - `getPresidentsDay(year)` - Get Presidents Day (3rd Monday of February)
1162
- - `getMemorialDay(year)` - Get Memorial Day (last Monday of May)
1163
- - `getIndependenceDay(year)` - Get Independence Day (July 4th)
1164
- - `getLaborDay(year)` - Get Labor Day (1st Monday of September)
1165
- - `getColumbusDay(year)` - Get Columbus Day (2nd Monday of October)
1166
- - `getVeteransDay(year)` - Get Veterans Day (November 11th)
1167
- - `getThanksgivingDay(year)` - Get Thanksgiving Day (4th Thursday of November)
1168
- - `getChristmasDay(year)` - Get Christmas Day
1169
- - `getGoodFriday(year)` - Get Good Friday
1170
- - `getUSHolidays(year)` - Get all US federal holidays for a year
1171
- - `isUSHoliday(date)` - Check if date is a US federal holiday
1172
- - `getUSHolidayName(date)` - Get name of US holiday (or null)
1173
-
1174
- ### Timezone Functions
1175
-
1176
- - `getTimezoneOffset(timezone, date?)` - Get timezone offset in minutes
1177
- - `convertTimezone(date, fromTz, toTz)` - Convert date between timezones
1178
- - `getTimezoneNames()` - Get array of valid timezone names
1179
- - `formatWithTimezone(date, timezone, format?)` - Format date in specific timezone
1180
- - `isDST(date, timezone?)` - Check if DST is in effect
1181
- - `getNextDSTTransition(date?, timezone?)` - Get next DST transition date
1182
- - `findCommonWorkingHours(tz1, tz2, workStart?, workEnd?)` - Find overlapping work hours
1183
- - `getTimezoneAbbreviation(date, timezone?)` - Get timezone abbreviation (EST, PST, etc.)
1184
- - `convertBetweenZones(date, fromTz, toTz)` - Convert date between zones (returns new Date)
1185
- - `getTimezoneDifferenceHours(tz1, tz2, date?)` - Get hour difference between timezones
1186
- - `isSameTimezone(tz1, tz2, date?)` - Check if two timezones have same offset
1187
-
1188
- ### Working Hours Functions
1189
-
1190
- - `isWithinWorkingHours(date, config?)` - Check if time is within working hours
1191
- - `getNextWorkingHour(date, config?)` - Get next available working hour
1192
- - `addWorkingMinutes(date, minutes, config?)` - Add minutes within working hours
1193
- - `workingMinutesBetween(start, end, config?)` - Count working minutes between dates
1194
- - `addWorkingDays(date, days, config?)` - Add working days to date
1195
- - `subtractWorkingDays(date, days, config?)` - Subtract working days from date
1196
- - `getNextWorkingDay(date, config?)` - Get next working day
1197
- - `getPreviousWorkingDay(date, config?)` - Get previous working day
1198
- - `getWorkingDaysInMonth(year, month, config?)` - Count working days in month
1199
- - `getWorkingDaysInMonthArray(year, month, config?)` - Get array of working days
1200
- - `workingDaysBetween(start, end, config?)` - Count working days between dates
1201
- - `isBreakTime(date, breakStart?, breakEnd?)` - Check if time is during break
1202
- - `getWorkDayStart(date, config?)` - Get start time of work day
1203
- - `getWorkDayEnd(date, config?)` - Get end time of work day
1204
- - `getWorkingHoursPerDay(config?)` - Get working hours per day
1205
-
1206
- ### Cron Functions
1207
-
1208
- - `parseCronExpression(expression)` - Parse cron expression to object
1209
- - `matchesCron(expression, date?)` - Check if date matches cron expression
1210
- - `getNextCronDate(expression, after?)` - Get next date matching cron
1211
- - `getNextCronDates(expression, count, after?)` - Get multiple future cron dates
1212
- - `getPreviousCronDate(expression, before?)` - Get previous date matching cron
1213
- - `isValidCron(expression)` - Validate cron expression syntax
1214
- - `describeCron(expression)` - Get human-readable cron description
1215
- - `CRON_PRESETS` - Common cron expressions (EVERY_MINUTE, HOURLY, DAILY, etc.)
1216
-
1217
- ### Fiscal Year Functions
1218
-
1219
- - `getFiscalYear(date, config?)` - Get fiscal year for a date
1220
- - `getFiscalQuarter(date, config?)` - Get fiscal quarter (1-4)
1221
- - `getFiscalMonth(date, config?)` - Get fiscal month (1-12 within fiscal year)
1222
- - `getFiscalWeek(date, config?)` - Get fiscal week number
1223
- - `getFiscalYearStart(year, config?)` - Get start date of fiscal year
1224
- - `getFiscalYearEnd(year, config?)` - Get end date of fiscal year
1225
- - `getFiscalQuarterStart(year, quarter, config?)` - Get start of fiscal quarter
1226
- - `getFiscalQuarterEnd(year, quarter, config?)` - Get end of fiscal quarter
1227
- - `isSameFiscalYear(date1, date2, config?)` - Check if dates are in same fiscal year
1228
- - `isSameFiscalQuarter(date1, date2, config?)` - Check if dates are in same fiscal quarter
1229
- - `getDaysElapsedInFiscalYear(date, config?)` - Days elapsed in fiscal year
1230
- - `getDaysRemainingInFiscalYear(date, config?)` - Days remaining in fiscal year
1231
- - `getFiscalYearProgress(date, config?)` - Percentage of fiscal year completed
1232
- - `formatFiscalYear(year, config?, format?)` - Format as "FY2024" or "FY2023/24"
1233
- - `formatFiscalQuarter(year, quarter, config?)` - Format as "Q1 FY2024"
1234
- - `getFiscalPeriodInfo(date, config?)` - Get comprehensive fiscal period info
1235
- - `FISCAL_PRESETS` - CALENDAR, UK_INDIA, AUSTRALIA, US_FEDERAL
1236
-
1237
- ### Compare Functions
1238
-
1239
- - `compareDates(a, b)` - Compare function for sorting dates
1240
- - `compareDatesDesc(a, b)` - Compare function for reverse sorting
1241
- - `sortDates(dates, direction?)` - Sort date array (asc/desc)
1242
- - `minDate(dates)` - Find earliest date
1243
- - `maxDate(dates)` - Find latest date
1244
- - `dateExtent(dates)` - Get { min, max } from date array
1245
- - `uniqueDates(dates, precision?)` - Remove duplicate dates
1246
- - `closestDate(target, candidates)` - Find closest date to target
1247
- - `closestFutureDate(target, candidates)` - Find closest future date
1248
- - `closestPastDate(target, candidates)` - Find closest past date
1249
- - `clampDate(date, min, max)` - Constrain date to range
1250
- - `isDateInRange(date, min, max)` - Check if date is in range
1251
- - `filterDatesInRange(dates, min, max)` - Filter dates in range
1252
- - `groupDates(dates, keyFn)` - Group dates by custom key
1253
- - `groupDatesByYear(dates)` - Group by year
1254
- - `groupDatesByMonth(dates)` - Group by month (YYYY-MM)
1255
- - `groupDatesByDay(dates)` - Group by day (YYYY-MM-DD)
1256
- - `groupDatesByDayOfWeek(dates)` - Group by day of week (0-6)
1257
- - `medianDate(dates)` - Calculate median date
1258
- - `averageDate(dates)` - Calculate average/mean date
1259
- - `roundDate(date, unit)` - Round to nearest minute/hour/day
1260
- - `snapDate(date, intervalMinutes, mode?)` - Snap to interval grid
1261
- - `isChronological(dates, strict?)` - Check if dates are in order
1262
- - `dateSpan(dates)` - Get duration between min and max
1263
- - `partitionDates(dates, predicate)` - Split into [matching, non-matching]
1264
- - `nthDate(dates, n)` - Get nth date (supports negative indices)
1265
-
1266
- ### Iterate Functions
1267
-
1268
- - `eachDay(start, end)` - Array of each day in range
1269
- - `eachWeekday(start, end)` - Array of weekdays (Mon-Fri)
1270
- - `eachWeekend(start, end)` - Array of weekend days (Sat-Sun)
1271
- - `eachWeek(start, end, weekStartsOn?)` - Array of week starts
1272
- - `eachMonth(start, end)` - Array of month starts
1273
- - `eachMonthEnd(start, end)` - Array of month ends
1274
- - `eachQuarter(start, end)` - Array of quarter starts
1275
- - `eachYear(start, end)` - Array of year starts
1276
- - `eachHour(start, end, step?)` - Array of hourly intervals
1277
- - `eachMinute(start, end, step?)` - Array of minute intervals
1278
- - `eachDayOfWeek(start, end, dayOfWeek)` - Array of specific weekday
1279
- - `eachNthDayOfMonth(start, end, day)` - Array of nth day of each month
1280
- - `eachInterval(start, end, interval)` - Array at custom intervals
1281
- - `countDays(start, end)` - Count days in range
1282
- - `countWeekdays(start, end)` - Count weekdays in range
1283
- - `countWeekendDays(start, end)` - Count weekend days
1284
- - `countWeeks(start, end)` - Count weeks in range
1285
- - `countMonths(start, end)` - Count months in range
1286
- - `iterateDates(start, end, step?)` - Lazy date generator
1287
- - `iterateDays(start, end)` - Lazy day iterator
1288
- - `iterateWeekdays(start, end)` - Lazy weekday iterator
1289
- - `iterateMonths(start, end)` - Lazy month iterator
1290
- - `filterDays(start, end, filter)` - Filter days by predicate
1291
-
1292
- ### Calculate Functions
1293
-
1294
- - `differenceInUnits(date1, date2, unit?, precise?)` - Calculate difference between dates
1295
- - `addTime(date, amount, unit)` - Add time to a date
1296
- - `subtractTime(date, amount, unit)` - Subtract time from a date
1297
- - `startOf(date, unit)` - Get start of time period
1298
- - `endOf(date, unit)` - Get end of time period
1299
- - `isBetween(date, start, end)` - Check if date is between two dates
1300
- - `businessDaysBetween(start, end)` - Count business days between dates
1301
-
1302
- ### Validation Functions
1303
-
1304
- - `isValidDate(date)` - Check if date is valid
1305
- - `isLeapYear(year)` - Check if year is leap year
1306
- - `isPast(date)` / `isFuture(date)` - Check if date is past/future
1307
- - `isToday(date)` / `isYesterday(date)` / `isTomorrow(date)` - Date comparisons
1308
- - `isSameDay(date1, date2)` - Check if dates are same day
1309
- - `isSameWeek(date1, date2)` - Check if dates are in same week
1310
- - `isSameMonth(date1, date2)` - Check if dates are in same month
1311
- - `isSameYear(date1, date2)` - Check if dates are in same year
1312
- - `isThisWeek(date)` - Check if date is in current week
1313
- - `isThisMonth(date)` - Check if date is in current month
1314
- - `isThisYear(date)` - Check if date is in current year
1315
- - `isWeekend(date)` / `isWeekday(date)` - Check day type
1316
- - `isBusinessDay(date)` - Check if date is a business day (weekday, not a US holiday)
1317
- - `isInLastNDays(date, n)` - Check if date is within last N days
1318
- - `isInNextNDays(date, n)` - Check if date is within next N days
1319
- - `isValidTimeString(time)` - Validate HH:MM time format
1320
- - `isValidISOString(dateString)` - Validate ISO 8601 date string
1321
-
1322
- ### Locale Functions
1323
-
1324
- - `formatRelativeTime(date, options?)` - Format relative time with locale support
1325
- - Options: `locale`, `maxUnit`, `minUnit`, `precision`, `short`, `numeric`, `style`
1326
- - Supports 30+ locales: en, es, fr, de, it, pt, nl, sv, da, no, fi, pl, cs, sk, hu, ro, bg, hr, sl, et, lv, lt, ru, uk, tr, ar, he, hi, th, ko, zh, ja
1327
- - `formatDateLocale(date, locale?, style?)` - Format date in locale-specific format
1328
- - Styles: 'short', 'medium', 'long', 'full'
1329
- - `formatTimeLocale(date, locale?, style?)` - Format time in locale-specific format
1330
- - `formatDateTimeLocale(date, locale?, dateStyle?, timeStyle?)` - Format both date and time
1331
- - `registerLocale(locale, config)` - Register a custom locale configuration
1332
- - `getLocaleConfig(locale)` - Get configuration for a specific locale
1333
- - `detectLocale(fallback?)` - Auto-detect system/browser locale
1334
- - `getSupportedLocales()` - Get array of all supported locale codes
1335
- - `getMonthNames(locale?, short?)` - Get localized month names
1336
- - `getDayNames(locale?, short?)` - Get localized day names
1337
- - `getBestMatchingLocale(preferences, fallback?)` - Find best matching locale from preferences
1338
-
1339
- #### Locale Conversion Functions
1340
-
1341
- - `convertRelativeTime(text, fromLocale, toLocale)` - Convert relative time between locales
1342
- - Example: `convertRelativeTime("2 hours ago", "en", "es")` → `"hace 2 horas"`
1343
- - Example: `convertRelativeTime("2 hours ago", "en", "nl")` → `"2 uur geleden"`
1344
- - Example: `convertRelativeTime("2 hours ago", "en", "it")` → `"2 ore fa"`
1345
- - Example: `convertRelativeTime("2 hours ago", "en", "fa")` → `"2 ساعت پیش"`
1346
- - `detectLocaleFromRelativeTime(text)` - Detect locale from relative time string
1347
- - Returns most likely locale or null if detection fails
1348
- - `convertFormatPattern(pattern, fromLocale, toLocale, style?)` - Convert date format patterns
1349
- - Maps common patterns between locales or uses target locale's style
1350
- - `convertFormattedDate(formattedDate, fromLocale, toLocale, targetStyle?)` - Convert formatted dates
1351
- - Parses date in source locale and reformats in target locale
1352
- - `convertRelativeTimeArray(array, fromLocale, toLocale)` - Bulk convert relative time arrays
1353
- - Returns array with same length, null for unparseable strings
1354
- - `compareLocaleFormats(locale1, locale2)` - Compare format differences between locales
1355
- - Returns object with dateFormats, timeFormats, and weekStartsOn comparisons
1356
-
1357
- ## 🛠️ Development
424
+ ---
425
+
426
+ ## API Reference
427
+
428
+ For complete API documentation, see the [Playground & Docs](https://ts-time-utils.h8frad.work).
429
+
430
+ ### All Modules
431
+
432
+ | Module | Description |
433
+ |--------|-------------|
434
+ | `format` | Duration formatting, time ago, date patterns |
435
+ | `calculate` | Date arithmetic, differences, period boundaries |
436
+ | `validate` | Date validation, comparisons, type checks |
437
+ | `duration` | Immutable Duration class with arithmetic |
438
+ | `chain` | Fluent chainable API |
439
+ | `timezone` | Timezone conversions, DST handling |
440
+ | `calendar` | ISO weeks, quarters, holidays, grids |
441
+ | `dateRange` | Range operations: overlap, gaps, merge |
442
+ | `recurrence` | RRULE-inspired recurring patterns |
443
+ | `cron` | Cron expression parsing and matching |
444
+ | `fiscal` | Fiscal year utilities |
445
+ | `compare` | Date sorting, grouping, statistics |
446
+ | `iterate` | Date iteration and counting |
447
+ | `naturalLanguage` | Natural language date parsing |
448
+ | `holidays` | International holiday calculations |
449
+ | `locale` | Multi-language formatting (40+ locales) |
450
+ | `workingHours` | Business hours calculations |
451
+ | `serialize` | JSON date serialization |
452
+ | `performance` | Async utilities, benchmarking |
453
+ | `age` | Age calculations, birthdays |
454
+ | `countdown` | Timer and countdown utilities |
455
+ | `interval` | Time interval operations |
456
+ | `rangePresets` | Common date range presets |
457
+ | `parse` | Date parsing from various formats |
458
+ | `plugins` | Plugin system for extensions |
459
+ | `constants` | Time constants and types |
460
+
461
+ ---
462
+
463
+ ## Development
1358
464
 
1359
465
  ```bash
1360
- # Install dependencies
1361
- npm install
1362
-
1363
- # Build (both CommonJS and ES modules)
1364
- npm run build
1365
-
1366
- # Run tests
1367
- npm test
1368
-
1369
- # Run tests in watch mode
1370
- npm run test:watch
1371
-
1372
- # Lint code
1373
- npm run lint
466
+ npm install # Install dependencies
467
+ npm run build # Build both CJS and ESM
468
+ npm test # Run tests
469
+ npm run lint # Lint code
1374
470
  ```
1375
471
 
1376
- ## 📄 License
472
+ ## License
1377
473
 
1378
474
  MIT