ts-time-utils 4.1.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -31
- package/dist/{age.js → age.cjs} +14 -6
- package/dist/{calculate.js → calculate.cjs} +30 -18
- package/dist/{calendar.js → calendar.cjs} +80 -39
- package/dist/{calendars.js → calendars.cjs} +48 -23
- package/dist/{chain.js → chain.cjs} +41 -40
- package/dist/{compare.js → compare.cjs} +58 -28
- package/dist/constants.cjs +19 -0
- package/dist/{countdown.js → countdown.cjs} +16 -7
- package/dist/{cron.js → cron.cjs} +20 -9
- package/dist/{dateRange.js → dateRange.cjs} +42 -26
- package/dist/{duration.js → duration.cjs} +56 -44
- package/dist/esm/chain.js +0 -5
- package/dist/esm/naturalLanguage.d.ts +1 -3
- package/dist/esm/naturalLanguage.d.ts.map +1 -1
- package/dist/esm/naturalLanguage.js +9 -2
- package/dist/esm/plugins.d.ts +0 -6
- package/dist/esm/plugins.d.ts.map +1 -1
- package/dist/esm/plugins.js +36 -42
- package/dist/esm/recurrence.d.ts.map +1 -1
- package/dist/esm/recurrence.js +3 -5
- package/dist/esm/timezone.d.ts +6 -1
- package/dist/esm/timezone.d.ts.map +1 -1
- package/dist/esm/timezone.js +106 -66
- package/dist/esm/types.d.ts +0 -4
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/{finance.js → finance.cjs} +39 -22
- package/dist/{fiscal.js → fiscal.cjs} +36 -17
- package/dist/{format.js → format.cjs} +83 -70
- package/dist/{healthcare.js → healthcare.cjs} +37 -22
- package/dist/{holidays.js → holidays.cjs} +52 -25
- package/dist/index.cjs +595 -0
- package/dist/{interval.js → interval.cjs} +24 -11
- package/dist/{iterate.js → iterate.cjs} +84 -41
- package/dist/{locale.js → locale.cjs} +54 -26
- package/dist/{naturalLanguage.js → naturalLanguage.cjs} +36 -23
- package/dist/naturalLanguage.d.ts +1 -3
- package/dist/naturalLanguage.d.ts.map +1 -1
- package/dist/{parse.js → parse.cjs} +24 -11
- package/dist/{performance.js → performance.cjs} +23 -10
- package/dist/{plugins.js → plugins.cjs} +48 -47
- package/dist/plugins.d.ts +0 -6
- package/dist/plugins.d.ts.map +1 -1
- package/dist/{precision.js → precision.cjs} +74 -37
- package/dist/{rangePresets.js → rangePresets.cjs} +40 -19
- package/dist/{recurrence.js → recurrence.cjs} +27 -21
- package/dist/recurrence.d.ts.map +1 -1
- package/dist/{scheduling.js → scheduling.cjs} +46 -31
- package/dist/{serialize.js → serialize.cjs} +36 -17
- package/dist/{temporal.js → temporal.cjs} +28 -13
- package/dist/{timezone.js → timezone.cjs} +140 -82
- package/dist/timezone.d.ts +6 -1
- package/dist/timezone.d.ts.map +1 -1
- package/dist/{types.js → types.cjs} +9 -3
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/{validate.js → validate.cjs} +54 -26
- package/dist/{workingHours.js → workingHours.cjs} +36 -17
- package/package.json +40 -37
- package/dist/constants.js +0 -16
- package/dist/index.js +0 -72
|
@@ -1,8 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Timezone utilities using Intl API with fallbacks
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.COMMON_TIMEZONES = void 0;
|
|
7
|
+
exports.getTimezoneOffset = getTimezoneOffset;
|
|
8
|
+
exports.formatInTimeZone = formatInTimeZone;
|
|
9
|
+
exports.getZonedTime = getZonedTime;
|
|
10
|
+
exports.convertDateToZone = convertDateToZone;
|
|
11
|
+
exports.isValidTimeZone = isValidTimeZone;
|
|
12
|
+
exports.getLocalOffset = getLocalOffset;
|
|
13
|
+
exports.compareZoneOffsets = compareZoneOffsets;
|
|
14
|
+
exports.reinterpretAsZone = reinterpretAsZone;
|
|
15
|
+
exports.isDST = isDST;
|
|
16
|
+
exports.getNextDSTTransition = getNextDSTTransition;
|
|
17
|
+
exports.findCommonWorkingHours = findCommonWorkingHours;
|
|
18
|
+
exports.getTimezoneAbbreviation = getTimezoneAbbreviation;
|
|
19
|
+
exports.convertBetweenZones = convertBetweenZones;
|
|
20
|
+
exports.getTimezoneDifferenceHours = getTimezoneDifferenceHours;
|
|
21
|
+
exports.isSameTimezone = isSameTimezone;
|
|
22
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
23
|
+
const DAY_HOURS = 24;
|
|
24
|
+
const YEAR_MONTHS = Array.from({ length: 12 }, (_, month) => month);
|
|
25
|
+
function normalizeHourValue(hour) {
|
|
26
|
+
return ((hour % DAY_HOURS) + DAY_HOURS) % DAY_HOURS;
|
|
27
|
+
}
|
|
28
|
+
function pushSweepInterval(events, start, end) {
|
|
29
|
+
const clampedStart = Math.max(0, start);
|
|
30
|
+
const clampedEnd = Math.min(DAY_HOURS * 2, end);
|
|
31
|
+
if (clampedStart >= clampedEnd)
|
|
32
|
+
return;
|
|
33
|
+
events.push({ time: clampedStart, delta: 1 });
|
|
34
|
+
events.push({ time: clampedEnd, delta: -1 });
|
|
35
|
+
}
|
|
4
36
|
/** Get offset (minutes) for a zone at a given date */
|
|
5
|
-
|
|
37
|
+
function getTimezoneOffset(zone, date = new Date()) {
|
|
6
38
|
try {
|
|
7
39
|
const dtf = new Intl.DateTimeFormat('en-US', { timeZone: zone, timeZoneName: 'shortOffset', hour: '2-digit' });
|
|
8
40
|
const parts = dtf.formatToParts(date);
|
|
@@ -23,19 +55,19 @@ export function getTimezoneOffset(zone, date = new Date()) {
|
|
|
23
55
|
}
|
|
24
56
|
}
|
|
25
57
|
/** Format date/time in a zone */
|
|
26
|
-
|
|
58
|
+
function formatInTimeZone(date, zone, options = {}) {
|
|
27
59
|
const fmt = new Intl.DateTimeFormat('en-US', { timeZone: zone, ...options });
|
|
28
60
|
return fmt.format(date);
|
|
29
61
|
}
|
|
30
62
|
/** Get a lightweight ZonedTime object */
|
|
31
|
-
|
|
63
|
+
function getZonedTime(date, zone) {
|
|
32
64
|
const offset = getTimezoneOffset(zone, date);
|
|
33
65
|
if (offset == null)
|
|
34
66
|
return null;
|
|
35
67
|
return { date: new Date(date), zone, offsetMinutes: offset };
|
|
36
68
|
}
|
|
37
69
|
/** Convert a date (treated as absolute moment) to another zone's clock components */
|
|
38
|
-
|
|
70
|
+
function convertDateToZone(date, zone) {
|
|
39
71
|
try {
|
|
40
72
|
const fmt = new Intl.DateTimeFormat('en-US', {
|
|
41
73
|
timeZone: zone,
|
|
@@ -58,7 +90,7 @@ export function convertDateToZone(date, zone) {
|
|
|
58
90
|
}
|
|
59
91
|
}
|
|
60
92
|
/** Check if provided zone string is a valid IANA zone */
|
|
61
|
-
|
|
93
|
+
function isValidTimeZone(zone) {
|
|
62
94
|
try {
|
|
63
95
|
new Intl.DateTimeFormat('en-US', { timeZone: zone });
|
|
64
96
|
return true;
|
|
@@ -68,18 +100,18 @@ export function isValidTimeZone(zone) {
|
|
|
68
100
|
}
|
|
69
101
|
}
|
|
70
102
|
/** List a subset of common timezones (cannot enumerate all via API) */
|
|
71
|
-
|
|
103
|
+
exports.COMMON_TIMEZONES = [
|
|
72
104
|
'UTC', 'Etc/UTC', 'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Madrid', 'Europe/Rome',
|
|
73
105
|
'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles', 'America/Toronto', 'America/Sao_Paulo',
|
|
74
106
|
'Asia/Tehran', 'Asia/Dubai', 'Asia/Tokyo', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Kolkata', 'Asia/Hong_Kong',
|
|
75
107
|
'Australia/Sydney', 'Pacific/Auckland'
|
|
76
108
|
];
|
|
77
109
|
/** Get current local offset in minutes */
|
|
78
|
-
|
|
110
|
+
function getLocalOffset() {
|
|
79
111
|
return -new Date().getTimezoneOffset();
|
|
80
112
|
}
|
|
81
113
|
/** Compare two timezones offset at given date */
|
|
82
|
-
|
|
114
|
+
function compareZoneOffsets(zoneA, zoneB, date = new Date()) {
|
|
83
115
|
const a = getTimezoneOffset(zoneA, date);
|
|
84
116
|
const b = getTimezoneOffset(zoneB, date);
|
|
85
117
|
if (a == null || b == null)
|
|
@@ -91,7 +123,7 @@ export function compareZoneOffsets(zoneA, zoneB, date = new Date()) {
|
|
|
91
123
|
* the same wall clock time in the target zone interpreted as local.
|
|
92
124
|
* For example useful for naive scheduling.
|
|
93
125
|
*/
|
|
94
|
-
|
|
126
|
+
function reinterpretAsZone(date, targetZone) {
|
|
95
127
|
const target = convertDateToZone(date, targetZone);
|
|
96
128
|
if (!target)
|
|
97
129
|
return null;
|
|
@@ -99,30 +131,35 @@ export function reinterpretAsZone(date, targetZone) {
|
|
|
99
131
|
}
|
|
100
132
|
/**
|
|
101
133
|
* Check if a date is in Daylight Saving Time for a given timezone
|
|
134
|
+
* Uses a yearly-offset heuristic: sample the zone's local year and treat the
|
|
135
|
+
* maximum observed UTC offset as the DST offset for that year.
|
|
102
136
|
* @param date - date to check
|
|
103
137
|
* @param zone - IANA timezone string
|
|
104
138
|
*/
|
|
105
|
-
|
|
139
|
+
function isDST(date, zone) {
|
|
106
140
|
if (!isValidTimeZone(zone))
|
|
107
141
|
return null;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const julOffset = getTimezoneOffset(zone, july);
|
|
142
|
+
const zonedDate = convertDateToZone(date, zone);
|
|
143
|
+
if (!zonedDate) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
113
146
|
const currentOffset = getTimezoneOffset(zone, date);
|
|
114
|
-
if (
|
|
147
|
+
if (currentOffset === null) {
|
|
115
148
|
return null;
|
|
116
149
|
}
|
|
117
|
-
|
|
118
|
-
|
|
150
|
+
const yearlyOffsets = new Set();
|
|
151
|
+
for (const month of YEAR_MONTHS) {
|
|
152
|
+
const sample = new Date(Date.UTC(zonedDate.year, month, 1, 12, 0, 0));
|
|
153
|
+
const offset = getTimezoneOffset(zone, sample);
|
|
154
|
+
if (offset === null) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
yearlyOffsets.add(offset);
|
|
158
|
+
}
|
|
159
|
+
if (yearlyOffsets.size <= 1) {
|
|
119
160
|
return false;
|
|
120
161
|
}
|
|
121
|
-
|
|
122
|
-
// In southern hemisphere, summer (January) has larger offset
|
|
123
|
-
// DST is whichever is the "larger" offset
|
|
124
|
-
const maxOffset = Math.max(janOffset, julOffset);
|
|
125
|
-
return currentOffset === maxOffset;
|
|
162
|
+
return currentOffset === Math.max(...yearlyOffsets);
|
|
126
163
|
}
|
|
127
164
|
/**
|
|
128
165
|
* Get the next DST transition (if any) for a timezone
|
|
@@ -130,49 +167,38 @@ export function isDST(date, zone) {
|
|
|
130
167
|
* @param zone - IANA timezone string
|
|
131
168
|
* @returns next DST transition date or null if no DST in that zone
|
|
132
169
|
*/
|
|
133
|
-
|
|
170
|
+
function getNextDSTTransition(date, zone) {
|
|
134
171
|
if (!isValidTimeZone(zone))
|
|
135
172
|
return null;
|
|
136
|
-
const january = new Date(date.getFullYear(), 0, 1);
|
|
137
|
-
const july = new Date(date.getFullYear(), 6, 1);
|
|
138
|
-
const janOffset = getTimezoneOffset(zone, january);
|
|
139
|
-
const julOffset = getTimezoneOffset(zone, july);
|
|
140
|
-
if (janOffset === null || julOffset === null)
|
|
141
|
-
return null;
|
|
142
|
-
// No DST if offsets are the same
|
|
143
|
-
if (janOffset === julOffset)
|
|
144
|
-
return null;
|
|
145
|
-
// Binary search for the transition within the next year
|
|
146
173
|
const currentOffset = getTimezoneOffset(zone, date);
|
|
147
174
|
if (currentOffset === null)
|
|
148
175
|
return null;
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
let low = prevDay.getTime();
|
|
160
|
-
let high = searchDate.getTime();
|
|
161
|
-
while (high - low > 60000) { // 1 minute precision
|
|
162
|
-
const mid = Math.floor((low + high) / 2);
|
|
163
|
-
const midDate = new Date(mid);
|
|
164
|
-
const midOffset = getTimezoneOffset(zone, midDate);
|
|
165
|
-
if (midOffset === currentOffset) {
|
|
166
|
-
low = mid;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
high = mid;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return new Date(high);
|
|
176
|
+
const startTime = date.getTime() + 1;
|
|
177
|
+
const searchLimit = startTime + 366 * DAY_MS;
|
|
178
|
+
let low = startTime;
|
|
179
|
+
let high = null;
|
|
180
|
+
for (let probeTime = startTime + DAY_MS; probeTime <= searchLimit; probeTime += DAY_MS) {
|
|
181
|
+
const probeOffset = getTimezoneOffset(zone, new Date(probeTime));
|
|
182
|
+
if (probeOffset !== null && probeOffset !== currentOffset) {
|
|
183
|
+
low = probeTime - DAY_MS;
|
|
184
|
+
high = probeTime;
|
|
185
|
+
break;
|
|
173
186
|
}
|
|
174
187
|
}
|
|
175
|
-
|
|
188
|
+
if (high === null) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
while (high - low > 1) {
|
|
192
|
+
const mid = Math.floor((low + high) / 2);
|
|
193
|
+
const midOffset = getTimezoneOffset(zone, new Date(mid));
|
|
194
|
+
if (midOffset === currentOffset) {
|
|
195
|
+
low = mid;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
high = mid;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return new Date(high);
|
|
176
202
|
}
|
|
177
203
|
/**
|
|
178
204
|
* Find overlapping working hours between multiple timezones
|
|
@@ -180,39 +206,71 @@ export function getNextDSTTransition(date, zone) {
|
|
|
180
206
|
* @param workHoursStart - work hours start (0-24)
|
|
181
207
|
* @param workHoursEnd - work hours end (0-24)
|
|
182
208
|
* @param date - reference date (default: today)
|
|
183
|
-
* @returns
|
|
209
|
+
* @returns one contiguous UTC overlap window, specifically the longest
|
|
210
|
+
* contiguous overlap slice. A full-day overlap is returned as
|
|
211
|
+
* `{ startUTC: 0, endUTC: 24 }`, and wrapped overlaps are returned with
|
|
212
|
+
* `endUTC` normalized back into the 0-24 range and may be less than `startUTC`
|
|
184
213
|
*/
|
|
185
|
-
|
|
214
|
+
function findCommonWorkingHours(zones, workHoursStart = 9, workHoursEnd = 17, date = new Date()) {
|
|
186
215
|
if (zones.length === 0)
|
|
187
216
|
return null;
|
|
188
|
-
|
|
189
|
-
const
|
|
217
|
+
const endHour = workHoursEnd < workHoursStart ? workHoursEnd + DAY_HOURS : workHoursEnd;
|
|
218
|
+
const duration = endHour - workHoursStart;
|
|
219
|
+
if (duration <= 0) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const sweepEvents = [];
|
|
223
|
+
for (const zone of zones) {
|
|
190
224
|
const offset = getTimezoneOffset(zone, date);
|
|
191
|
-
if (offset === null)
|
|
225
|
+
if (offset === null) {
|
|
192
226
|
return null;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
227
|
+
}
|
|
228
|
+
if (duration >= DAY_HOURS) {
|
|
229
|
+
pushSweepInterval(sweepEvents, 0, DAY_HOURS * 2);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const startUTC = normalizeHourValue(workHoursStart - (offset / 60));
|
|
233
|
+
pushSweepInterval(sweepEvents, startUTC, startUTC + duration);
|
|
234
|
+
pushSweepInterval(sweepEvents, startUTC + DAY_HOURS, startUTC + DAY_HOURS + duration);
|
|
235
|
+
}
|
|
236
|
+
sweepEvents.sort((a, b) => a.time - b.time || b.delta - a.delta);
|
|
237
|
+
let activeWindows = 0;
|
|
238
|
+
let previousTime = 0;
|
|
239
|
+
let bestOverlap = null;
|
|
240
|
+
for (let i = 0; i < sweepEvents.length;) {
|
|
241
|
+
const currentTime = sweepEvents[i].time;
|
|
242
|
+
if (currentTime > previousTime && activeWindows === zones.length) {
|
|
243
|
+
const candidate = { start: previousTime, end: currentTime };
|
|
244
|
+
if (bestOverlap === null ||
|
|
245
|
+
candidate.end - candidate.start > bestOverlap.end - bestOverlap.start ||
|
|
246
|
+
(candidate.end - candidate.start === bestOverlap.end - bestOverlap.start &&
|
|
247
|
+
candidate.start < bestOverlap.start)) {
|
|
248
|
+
bestOverlap = candidate;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
while (i < sweepEvents.length && sweepEvents[i].time === currentTime) {
|
|
252
|
+
activeWindows += sweepEvents[i].delta;
|
|
253
|
+
i++;
|
|
254
|
+
}
|
|
255
|
+
previousTime = currentTime;
|
|
256
|
+
}
|
|
257
|
+
if (bestOverlap === null) {
|
|
200
258
|
return null;
|
|
201
|
-
const validRanges = utcRanges;
|
|
202
|
-
// Find intersection of all ranges
|
|
203
|
-
let overlapStart = Math.max(...validRanges.map(r => r.startUTC));
|
|
204
|
-
let overlapEnd = Math.min(...validRanges.map(r => r.endUTC));
|
|
205
|
-
if (overlapStart >= overlapEnd) {
|
|
206
|
-
return null; // No overlap
|
|
207
259
|
}
|
|
208
|
-
|
|
260
|
+
const overlapDuration = bestOverlap.end - bestOverlap.start;
|
|
261
|
+
if (overlapDuration >= DAY_HOURS) {
|
|
262
|
+
return { startUTC: 0, endUTC: DAY_HOURS };
|
|
263
|
+
}
|
|
264
|
+
const startUTC = normalizeHourValue(bestOverlap.start);
|
|
265
|
+
const endUTC = normalizeHourValue(bestOverlap.start + overlapDuration);
|
|
266
|
+
return { startUTC, endUTC };
|
|
209
267
|
}
|
|
210
268
|
/**
|
|
211
269
|
* Get all timezone abbreviations for a zone on a given date
|
|
212
270
|
* @param zone - IANA timezone string
|
|
213
271
|
* @param date - reference date
|
|
214
272
|
*/
|
|
215
|
-
|
|
273
|
+
function getTimezoneAbbreviation(zone, date = new Date()) {
|
|
216
274
|
try {
|
|
217
275
|
const fmt = new Intl.DateTimeFormat('en-US', {
|
|
218
276
|
timeZone: zone,
|
|
@@ -232,7 +290,7 @@ export function getTimezoneAbbreviation(zone, date = new Date()) {
|
|
|
232
290
|
* @param fromZone - source timezone
|
|
233
291
|
* @param toZone - target timezone
|
|
234
292
|
*/
|
|
235
|
-
|
|
293
|
+
function convertBetweenZones(date, fromZone, toZone) {
|
|
236
294
|
// First, interpret the date as being in fromZone
|
|
237
295
|
const fromOffset = getTimezoneOffset(fromZone, date);
|
|
238
296
|
const toOffset = getTimezoneOffset(toZone, date);
|
|
@@ -250,7 +308,7 @@ export function convertBetweenZones(date, fromZone, toZone) {
|
|
|
250
308
|
* @param zoneB - second timezone
|
|
251
309
|
* @param date - reference date
|
|
252
310
|
*/
|
|
253
|
-
|
|
311
|
+
function getTimezoneDifferenceHours(zoneA, zoneB, date = new Date()) {
|
|
254
312
|
const diff = compareZoneOffsets(zoneA, zoneB, date);
|
|
255
313
|
if (diff === null)
|
|
256
314
|
return null;
|
|
@@ -262,7 +320,7 @@ export function getTimezoneDifferenceHours(zoneA, zoneB, date = new Date()) {
|
|
|
262
320
|
* @param zoneB - second timezone
|
|
263
321
|
* @param date - reference date
|
|
264
322
|
*/
|
|
265
|
-
|
|
323
|
+
function isSameTimezone(zoneA, zoneB, date = new Date()) {
|
|
266
324
|
const diff = compareZoneOffsets(zoneA, zoneB, date);
|
|
267
325
|
if (diff === null)
|
|
268
326
|
return null;
|
package/dist/timezone.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export declare function compareZoneOffsets(zoneA: string, zoneB: string, date?:
|
|
|
33
33
|
export declare function reinterpretAsZone(date: Date, targetZone: string): Date | null;
|
|
34
34
|
/**
|
|
35
35
|
* Check if a date is in Daylight Saving Time for a given timezone
|
|
36
|
+
* Uses a yearly-offset heuristic: sample the zone's local year and treat the
|
|
37
|
+
* maximum observed UTC offset as the DST offset for that year.
|
|
36
38
|
* @param date - date to check
|
|
37
39
|
* @param zone - IANA timezone string
|
|
38
40
|
*/
|
|
@@ -50,7 +52,10 @@ export declare function getNextDSTTransition(date: Date, zone: string): Date | n
|
|
|
50
52
|
* @param workHoursStart - work hours start (0-24)
|
|
51
53
|
* @param workHoursEnd - work hours end (0-24)
|
|
52
54
|
* @param date - reference date (default: today)
|
|
53
|
-
* @returns
|
|
55
|
+
* @returns one contiguous UTC overlap window, specifically the longest
|
|
56
|
+
* contiguous overlap slice. A full-day overlap is returned as
|
|
57
|
+
* `{ startUTC: 0, endUTC: 24 }`, and wrapped overlaps are returned with
|
|
58
|
+
* `endUTC` normalized back into the 0-24 range and may be less than `startUTC`
|
|
54
59
|
*/
|
|
55
60
|
export declare function findCommonWorkingHours(zones: string[], workHoursStart?: number, workHoursEnd?: number, date?: Date): {
|
|
56
61
|
startUTC: number;
|
package/dist/timezone.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA6B5C,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAgBtF;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,qBAA0B,GAAG,MAAM,CAG3G;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIvE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CAAE,GAAG,IAAI,CAoB9J;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,UAK5B,CAAC;AAEF,0CAA0C;AAC1C,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAKvG;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAI7E;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA4B9D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAmC1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,GAAE,MAAU,EAC1B,YAAY,GAAE,MAAW,EACzB,IAAI,GAAE,IAAiB,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAqE7C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAY5F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAa7F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAI/G;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,OAAO,GAAG,IAAI,CAIpG"}
|
|
@@ -1,25 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Shared types and interfaces used across ts-time-utils modules
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ValidationError = exports.ParseError = exports.TimeUtilsError = void 0;
|
|
4
7
|
/** Standardized error types */
|
|
5
|
-
|
|
8
|
+
class TimeUtilsError extends Error {
|
|
6
9
|
constructor(message, code) {
|
|
7
10
|
super(message);
|
|
8
11
|
this.code = code;
|
|
9
12
|
this.name = 'TimeUtilsError';
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
|
-
|
|
15
|
+
exports.TimeUtilsError = TimeUtilsError;
|
|
16
|
+
class ParseError extends TimeUtilsError {
|
|
13
17
|
constructor(message, input) {
|
|
14
18
|
super(message, 'PARSE_ERROR');
|
|
15
19
|
this.input = input;
|
|
16
20
|
this.name = 'ParseError';
|
|
17
21
|
}
|
|
18
22
|
}
|
|
19
|
-
|
|
23
|
+
exports.ParseError = ParseError;
|
|
24
|
+
class ValidationError extends TimeUtilsError {
|
|
20
25
|
constructor(message, value) {
|
|
21
26
|
super(message, 'VALIDATION_ERROR');
|
|
22
27
|
this.value = value;
|
|
23
28
|
this.name = 'ValidationError';
|
|
24
29
|
}
|
|
25
30
|
}
|
|
31
|
+
exports.ValidationError = ValidationError;
|
package/dist/types.d.ts
CHANGED
|
@@ -14,8 +14,6 @@ export interface ParseOptions {
|
|
|
14
14
|
strict?: boolean;
|
|
15
15
|
/** Timezone to use for parsing */
|
|
16
16
|
timezone?: string;
|
|
17
|
-
/** Default locale for parsing */
|
|
18
|
-
locale?: string;
|
|
19
17
|
}
|
|
20
18
|
/** Options for formatting operations */
|
|
21
19
|
export interface FormatOptions {
|
|
@@ -63,8 +61,6 @@ export interface WorkingHoursConfig {
|
|
|
63
61
|
start: number;
|
|
64
62
|
end: number;
|
|
65
63
|
}[];
|
|
66
|
-
/** Timezone for working hours calculation */
|
|
67
|
-
timezone?: string;
|
|
68
64
|
}
|
|
69
65
|
/** Result of age calculation */
|
|
70
66
|
export interface AgeResult {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/C,4CAA4C;AAC5C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX;AAED,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|