ts-time-utils 3.0.0 â 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +401 -1329
- package/dist/calculate.d.ts +25 -0
- package/dist/calculate.d.ts.map +1 -1
- package/dist/calculate.js +125 -0
- package/dist/calendar.d.ts +45 -0
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +68 -0
- package/dist/calendars.d.ts +156 -0
- package/dist/calendars.d.ts.map +1 -0
- package/dist/calendars.js +348 -0
- package/dist/compare.d.ts +27 -0
- package/dist/compare.d.ts.map +1 -1
- package/dist/compare.js +46 -0
- package/dist/esm/calculate.d.ts +25 -0
- package/dist/esm/calculate.d.ts.map +1 -1
- package/dist/esm/calculate.js +125 -0
- package/dist/esm/calendar.d.ts +45 -0
- package/dist/esm/calendar.d.ts.map +1 -1
- package/dist/esm/calendar.js +68 -0
- package/dist/esm/calendars.d.ts +156 -0
- package/dist/esm/calendars.d.ts.map +1 -0
- package/dist/esm/calendars.js +348 -0
- package/dist/esm/compare.d.ts +27 -0
- package/dist/esm/compare.d.ts.map +1 -1
- package/dist/esm/compare.js +46 -0
- package/dist/esm/holidays.d.ts +11 -1
- package/dist/esm/holidays.d.ts.map +1 -1
- package/dist/esm/holidays.js +220 -1
- package/dist/esm/index.d.ts +13 -7
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +17 -9
- package/dist/esm/iterate.d.ts +55 -0
- package/dist/esm/iterate.d.ts.map +1 -1
- package/dist/esm/iterate.js +86 -0
- package/dist/esm/locale.d.ts +53 -0
- package/dist/esm/locale.d.ts.map +1 -1
- package/dist/esm/locale.js +141 -0
- package/dist/esm/precision.d.ts +225 -0
- package/dist/esm/precision.d.ts.map +1 -0
- package/dist/esm/precision.js +491 -0
- package/dist/esm/temporal.d.ts +237 -0
- package/dist/esm/temporal.d.ts.map +1 -0
- package/dist/esm/temporal.js +660 -0
- package/dist/esm/validate.d.ts +30 -0
- package/dist/esm/validate.d.ts.map +1 -1
- package/dist/esm/validate.js +48 -0
- package/dist/holidays.d.ts +11 -1
- package/dist/holidays.d.ts.map +1 -1
- package/dist/holidays.js +220 -1
- package/dist/index.d.ts +13 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -9
- package/dist/iterate.d.ts +55 -0
- package/dist/iterate.d.ts.map +1 -1
- package/dist/iterate.js +86 -0
- package/dist/locale.d.ts +53 -0
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +141 -0
- package/dist/precision.d.ts +225 -0
- package/dist/precision.d.ts.map +1 -0
- package/dist/precision.js +491 -0
- package/dist/temporal.d.ts +237 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +660 -0
- package/dist/validate.d.ts +30 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +48 -0
- package/package.json +22 -2
package/README.md
CHANGED
|
@@ -1,1487 +1,559 @@
|
|
|
1
1
|
# ts-time-utils
|
|
2
2
|
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
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/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
|
-
|
|
247
|
-
### đ§ą Constants
|
|
248
|
-
|
|
249
|
-
- Milliseconds & seconds per unit
|
|
250
|
-
- Time unit and formatting option types
|
|
251
|
-
|
|
252
|
-
## đŚ Installation
|
|
3
|
+
A comprehensive TypeScript utility library for time, dates, durations, and calendar operations. Zero dependencies, full tree-shaking support, 400+ functions across 29 categories.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/ts-time-utils)
|
|
6
|
+
[](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** â 400+ functions across 29 utility categories
|
|
16
|
+
- **Fluent API** â Chain operations with the `chain()` API
|
|
17
|
+
- **Extensible** â Plugin system for custom functionality
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
253
20
|
|
|
254
21
|
```bash
|
|
255
22
|
npm install ts-time-utils
|
|
256
23
|
```
|
|
257
24
|
|
|
258
|
-
##
|
|
259
|
-
|
|
260
|
-
### Import everything (not recommended for production)
|
|
25
|
+
## Quick Start
|
|
261
26
|
|
|
262
27
|
```ts
|
|
263
|
-
import { formatDuration, timeAgo,
|
|
28
|
+
import { formatDuration, timeAgo, Duration } from 'ts-time-utils';
|
|
29
|
+
|
|
30
|
+
// Format milliseconds to readable duration
|
|
31
|
+
formatDuration(3661000); // "1 hour, 1 minute, 1 second"
|
|
32
|
+
|
|
33
|
+
// Get "time ago" strings
|
|
34
|
+
timeAgo(new Date(Date.now() - 3600000)); // "1 hour ago"
|
|
35
|
+
|
|
36
|
+
// Duration arithmetic
|
|
37
|
+
const meeting = Duration.fromMinutes(45);
|
|
38
|
+
const buffer = Duration.fromMinutes(15);
|
|
39
|
+
meeting.add(buffer).toString(); // "1h"
|
|
264
40
|
```
|
|
265
41
|
|
|
266
|
-
###
|
|
42
|
+
### Tree-shaking (recommended)
|
|
267
43
|
|
|
268
44
|
```ts
|
|
269
|
-
import { formatDuration
|
|
270
|
-
import { differenceInUnits
|
|
271
|
-
import { isValidDate
|
|
272
|
-
import { calculateAge, getNextBirthday } from "ts-time-utils/age";
|
|
273
|
-
import {
|
|
274
|
-
getWeekNumber,
|
|
275
|
-
getQuarter,
|
|
276
|
-
getUSHolidays,
|
|
277
|
-
} from "ts-time-utils/calendar";
|
|
278
|
-
import { parseDate, parseRelativeDate, parseTime } from "ts-time-utils/parse";
|
|
279
|
-
import { sleep, benchmark, Stopwatch } from "ts-time-utils/performance";
|
|
280
|
-
import { createInterval, mergeIntervals } from "ts-time-utils/interval";
|
|
281
|
-
import { formatInTimeZone, isDST } from "ts-time-utils/timezone";
|
|
282
|
-
import { isWorkingTime, addWorkingDays } from "ts-time-utils/workingHours";
|
|
283
|
-
import { today, lastNDays } from "ts-time-utils/rangePresets";
|
|
284
|
-
import { Duration, createDuration } from "ts-time-utils/duration";
|
|
285
|
-
import { serializeDate, parseJSONWithDates } from "ts-time-utils/serialize";
|
|
286
|
-
import {
|
|
287
|
-
formatRelativeTime,
|
|
288
|
-
formatDateLocale,
|
|
289
|
-
detectLocale,
|
|
290
|
-
} from "ts-time-utils/locale";
|
|
291
|
-
import { createRecurrence, getNextOccurrence } from "ts-time-utils/recurrence";
|
|
292
|
-
import { createCountdown, getRemainingTime } from "ts-time-utils/countdown";
|
|
293
|
-
import { mergeDateRanges, findGaps } from "ts-time-utils/dateRange";
|
|
294
|
-
import {
|
|
295
|
-
parseNaturalDate,
|
|
296
|
-
extractDatesFromText,
|
|
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";
|
|
45
|
+
import { formatDuration } from 'ts-time-utils/format';
|
|
46
|
+
import { differenceInUnits } from 'ts-time-utils/calculate';
|
|
47
|
+
import { isValidDate } from 'ts-time-utils/validate';
|
|
333
48
|
```
|
|
334
49
|
|
|
335
|
-
|
|
50
|
+
---
|
|
336
51
|
|
|
337
|
-
|
|
52
|
+
## Utility Categories
|
|
53
|
+
|
|
54
|
+
### Format
|
|
55
|
+
|
|
56
|
+
Format durations, time ago strings, and custom date formats.
|
|
338
57
|
|
|
339
58
|
```ts
|
|
340
|
-
import {
|
|
341
|
-
|
|
342
|
-
// Daily recurrence
|
|
343
|
-
const daily = createRecurrence({
|
|
344
|
-
frequency: "daily",
|
|
345
|
-
interval: 2,
|
|
346
|
-
startDate: new Date("2024-01-01"),
|
|
347
|
-
count: 10,
|
|
348
|
-
});
|
|
59
|
+
import { formatDuration, timeAgo, parseDuration } from 'ts-time-utils/format';
|
|
349
60
|
|
|
350
|
-
|
|
351
|
-
|
|
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)
|
|
65
|
+
```
|
|
352
66
|
|
|
353
|
-
|
|
354
|
-
const weekly = createRecurrence({
|
|
355
|
-
frequency: "weekly",
|
|
356
|
-
interval: 1,
|
|
357
|
-
startDate: new Date("2024-01-01"),
|
|
358
|
-
byWeekday: [1, 3, 5], // Monday, Wednesday, Friday
|
|
359
|
-
});
|
|
67
|
+
### Calculate
|
|
360
68
|
|
|
361
|
-
|
|
362
|
-
// "Every week on Monday, Wednesday, Friday"
|
|
69
|
+
Date arithmetic, differences, and business day calculations.
|
|
363
70
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
frequency: "monthly",
|
|
367
|
-
interval: 1,
|
|
368
|
-
startDate: new Date("2024-01-01"),
|
|
369
|
-
byMonthDay: [15],
|
|
370
|
-
until: new Date("2024-12-31"),
|
|
371
|
-
});
|
|
71
|
+
```ts
|
|
72
|
+
import { differenceInUnits, addTime, startOf, endOf } from 'ts-time-utils/calculate';
|
|
372
73
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
);
|
|
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
|
|
377
78
|
```
|
|
378
79
|
|
|
379
|
-
###
|
|
80
|
+
### Validate
|
|
81
|
+
|
|
82
|
+
Date validation, checks, and comparisons.
|
|
380
83
|
|
|
381
84
|
```ts
|
|
382
|
-
import {
|
|
383
|
-
createCountdown,
|
|
384
|
-
getRemainingTime,
|
|
385
|
-
formatCountdown,
|
|
386
|
-
} from "ts-time-utils/countdown";
|
|
387
|
-
|
|
388
|
-
// Create a countdown timer
|
|
389
|
-
const countdown = createCountdown(new Date("2024-12-31T23:59:59"), {
|
|
390
|
-
onTick: (remaining) => {
|
|
391
|
-
console.log(`${remaining.days}d ${remaining.hours}h ${remaining.minutes}m`);
|
|
392
|
-
},
|
|
393
|
-
onComplete: () => {
|
|
394
|
-
console.log("Happy New Year!");
|
|
395
|
-
},
|
|
396
|
-
interval: 1000, // Update every second
|
|
397
|
-
});
|
|
85
|
+
import { isValidDate, isLeapYear, isWeekend, isSameDay } from 'ts-time-utils/validate';
|
|
398
86
|
|
|
399
|
-
|
|
400
|
-
//
|
|
401
|
-
|
|
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
|
|
91
|
+
```
|
|
402
92
|
|
|
403
|
-
|
|
404
|
-
const remaining = getRemainingTime(new Date("2024-12-31"));
|
|
405
|
-
console.log(`${remaining.days} days, ${remaining.hours} hours remaining`);
|
|
93
|
+
### Duration
|
|
406
94
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
});
|
|
412
|
-
// "45d 12h 30m"
|
|
95
|
+
Immutable Duration class with arithmetic operations.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { Duration } from 'ts-time-utils/duration';
|
|
413
99
|
|
|
414
|
-
|
|
415
|
-
|
|
100
|
+
const d1 = Duration.fromHours(2.5);
|
|
101
|
+
const d2 = Duration.fromString('1h 30m 45s');
|
|
102
|
+
const d3 = Duration.between(startDate, endDate);
|
|
416
103
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
new Date("2024-07-01")
|
|
421
|
-
);
|
|
422
|
-
console.log(`${progress}% complete`); // ~50%
|
|
104
|
+
d1.add(d2).toString(); // "4h 0m 45s"
|
|
105
|
+
d1.greaterThan(d2); // true
|
|
106
|
+
d1.multiply(2).hours; // 5
|
|
423
107
|
```
|
|
424
108
|
|
|
425
|
-
###
|
|
109
|
+
### Chain API
|
|
110
|
+
|
|
111
|
+
Fluent chainable API for date operations.
|
|
426
112
|
|
|
427
113
|
```ts
|
|
428
|
-
import {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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
|
|
126
|
+
```
|
|
434
127
|
|
|
435
|
-
|
|
436
|
-
const ranges = [
|
|
437
|
-
{ start: new Date("2024-01-01"), end: new Date("2024-01-10") },
|
|
438
|
-
{ start: new Date("2024-01-05"), end: new Date("2024-01-15") },
|
|
439
|
-
{ start: new Date("2024-01-20"), end: new Date("2024-01-25") },
|
|
440
|
-
];
|
|
128
|
+
### Timezone
|
|
441
129
|
|
|
442
|
-
|
|
443
|
-
// [
|
|
444
|
-
// { start: Date('2024-01-01'), end: Date('2024-01-15') },
|
|
445
|
-
// { start: Date('2024-01-20'), end: Date('2024-01-25') }
|
|
446
|
-
// ]
|
|
130
|
+
Timezone conversions, DST handling, and zone comparisons.
|
|
447
131
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
{ start: new Date("2024-01-01T09:00"), end: new Date("2024-01-01T11:00") },
|
|
451
|
-
{ start: new Date("2024-01-01T14:00"), end: new Date("2024-01-01T16:00") },
|
|
452
|
-
];
|
|
132
|
+
```ts
|
|
133
|
+
import { formatInTimeZone, isDST, convertTimezone } from 'ts-time-utils/timezone';
|
|
453
134
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
});
|
|
458
|
-
// Returns available time slots
|
|
459
|
-
|
|
460
|
-
// Split into chunks
|
|
461
|
-
const range = {
|
|
462
|
-
start: new Date("2024-01-01"),
|
|
463
|
-
end: new Date("2024-01-31"),
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
const weeks = splitRange(range, 1, "week");
|
|
467
|
-
// Splits January into weekly chunks
|
|
468
|
-
|
|
469
|
-
// Check overlap
|
|
470
|
-
const overlap = dateRangeOverlap(
|
|
471
|
-
{ start: new Date("2024-01-01"), end: new Date("2024-01-15") },
|
|
472
|
-
{ start: new Date("2024-01-10"), end: new Date("2024-01-20") }
|
|
473
|
-
); // true
|
|
135
|
+
formatInTimeZone(date, 'America/New_York');
|
|
136
|
+
isDST(new Date('2025-07-14'), 'America/New_York'); // true
|
|
137
|
+
convertTimezone(date, 'UTC', 'Asia/Tokyo');
|
|
474
138
|
```
|
|
475
139
|
|
|
476
|
-
###
|
|
140
|
+
### Calendar
|
|
141
|
+
|
|
142
|
+
ISO weeks, quarters, holidays, and calendar grids.
|
|
477
143
|
|
|
478
144
|
```ts
|
|
479
|
-
import {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
// Parse natural language dates
|
|
486
|
-
parseNaturalDate("tomorrow at 3pm");
|
|
487
|
-
// Returns Date for tomorrow at 15:00
|
|
488
|
-
|
|
489
|
-
parseNaturalDate("next Friday");
|
|
490
|
-
// Returns Date for next Friday
|
|
491
|
-
|
|
492
|
-
parseNaturalDate("in 2 weeks");
|
|
493
|
-
// Returns Date 2 weeks from now
|
|
494
|
-
|
|
495
|
-
parseNaturalDate("3 days ago");
|
|
496
|
-
// Returns Date 3 days ago
|
|
497
|
-
|
|
498
|
-
// Extract dates from text
|
|
499
|
-
const text = "Meeting tomorrow at 3pm and lunch next Friday at noon";
|
|
500
|
-
const dates = extractDatesFromText(text);
|
|
501
|
-
// [
|
|
502
|
-
// { date: Date(...), text: 'tomorrow at 3pm', index: 8, confidence: 0.9 },
|
|
503
|
-
// { date: Date(...), text: 'next Friday at noon', index: 35, confidence: 0.85 }
|
|
504
|
-
// ]
|
|
505
|
-
|
|
506
|
-
// Context-aware suggestions
|
|
507
|
-
const suggestions = suggestDateFromContext("deadline is end of month");
|
|
508
|
-
// [{ date: Date(last day of current month), text: 'end of month', confidence: 0.85 }]
|
|
509
|
-
|
|
510
|
-
// Supported phrases:
|
|
511
|
-
// - "tomorrow", "yesterday", "today"
|
|
512
|
-
// - "next Monday", "last Friday"
|
|
513
|
-
// - "in 2 hours", "5 days ago"
|
|
514
|
-
// - "end of month/week/year" (or EOM/EOW/EOY)
|
|
515
|
-
// - "beginning of month/year"
|
|
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
|
|
516
151
|
```
|
|
517
152
|
|
|
518
|
-
###
|
|
153
|
+
### Date Range
|
|
154
|
+
|
|
155
|
+
Date range operations: overlap, gaps, merge, split.
|
|
519
156
|
|
|
520
157
|
```ts
|
|
521
|
-
import {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const duration4 = Duration.between(startDate, endDate); // From date range
|
|
532
|
-
|
|
533
|
-
// Arithmetic operations
|
|
534
|
-
const sum = duration1.add(duration2); // 4 hours
|
|
535
|
-
const diff = duration1.subtract(duration2); // 1 hour
|
|
536
|
-
const doubled = duration1.multiply(2); // 5 hours
|
|
537
|
-
const half = duration1.divide(2); // 1.25 hours
|
|
538
|
-
|
|
539
|
-
// Comparisons
|
|
540
|
-
duration1.equals(duration2); // false
|
|
541
|
-
duration1.greaterThan(duration2); // true
|
|
542
|
-
duration1.compareTo(duration2); // 1
|
|
543
|
-
|
|
544
|
-
// Conversions and formatting
|
|
545
|
-
duration1.hours; // 2.5
|
|
546
|
-
duration1.minutes; // 150
|
|
547
|
-
duration1.toString(); // "2h 30m"
|
|
548
|
-
formatDurationString(duration1, { long: true }); // "2 hours, 30 minutes"
|
|
549
|
-
|
|
550
|
-
// Utility functions with arrays
|
|
551
|
-
const durations = [duration1, duration2, duration3];
|
|
552
|
-
const max = maxDuration(...durations);
|
|
553
|
-
const total = sumDurations(...durations);
|
|
554
|
-
const average = averageDuration(...durations);
|
|
158
|
+
import { mergeDateRanges, findGaps, dateRangeOverlap } from 'ts-time-utils/dateRange';
|
|
159
|
+
|
|
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
|
+
];
|
|
164
|
+
|
|
165
|
+
mergeDateRanges(ranges); // Merged into single range
|
|
166
|
+
findGaps(busyTimes, workday); // Available time slots
|
|
167
|
+
dateRangeOverlap(range1, range2); // true/false
|
|
555
168
|
```
|
|
556
169
|
|
|
557
|
-
###
|
|
170
|
+
### Recurrence
|
|
171
|
+
|
|
172
|
+
RRULE-inspired recurring event patterns.
|
|
558
173
|
|
|
559
174
|
```ts
|
|
560
|
-
import {
|
|
561
|
-
serializeDate,
|
|
562
|
-
deserializeDate,
|
|
563
|
-
parseJSONWithDates,
|
|
564
|
-
stringifyWithDates,
|
|
565
|
-
toEpochTimestamp,
|
|
566
|
-
fromEpochTimestamp,
|
|
567
|
-
toDateObject,
|
|
568
|
-
fromDateObject,
|
|
569
|
-
} from "ts-time-utils/serialize";
|
|
570
|
-
|
|
571
|
-
// Serialize dates in different formats
|
|
572
|
-
const date = new Date("2025-09-14T12:30:45.123Z");
|
|
573
|
-
|
|
574
|
-
const isoString = serializeDate(date, { format: "iso" }); // "2025-09-14T12:30:45.123Z"
|
|
575
|
-
const epochMs = serializeDate(date, { format: "epoch" }); // 1757853045123
|
|
576
|
-
const dateObj = serializeDate(date, { format: "object" }); // {year: 2025, month: 9, ...}
|
|
577
|
-
const custom = serializeDate(date, {
|
|
578
|
-
format: "custom",
|
|
579
|
-
customFormat: "YYYY-MM-DD HH:mm:ss",
|
|
580
|
-
}); // "2025-09-14 12:30:45"
|
|
581
|
-
|
|
582
|
-
// Deserialize from various formats
|
|
583
|
-
const fromISO = deserializeDate("2025-09-14T12:30:45.123Z");
|
|
584
|
-
const fromEpoch = deserializeDate(1757853045123);
|
|
585
|
-
const fromObj = deserializeDate({
|
|
586
|
-
year: 2025,
|
|
587
|
-
month: 9,
|
|
588
|
-
day: 14,
|
|
589
|
-
hour: 12,
|
|
590
|
-
minute: 30,
|
|
591
|
-
second: 45,
|
|
592
|
-
millisecond: 123,
|
|
593
|
-
});
|
|
175
|
+
import { createRecurrence, recurrenceToString } from 'ts-time-utils/recurrence';
|
|
594
176
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
metadata: "other data",
|
|
601
|
-
};
|
|
602
|
-
|
|
603
|
-
// Stringify with automatic date serialization
|
|
604
|
-
const jsonString = stringifyWithDates(data, ["createdAt", "updatedAt"], {
|
|
605
|
-
format: "epoch",
|
|
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
|
|
606
182
|
});
|
|
607
|
-
// {"name":"User","createdAt":1757853045123,"updatedAt":1757853045123,"metadata":"other data"}
|
|
608
183
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
//
|
|
184
|
+
weekly.getNextOccurrence(new Date());
|
|
185
|
+
weekly.getAllOccurrences();
|
|
186
|
+
recurrenceToString(weekly.rule); // "Every week on Monday, Wednesday, Friday"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Cron
|
|
190
|
+
|
|
191
|
+
Parse and match cron expressions.
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import { matchesCron, getNextCronDate, describeCron, CRON_PRESETS } from 'ts-time-utils/cron';
|
|
195
|
+
|
|
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 * * *"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Fiscal Year
|
|
612
203
|
|
|
613
|
-
|
|
614
|
-
const timestamp = toEpochTimestamp(date, "seconds"); // 1757853045
|
|
615
|
-
const restoredDate = fromEpochTimestamp(timestamp, "seconds");
|
|
204
|
+
Fiscal year utilities with configurable start month.
|
|
616
205
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
206
|
+
```ts
|
|
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
|
|
620
213
|
```
|
|
621
214
|
|
|
622
|
-
###
|
|
215
|
+
### Compare & Sort
|
|
216
|
+
|
|
217
|
+
Sort, group, and analyze date arrays.
|
|
623
218
|
|
|
624
219
|
```ts
|
|
625
|
-
import {
|
|
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
|
|
226
|
+
```
|
|
626
227
|
|
|
627
|
-
|
|
628
|
-
formatDuration(65000); // "1 minute, 5 seconds"
|
|
629
|
-
formatDuration(65000, { short: true }); // "1m 5s"
|
|
630
|
-
formatDuration(90061000, { maxUnits: 2 }); // "1 day, 1 hour"
|
|
228
|
+
### Iterate
|
|
631
229
|
|
|
632
|
-
|
|
633
|
-
timeAgo(new Date(Date.now() - 60000)); // "1 minute ago"
|
|
634
|
-
timeAgo(new Date(Date.now() + 60000)); // "in 1 minute"
|
|
230
|
+
Iterate through date sequences and count dates.
|
|
635
231
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
232
|
+
```ts
|
|
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
|
|
639
239
|
```
|
|
640
240
|
|
|
641
|
-
###
|
|
241
|
+
### Natural Language
|
|
242
|
+
|
|
243
|
+
Parse human-friendly date strings.
|
|
642
244
|
|
|
643
245
|
```ts
|
|
644
|
-
import {
|
|
246
|
+
import { parseNaturalDate, extractDatesFromText } from 'ts-time-utils/naturalLanguage';
|
|
645
247
|
|
|
646
|
-
|
|
647
|
-
|
|
248
|
+
parseNaturalDate('tomorrow');
|
|
249
|
+
parseNaturalDate('next Friday');
|
|
250
|
+
parseNaturalDate('in 2 weeks');
|
|
251
|
+
parseNaturalDate('end of month');
|
|
648
252
|
|
|
649
|
-
|
|
650
|
-
|
|
253
|
+
extractDatesFromText('Meeting tomorrow at 3pm');
|
|
254
|
+
// [{ date: Date, text: 'tomorrow at 3pm', confidence: 0.9 }]
|
|
651
255
|
```
|
|
652
256
|
|
|
653
|
-
###
|
|
257
|
+
### International Holidays
|
|
258
|
+
|
|
259
|
+
Public holidays for 20 countries.
|
|
654
260
|
|
|
655
261
|
```ts
|
|
656
|
-
import {
|
|
262
|
+
import { getHolidays, isHoliday, getNextHoliday } from 'ts-time-utils/holidays';
|
|
657
263
|
|
|
658
|
-
//
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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,
|
|
270
|
+
// JP, FR, BR, MX, KR, SG, PL, SE, BE, CH
|
|
662
271
|
```
|
|
663
272
|
|
|
664
|
-
###
|
|
273
|
+
### Locale
|
|
274
|
+
|
|
275
|
+
Multi-language formatting with 40+ locales.
|
|
665
276
|
|
|
666
277
|
```ts
|
|
667
|
-
import {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
// Age calculations
|
|
675
|
-
calculateAge(new Date("1990-05-15")); // { years: 34, months: 4, days: 2 }
|
|
676
|
-
getLifeStage(25); // "adult"
|
|
677
|
-
getNextBirthday(new Date("1990-05-15")); // Next May 15th
|
|
678
|
-
isBirthday(new Date("1990-05-15"), new Date("2025-05-15")); // true
|
|
278
|
+
import { formatRelativeTime, formatDateLocale, detectLocale } from 'ts-time-utils/locale';
|
|
279
|
+
|
|
280
|
+
formatRelativeTime(pastDate, { locale: 'es' }); // "hace 2 horas"
|
|
281
|
+
formatRelativeTime(pastDate, { locale: 'de' }); // "vor 2 Stunden"
|
|
282
|
+
formatDateLocale(date, 'fr', 'long'); // "15 janvier 2024"
|
|
283
|
+
detectLocale(); // Auto-detect system locale
|
|
679
284
|
```
|
|
680
285
|
|
|
681
|
-
###
|
|
286
|
+
### Working Hours
|
|
287
|
+
|
|
288
|
+
Business hours calculations with break support.
|
|
682
289
|
|
|
683
290
|
```ts
|
|
684
|
-
import {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
} from "ts-time-utils/calendar";
|
|
690
|
-
|
|
691
|
-
// Calendar operations
|
|
692
|
-
getWeekNumber(new Date("2025-01-15")); // 3
|
|
693
|
-
getQuarter(new Date("2025-07-15")); // 3
|
|
694
|
-
getEaster(2025); // Date object for Easter Sunday 2025
|
|
695
|
-
getDaysInMonth(2, 2024); // 29 (leap year)
|
|
291
|
+
import { isWorkingTime, addWorkingDays, workingDaysBetween } from 'ts-time-utils/workingHours';
|
|
292
|
+
|
|
293
|
+
isWorkingTime(date, config);
|
|
294
|
+
addWorkingDays(date, 5, config);
|
|
295
|
+
workingDaysBetween(start, end, config);
|
|
696
296
|
```
|
|
697
297
|
|
|
698
|
-
###
|
|
298
|
+
### Serialization
|
|
299
|
+
|
|
300
|
+
Safe JSON date serialization and deserialization.
|
|
699
301
|
|
|
700
302
|
```ts
|
|
701
|
-
import {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
parseDate("2025-02-30"); // null (invalid date)
|
|
709
|
-
parseDate("Dec 25, 2025"); // Date object
|
|
710
|
-
parseRelativeDate("tomorrow"); // Date for tomorrow
|
|
711
|
-
parseCustomFormat("25/12/2025", "DD/MM/YYYY"); // Date object
|
|
303
|
+
import { serializeDate, parseJSONWithDates, stringifyWithDates } from 'ts-time-utils/serialize';
|
|
304
|
+
|
|
305
|
+
serializeDate(date, { format: 'iso' }); // "2025-09-14T12:30:45.123Z"
|
|
306
|
+
serializeDate(date, { format: 'epoch' }); // 1757853045123
|
|
307
|
+
|
|
308
|
+
const json = stringifyWithDates(data, ['createdAt']);
|
|
309
|
+
const parsed = parseJSONWithDates(json, ['createdAt']);
|
|
712
310
|
```
|
|
713
311
|
|
|
714
|
-
### Performance
|
|
312
|
+
### Performance
|
|
313
|
+
|
|
314
|
+
Async utilities, benchmarking, and timing.
|
|
715
315
|
|
|
716
316
|
```ts
|
|
717
|
-
import {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
debounce,
|
|
723
|
-
} from "ts-time-utils/performance";
|
|
724
|
-
|
|
725
|
-
// Async utilities
|
|
726
|
-
await sleep(1000); // Wait 1 second
|
|
727
|
-
await timeout(promise, 5000); // Timeout after 5 seconds
|
|
728
|
-
|
|
729
|
-
// Performance measurement
|
|
730
|
-
const result = await benchmark(() => heavyOperation(), 10); // Run 10 times
|
|
317
|
+
import { sleep, benchmark, Stopwatch, debounce } from 'ts-time-utils/performance';
|
|
318
|
+
|
|
319
|
+
await sleep(1000);
|
|
320
|
+
await benchmark(() => heavyOperation(), 10);
|
|
321
|
+
|
|
731
322
|
const stopwatch = new Stopwatch();
|
|
732
323
|
stopwatch.start();
|
|
733
324
|
// ... operations
|
|
734
|
-
|
|
325
|
+
stopwatch.getElapsed();
|
|
735
326
|
|
|
736
|
-
|
|
737
|
-
const debouncedFn = debounce(() => console.log("Called!"), 300);
|
|
327
|
+
const debouncedFn = debounce(fn, 300);
|
|
738
328
|
```
|
|
739
329
|
|
|
740
|
-
###
|
|
330
|
+
### Age
|
|
331
|
+
|
|
332
|
+
Age calculations and birthday utilities.
|
|
741
333
|
|
|
742
334
|
```ts
|
|
743
|
-
import {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
const a = createInterval("2025-01-01", "2025-01-05");
|
|
750
|
-
const b = createInterval("2025-01-04", "2025-01-10");
|
|
751
|
-
intervalsOverlap(a!, b!); // true
|
|
752
|
-
const merged = mergeIntervals([a!, b!]);
|
|
335
|
+
import { calculateAge, getLifeStage, getNextBirthday } from 'ts-time-utils/age';
|
|
336
|
+
|
|
337
|
+
calculateAge(new Date('1990-05-15')); // { years: 34, months: 4, days: 2 }
|
|
338
|
+
getLifeStage(25); // "adult"
|
|
339
|
+
getNextBirthday(birthDate); // Next birthday date
|
|
753
340
|
```
|
|
754
341
|
|
|
755
|
-
###
|
|
342
|
+
### Countdown
|
|
343
|
+
|
|
344
|
+
Timer and countdown utilities.
|
|
756
345
|
|
|
757
346
|
```ts
|
|
758
|
-
import {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
347
|
+
import { createCountdown, getRemainingTime, formatCountdown } from 'ts-time-utils/countdown';
|
|
348
|
+
|
|
349
|
+
const countdown = createCountdown(targetDate, {
|
|
350
|
+
onTick: (remaining) => console.log(remaining.days, 'd'),
|
|
351
|
+
onComplete: () => console.log('Done!'),
|
|
762
352
|
});
|
|
763
|
-
|
|
353
|
+
countdown.start();
|
|
354
|
+
|
|
355
|
+
getRemainingTime(targetDate); // { days, hours, minutes, seconds }
|
|
356
|
+
formatCountdown(targetDate, { units: ['days', 'hours'] }); // "45d 12h"
|
|
764
357
|
```
|
|
765
358
|
|
|
766
|
-
###
|
|
359
|
+
### Interval
|
|
360
|
+
|
|
361
|
+
Time interval operations.
|
|
767
362
|
|
|
768
363
|
```ts
|
|
769
|
-
import {
|
|
364
|
+
import { createInterval, intervalsOverlap, mergeIntervals } from 'ts-time-utils/interval';
|
|
770
365
|
|
|
771
|
-
|
|
772
|
-
|
|
366
|
+
const a = createInterval('2025-01-01', '2025-01-05');
|
|
367
|
+
const b = createInterval('2025-01-04', '2025-01-10');
|
|
368
|
+
intervalsOverlap(a, b); // true
|
|
369
|
+
mergeIntervals([a, b]); // Single merged interval
|
|
773
370
|
```
|
|
774
371
|
|
|
775
|
-
### Range
|
|
372
|
+
### Range Presets
|
|
373
|
+
|
|
374
|
+
Common date range presets.
|
|
776
375
|
|
|
777
376
|
```ts
|
|
778
|
-
import { lastNDays, thisWeek,
|
|
377
|
+
import { today, lastNDays, thisWeek, thisMonth } from 'ts-time-utils/rangePresets';
|
|
779
378
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
379
|
+
today(); // { start, end } for today
|
|
380
|
+
lastNDays(7); // Last 7 days
|
|
381
|
+
thisWeek(); // Current week
|
|
382
|
+
thisMonth(); // Current month
|
|
783
383
|
```
|
|
784
384
|
|
|
785
|
-
###
|
|
385
|
+
### Non-Gregorian Calendars
|
|
386
|
+
|
|
387
|
+
Convert dates between calendar systems using Intl.DateTimeFormat.
|
|
786
388
|
|
|
787
389
|
```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
|
-
```
|
|
390
|
+
import { toHebrewDate, toIslamicDate, toJapaneseDate, getChineseZodiac } from 'ts-time-utils/calendars';
|
|
830
391
|
|
|
831
|
-
|
|
392
|
+
toHebrewDate(new Date()); // { year: 5785, month: 4, day: 23, calendar: 'hebrew' }
|
|
393
|
+
toIslamicDate(new Date()); // { year: 1446, month: 7, day: 1, calendar: 'islamic-umalqura' }
|
|
394
|
+
toJapaneseDate(new Date()); // { year: 6, era: 'Reiwa', calendar: 'japanese' }
|
|
395
|
+
getChineseZodiac(2024); // 'Dragon'
|
|
832
396
|
|
|
833
|
-
|
|
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, ... }
|
|
397
|
+
// Supported: Hebrew, Islamic, Buddhist, Japanese, Persian, Chinese
|
|
871
398
|
```
|
|
872
399
|
|
|
873
|
-
###
|
|
400
|
+
### Temporal API Compatibility
|
|
401
|
+
|
|
402
|
+
Future-proof with Temporal-like objects that work with native Date.
|
|
874
403
|
|
|
875
404
|
```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
|
-
];
|
|
405
|
+
import { toPlainDate, toPlainDateTime, toZonedDateTime, toInstant } from 'ts-time-utils/temporal';
|
|
893
406
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
407
|
+
const date = toPlainDate(2024, 3, 25);
|
|
408
|
+
date.add({ days: 7 }); // PlainDate
|
|
409
|
+
date.until(otherDate); // Duration
|
|
410
|
+
date.dayOfWeek; // 1 (Monday, ISO)
|
|
897
411
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
medianDate(dates); // Mar 15, 2024
|
|
412
|
+
const zdt = toZonedDateTime(new Date(), 'America/New_York');
|
|
413
|
+
zdt.hour; // Hour in that timezone
|
|
414
|
+
zdt.toInstant(); // Epoch-based Instant
|
|
902
415
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
416
|
+
const instant = toInstant(Date.now());
|
|
417
|
+
instant.toZonedDateTime('UTC'); // Convert to any timezone
|
|
418
|
+
```
|
|
906
419
|
|
|
907
|
-
|
|
908
|
-
uniqueDates([date1, date1Copy, date2]); // [date1, date2]
|
|
909
|
-
uniqueDates(dates, "day"); // Unique by day precision
|
|
420
|
+
### High-Precision Utilities
|
|
910
421
|
|
|
911
|
-
|
|
912
|
-
groupDatesByMonth(dates);
|
|
913
|
-
// Map { "2024-01" => [Jan 10], "2024-03" => [Mar 15], "2024-06" => [Jun 20] }
|
|
422
|
+
Nanosecond timestamps, BigInt support, DST handling, and leap seconds.
|
|
914
423
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
424
|
+
```ts
|
|
425
|
+
import {
|
|
426
|
+
createNanosecondTimestamp, nowNanoseconds,
|
|
427
|
+
toBigIntMs, ValidDate, isInDSTGap, leapSecondsBetween
|
|
428
|
+
} from 'ts-time-utils/precision';
|
|
918
429
|
|
|
919
|
-
//
|
|
920
|
-
|
|
921
|
-
|
|
430
|
+
// Nanosecond precision
|
|
431
|
+
const ts = createNanosecondTimestamp(Date.now(), 500000);
|
|
432
|
+
ts.totalNanoseconds; // BigInt
|
|
922
433
|
|
|
923
|
-
|
|
434
|
+
// BigInt timestamps for large date ranges
|
|
435
|
+
toBigIntMs(new Date()); // BigInt milliseconds
|
|
924
436
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
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
|
|
437
|
+
// DST transition detection
|
|
438
|
+
isInDSTGap(new Date('2024-03-10T02:30:00'));
|
|
439
|
+
|
|
440
|
+
// Validated dates (never invalid)
|
|
441
|
+
const valid = ValidDate.from(date); // Throws if invalid
|
|
442
|
+
const maybe = ValidDate.tryFrom(date); // Returns null if invalid
|
|
443
|
+
|
|
444
|
+
// Leap second awareness
|
|
445
|
+
leapSecondsBetween(date1, date2); // Number of leap seconds
|
|
963
446
|
```
|
|
964
447
|
|
|
965
|
-
###
|
|
448
|
+
### Parse
|
|
966
449
|
|
|
967
|
-
|
|
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
|
-
});
|
|
450
|
+
Date parsing from various formats.
|
|
1008
451
|
|
|
1009
|
-
|
|
1010
|
-
|
|
452
|
+
```ts
|
|
453
|
+
import { parseDate, parseTime, autoDetectFormat } from 'ts-time-utils/parse';
|
|
1011
454
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
const esHolidays = getHolidays(2024, "ES"); // Spanish holidays (includes Constitution Day)
|
|
455
|
+
parseDate('Dec 25, 2025');
|
|
456
|
+
parseDate('25/12/2025', 'DD/MM/YYYY');
|
|
457
|
+
parseTime('2:30 PM'); // { hour: 14, minute: 30 }
|
|
458
|
+
autoDetectFormat('2025-09-14'); // 'YYYY-MM-DD'
|
|
1017
459
|
```
|
|
1018
460
|
|
|
1019
|
-
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Plugin System
|
|
464
|
+
|
|
465
|
+
Extend ChainedDate with custom functionality.
|
|
1020
466
|
|
|
1021
467
|
```ts
|
|
1022
|
-
import {
|
|
1023
|
-
formatRelativeTime,
|
|
1024
|
-
formatDateLocale,
|
|
1025
|
-
formatTimeLocale,
|
|
1026
|
-
formatDateTimeLocale,
|
|
1027
|
-
registerLocale,
|
|
1028
|
-
getLocaleConfig,
|
|
1029
|
-
detectLocale,
|
|
1030
|
-
getSupportedLocales,
|
|
1031
|
-
} from "ts-time-utils/locale";
|
|
1032
|
-
|
|
1033
|
-
// Relative time formatting in multiple languages
|
|
1034
|
-
const pastDate = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
|
|
1035
|
-
formatRelativeTime(pastDate, { locale: "en" }); // "2 hours ago"
|
|
1036
|
-
formatRelativeTime(pastDate, { locale: "es" }); // "hace 2 horas"
|
|
1037
|
-
formatRelativeTime(pastDate, { locale: "fr" }); // "il y a 2 heures"
|
|
1038
|
-
formatRelativeTime(pastDate, { locale: "de" }); // "vor 2 Stunden"
|
|
1039
|
-
formatRelativeTime(pastDate, { locale: "nl" }); // "2 uur geleden"
|
|
1040
|
-
formatRelativeTime(pastDate, { locale: "it" }); // "2 ore fa"
|
|
1041
|
-
formatRelativeTime(pastDate, { locale: "zh" }); // "2ĺ°ćśĺ"
|
|
1042
|
-
formatRelativeTime(pastDate, { locale: "ja" }); // "2ćéĺ"
|
|
1043
|
-
formatRelativeTime(pastDate, { locale: "fa" }); // "2 ساؚت ŮžŰŘ´"
|
|
1044
|
-
|
|
1045
|
-
// Future dates
|
|
1046
|
-
const futureDate = new Date(Date.now() + 3 * 24 * 60 * 60 * 1000);
|
|
1047
|
-
formatRelativeTime(futureDate, { locale: "en" }); // "in 3 days"
|
|
1048
|
-
formatRelativeTime(futureDate, { locale: "es" }); // "en 3 dĂas"
|
|
1049
|
-
formatRelativeTime(futureDate, { locale: "nl" }); // "over 3 dagen"
|
|
1050
|
-
formatRelativeTime(futureDate, { locale: "it" }); // "tra 3 giorni"
|
|
1051
|
-
formatRelativeTime(futureDate, { locale: "fa" }); // "3 ŘąŮز ŘŻŰÚŻŘą"
|
|
1052
|
-
|
|
1053
|
-
// Relative time options
|
|
1054
|
-
formatRelativeTime(pastDate, {
|
|
1055
|
-
locale: "en",
|
|
1056
|
-
maxUnit: "days", // Don't use units larger than days
|
|
1057
|
-
minUnit: "minutes", // Don't use units smaller than minutes
|
|
1058
|
-
precision: 1, // Show 1 decimal place: "2.0 hours ago"
|
|
1059
|
-
short: true, // Use abbreviated format: "2h ago"
|
|
1060
|
-
numeric: "auto", // Use words when appropriate: "yesterday"
|
|
1061
|
-
});
|
|
468
|
+
import { chain, registerPlugin, createPlugin } from 'ts-time-utils/chain';
|
|
1062
469
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
formatDateLocale(date, "fr", "long"); // "15 janvier 2024"
|
|
1068
|
-
formatDateLocale(date, "de", "short"); // "15.1.2024"
|
|
1069
|
-
|
|
1070
|
-
// Time formatting
|
|
1071
|
-
formatTimeLocale(date, "en", "short"); // "2:30 PM"
|
|
1072
|
-
formatTimeLocale(date, "de", "medium"); // "14:30:45"
|
|
1073
|
-
formatTimeLocale(date, "fr", "long"); // "14:30:45 UTC"
|
|
1074
|
-
|
|
1075
|
-
// Combined date and time
|
|
1076
|
-
formatDateTimeLocale(date, "en"); // "Jan 15, 2024 2:30:45 PM"
|
|
1077
|
-
|
|
1078
|
-
// Auto-detect locale from browser/system
|
|
1079
|
-
const userLocale = detectLocale(); // e.g., 'en-US' or 'fr-FR'
|
|
1080
|
-
formatRelativeTime(pastDate, { locale: userLocale });
|
|
1081
|
-
|
|
1082
|
-
// Get supported locales
|
|
1083
|
-
const locales = getSupportedLocales();
|
|
1084
|
-
// ['en', 'es', 'fr', 'de', 'zh', 'ja', ...]
|
|
1085
|
-
|
|
1086
|
-
// Register custom locale
|
|
1087
|
-
registerLocale("custom", {
|
|
1088
|
-
locale: "custom",
|
|
1089
|
-
dateFormats: {
|
|
1090
|
-
short: "M/d/yyyy",
|
|
1091
|
-
medium: "MMM d, yyyy",
|
|
1092
|
-
long: "MMMM d, yyyy",
|
|
1093
|
-
full: "EEEE, MMMM d, yyyy",
|
|
1094
|
-
},
|
|
1095
|
-
timeFormats: {
|
|
1096
|
-
short: "h:mm a",
|
|
1097
|
-
medium: "h:mm:ss a",
|
|
1098
|
-
long: "h:mm:ss a z",
|
|
1099
|
-
full: "h:mm:ss a zzzz",
|
|
1100
|
-
},
|
|
1101
|
-
relativeTime: {
|
|
1102
|
-
future: "in {0}",
|
|
1103
|
-
past: "{0} ago",
|
|
1104
|
-
units: {
|
|
1105
|
-
second: "sec",
|
|
1106
|
-
seconds: "secs",
|
|
1107
|
-
minute: "min",
|
|
1108
|
-
minutes: "mins",
|
|
1109
|
-
hour: "hr",
|
|
1110
|
-
hours: "hrs",
|
|
1111
|
-
day: "day",
|
|
1112
|
-
days: "days",
|
|
1113
|
-
week: "wk",
|
|
1114
|
-
weeks: "wks",
|
|
1115
|
-
month: "mo",
|
|
1116
|
-
months: "mos",
|
|
1117
|
-
year: "yr",
|
|
1118
|
-
years: "yrs",
|
|
1119
|
-
},
|
|
1120
|
-
},
|
|
1121
|
-
calendar: {
|
|
1122
|
-
weekStartsOn: 0, // Sunday
|
|
1123
|
-
monthNames: ["Jan", "Feb", "Mar" /* ... */],
|
|
1124
|
-
monthNamesShort: ["J", "F", "M" /* ... */],
|
|
1125
|
-
dayNames: ["Sun", "Mon", "Tue" /* ... */],
|
|
1126
|
-
dayNamesShort: ["S", "M", "T" /* ... */],
|
|
1127
|
-
},
|
|
1128
|
-
numbers: {
|
|
1129
|
-
decimal: ".",
|
|
1130
|
-
thousands: ",",
|
|
470
|
+
const businessPlugin = createPlugin('business', {
|
|
471
|
+
addBusinessDays(days: number) {
|
|
472
|
+
// Implementation
|
|
473
|
+
return this;
|
|
1131
474
|
},
|
|
475
|
+
isBusinessDay() {
|
|
476
|
+
const day = this.toDate().getDay();
|
|
477
|
+
return day !== 0 && day !== 6;
|
|
478
|
+
}
|
|
1132
479
|
});
|
|
1133
480
|
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
convertFormattedDate,
|
|
1140
|
-
convertRelativeTimeArray,
|
|
1141
|
-
compareLocaleFormats,
|
|
1142
|
-
} from "ts-time-utils/locale";
|
|
1143
|
-
|
|
1144
|
-
// Convert relative time between locales
|
|
1145
|
-
convertRelativeTime("2 hours ago", "en", "es"); // "hace 2 horas"
|
|
1146
|
-
convertRelativeTime("hace 3 dĂas", "es", "fr"); // "il y a 3 jours"
|
|
1147
|
-
convertRelativeTime("2h ago", "en", "de"); // "vor 2h"
|
|
1148
|
-
convertRelativeTime("2 hours ago", "en", "nl"); // "2 uur geleden"
|
|
1149
|
-
convertRelativeTime("2 hours ago", "en", "it"); // "2 ore fa"
|
|
1150
|
-
convertRelativeTime("2 hours ago", "en", "fa"); // "2 ساؚت ŮžŰŘ´"
|
|
1151
|
-
convertRelativeTime("2 ساؚت ŮžŰŘ´", "fa", "en"); // "2 hours ago"
|
|
1152
|
-
|
|
1153
|
-
// Detect locale from formatted text
|
|
1154
|
-
detectLocaleFromRelativeTime("2 hours ago"); // "en"
|
|
1155
|
-
detectLocaleFromRelativeTime("hace 2 horas"); // "es"
|
|
1156
|
-
detectLocaleFromRelativeTime("il y a 2 heures"); // "fr"
|
|
1157
|
-
detectLocaleFromRelativeTime("2 uur geleden"); // "nl"
|
|
1158
|
-
detectLocaleFromRelativeTime("2 ore fa"); // "it"
|
|
1159
|
-
detectLocaleFromRelativeTime("2 ساؚت ŮžŰŘ´"); // "fa"
|
|
1160
|
-
detectLocaleFromRelativeTime("vor 2 Stunden"); // "de"
|
|
1161
|
-
|
|
1162
|
-
// Convert date format patterns between locales
|
|
1163
|
-
convertFormatPattern("M/d/yyyy", "en", "de"); // "dd.MM.yyyy"
|
|
1164
|
-
convertFormatPattern("MMM d, yyyy", "en", "fr", "long"); // "d MMMM yyyy"
|
|
1165
|
-
|
|
1166
|
-
// Convert formatted dates between locales
|
|
1167
|
-
convertFormattedDate("Jan 15, 2024", "en", "es"); // "15 ene 2024"
|
|
1168
|
-
convertFormattedDate("15. Januar 2024", "de", "en"); // "Jan 15, 2024"
|
|
1169
|
-
|
|
1170
|
-
// Bulk conversion of relative time arrays
|
|
1171
|
-
const englishTimes = ["2 hours ago", "in 3 days", "1 week ago"];
|
|
1172
|
-
convertRelativeTimeArray(englishTimes, "en", "es");
|
|
1173
|
-
// ["hace 2 horas", "en 3 dĂas", "hace 1 semana"]
|
|
1174
|
-
|
|
1175
|
-
// Compare format differences between locales
|
|
1176
|
-
const comparison = compareLocaleFormats("en", "de");
|
|
1177
|
-
console.log(comparison.dateFormats.short);
|
|
1178
|
-
// { locale1: "M/d/yyyy", locale2: "dd.MM.yyyy" }
|
|
1179
|
-
console.log(comparison.weekStartsOn);
|
|
1180
|
-
// { locale1: 0, locale2: 1 } // Sunday vs Monday
|
|
481
|
+
registerPlugin(businessPlugin);
|
|
482
|
+
|
|
483
|
+
chain(new Date())
|
|
484
|
+
.addBusinessDays(5)
|
|
485
|
+
.isBusinessDay(); // true/false
|
|
1181
486
|
```
|
|
1182
487
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
-
|
|
1401
|
-
### Calculate Functions
|
|
1402
|
-
|
|
1403
|
-
- `differenceInUnits(date1, date2, unit?, precise?)` - Calculate difference between dates
|
|
1404
|
-
- `addTime(date, amount, unit)` - Add time to a date
|
|
1405
|
-
- `subtractTime(date, amount, unit)` - Subtract time from a date
|
|
1406
|
-
- `startOf(date, unit)` - Get start of time period
|
|
1407
|
-
- `endOf(date, unit)` - Get end of time period
|
|
1408
|
-
- `isBetween(date, start, end)` - Check if date is between two dates
|
|
1409
|
-
- `businessDaysBetween(start, end)` - Count business days between dates
|
|
1410
|
-
|
|
1411
|
-
### Validation Functions
|
|
1412
|
-
|
|
1413
|
-
- `isValidDate(date)` - Check if date is valid
|
|
1414
|
-
- `isLeapYear(year)` - Check if year is leap year
|
|
1415
|
-
- `isPast(date)` / `isFuture(date)` - Check if date is past/future
|
|
1416
|
-
- `isToday(date)` / `isYesterday(date)` / `isTomorrow(date)` - Date comparisons
|
|
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
|
|
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
|
|
1428
|
-
- `isValidTimeString(time)` - Validate HH:MM time format
|
|
1429
|
-
- `isValidISOString(dateString)` - Validate ISO 8601 date string
|
|
1430
|
-
|
|
1431
|
-
### Locale Functions
|
|
1432
|
-
|
|
1433
|
-
- `formatRelativeTime(date, options?)` - Format relative time with locale support
|
|
1434
|
-
- Options: `locale`, `maxUnit`, `minUnit`, `precision`, `short`, `numeric`, `style`
|
|
1435
|
-
- 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
|
|
1436
|
-
- `formatDateLocale(date, locale?, style?)` - Format date in locale-specific format
|
|
1437
|
-
- Styles: 'short', 'medium', 'long', 'full'
|
|
1438
|
-
- `formatTimeLocale(date, locale?, style?)` - Format time in locale-specific format
|
|
1439
|
-
- `formatDateTimeLocale(date, locale?, dateStyle?, timeStyle?)` - Format both date and time
|
|
1440
|
-
- `registerLocale(locale, config)` - Register a custom locale configuration
|
|
1441
|
-
- `getLocaleConfig(locale)` - Get configuration for a specific locale
|
|
1442
|
-
- `detectLocale(fallback?)` - Auto-detect system/browser locale
|
|
1443
|
-
- `getSupportedLocales()` - Get array of all supported locale codes
|
|
1444
|
-
- `getMonthNames(locale?, short?)` - Get localized month names
|
|
1445
|
-
- `getDayNames(locale?, short?)` - Get localized day names
|
|
1446
|
-
- `getBestMatchingLocale(preferences, fallback?)` - Find best matching locale from preferences
|
|
1447
|
-
|
|
1448
|
-
#### Locale Conversion Functions
|
|
1449
|
-
|
|
1450
|
-
- `convertRelativeTime(text, fromLocale, toLocale)` - Convert relative time between locales
|
|
1451
|
-
- Example: `convertRelativeTime("2 hours ago", "en", "es")` â `"hace 2 horas"`
|
|
1452
|
-
- Example: `convertRelativeTime("2 hours ago", "en", "nl")` â `"2 uur geleden"`
|
|
1453
|
-
- Example: `convertRelativeTime("2 hours ago", "en", "it")` â `"2 ore fa"`
|
|
1454
|
-
- Example: `convertRelativeTime("2 hours ago", "en", "fa")` â `"2 ساؚت ŮžŰŘ´"`
|
|
1455
|
-
- `detectLocaleFromRelativeTime(text)` - Detect locale from relative time string
|
|
1456
|
-
- Returns most likely locale or null if detection fails
|
|
1457
|
-
- `convertFormatPattern(pattern, fromLocale, toLocale, style?)` - Convert date format patterns
|
|
1458
|
-
- Maps common patterns between locales or uses target locale's style
|
|
1459
|
-
- `convertFormattedDate(formattedDate, fromLocale, toLocale, targetStyle?)` - Convert formatted dates
|
|
1460
|
-
- Parses date in source locale and reformats in target locale
|
|
1461
|
-
- `convertRelativeTimeArray(array, fromLocale, toLocale)` - Bulk convert relative time arrays
|
|
1462
|
-
- Returns array with same length, null for unparseable strings
|
|
1463
|
-
- `compareLocaleFormats(locale1, locale2)` - Compare format differences between locales
|
|
1464
|
-
- Returns object with dateFormats, timeFormats, and weekStartsOn comparisons
|
|
1465
|
-
|
|
1466
|
-
## đ ď¸ Development
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## API Reference
|
|
491
|
+
|
|
492
|
+
For complete API documentation, see the [Playground & Docs](https://ts-time-utils.h8frad.work).
|
|
493
|
+
|
|
494
|
+
### All Modules
|
|
495
|
+
|
|
496
|
+
| Module | Description |
|
|
497
|
+
|--------|-------------|
|
|
498
|
+
| `format` | Duration formatting, time ago, date patterns |
|
|
499
|
+
| `calculate` | Date arithmetic, differences, rounding |
|
|
500
|
+
| `validate` | Date validation, comparisons, type checks |
|
|
501
|
+
| `duration` | Immutable Duration class with arithmetic |
|
|
502
|
+
| `chain` | Fluent chainable API |
|
|
503
|
+
| `timezone` | Timezone conversions, DST handling |
|
|
504
|
+
| `calendar` | ISO weeks, quarters, holidays, grids |
|
|
505
|
+
| `calendars` | Non-Gregorian calendars (Hebrew, Islamic, etc.) |
|
|
506
|
+
| `temporal` | Temporal API compatibility layer |
|
|
507
|
+
| `precision` | Nanoseconds, BigInt, DST, leap seconds |
|
|
508
|
+
| `dateRange` | Range operations: overlap, gaps, merge |
|
|
509
|
+
| `recurrence` | RRULE-inspired recurring patterns |
|
|
510
|
+
| `cron` | Cron expression parsing and matching |
|
|
511
|
+
| `fiscal` | Fiscal year utilities |
|
|
512
|
+
| `compare` | Date sorting, grouping, statistics |
|
|
513
|
+
| `iterate` | Date iteration and counting |
|
|
514
|
+
| `naturalLanguage` | Natural language date parsing |
|
|
515
|
+
| `holidays` | International holidays (20 countries) |
|
|
516
|
+
| `locale` | Multi-language formatting (40+ locales) |
|
|
517
|
+
| `workingHours` | Business hours calculations |
|
|
518
|
+
| `serialize` | JSON date serialization |
|
|
519
|
+
| `performance` | Async utilities, benchmarking |
|
|
520
|
+
| `age` | Age calculations, birthdays |
|
|
521
|
+
| `countdown` | Timer and countdown utilities |
|
|
522
|
+
| `interval` | Time interval operations |
|
|
523
|
+
| `rangePresets` | Common date range presets |
|
|
524
|
+
| `parse` | Date parsing from various formats |
|
|
525
|
+
| `plugins` | Plugin system for extensions |
|
|
526
|
+
| `constants` | Time constants and types |
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## Development
|
|
1467
531
|
|
|
1468
532
|
```bash
|
|
1469
|
-
# Install dependencies
|
|
1470
|
-
npm
|
|
533
|
+
npm install # Install dependencies
|
|
534
|
+
npm run build # Build both CJS and ESM
|
|
535
|
+
npm test # Run tests
|
|
536
|
+
npm run lint # Lint code
|
|
537
|
+
```
|
|
1471
538
|
|
|
1472
|
-
|
|
1473
|
-
npm run build
|
|
539
|
+
## Releasing
|
|
1474
540
|
|
|
1475
|
-
|
|
1476
|
-
npm test
|
|
541
|
+
Releases are automated via GitHub Actions with npm trusted publishing (OIDC).
|
|
1477
542
|
|
|
1478
|
-
|
|
1479
|
-
npm run test:watch
|
|
543
|
+
**To release a new version:**
|
|
1480
544
|
|
|
1481
|
-
|
|
1482
|
-
|
|
545
|
+
```bash
|
|
546
|
+
git tag v4.0.1 # Create tag (use semantic versioning)
|
|
547
|
+
git push --tags # Push tag â triggers publish workflow
|
|
1483
548
|
```
|
|
1484
549
|
|
|
1485
|
-
|
|
550
|
+
The workflow automatically:
|
|
551
|
+
1. Sets `package.json` version from tag
|
|
552
|
+
2. Runs lint, tests, and build
|
|
553
|
+
3. Publishes to npm with provenance
|
|
554
|
+
|
|
555
|
+
**Version format:** Tags must match `v*` pattern (e.g., `v4.0.0`, `v4.1.0-beta.1`)
|
|
556
|
+
|
|
557
|
+
## License
|
|
1486
558
|
|
|
1487
559
|
MIT
|