ts-time-utils 4.1.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -32
- package/dist/{age.js → age.cjs} +14 -6
- package/dist/{calculate.js → calculate.cjs} +42 -18
- package/dist/calculate.d.ts +7 -0
- package/dist/calculate.d.ts.map +1 -1
- 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/calculate.d.ts +7 -0
- package/dist/esm/calculate.d.ts.map +1 -1
- package/dist/esm/calculate.js +11 -0
- package/dist/esm/chain.js +0 -5
- package/dist/esm/format.d.ts.map +1 -1
- package/dist/esm/format.js +3 -3
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- 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} +85 -72
- package/dist/format.d.ts.map +1 -1
- package/dist/{healthcare.js → healthcare.cjs} +37 -22
- package/dist/{holidays.js → holidays.cjs} +52 -25
- package/dist/index.cjs +596 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- 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 +41 -38
- package/dist/constants.js +0 -16
- package/dist/index.js +0 -72
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDuration = formatDuration;
|
|
4
|
+
exports.timeAgo = timeAgo;
|
|
5
|
+
exports.formatTime = formatTime;
|
|
6
|
+
exports.parseDuration = parseDuration;
|
|
7
|
+
exports.formatDate = formatDate;
|
|
8
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
9
|
+
exports.formatDateRange = formatDateRange;
|
|
10
|
+
exports.formatOrdinal = formatOrdinal;
|
|
11
|
+
exports.formatDayOrdinal = formatDayOrdinal;
|
|
12
|
+
exports.formatDurationCompact = formatDurationCompact;
|
|
13
|
+
exports.formatCalendarDate = formatCalendarDate;
|
|
14
|
+
const constants_js_1 = require("./constants.cjs");
|
|
15
|
+
const calculate_js_1 = require("./calculate.cjs");
|
|
2
16
|
/**
|
|
3
17
|
* Convert milliseconds to a human-readable duration.
|
|
4
18
|
* @param ms - milliseconds
|
|
5
19
|
* @param options - formatting options
|
|
6
20
|
*/
|
|
7
|
-
|
|
21
|
+
function formatDuration(ms, options = {}) {
|
|
8
22
|
const { includeMs = false, short = false, maxUnits = 2, round = false } = options;
|
|
9
23
|
if (ms < 0)
|
|
10
24
|
return '0' + (short ? 's' : ' seconds');
|
|
@@ -12,46 +26,46 @@ export function formatDuration(ms, options = {}) {
|
|
|
12
26
|
const parts = [];
|
|
13
27
|
let remaining = ms;
|
|
14
28
|
// Years
|
|
15
|
-
if (remaining >= MILLISECONDS_PER_YEAR) {
|
|
16
|
-
const years = mathFn(remaining / MILLISECONDS_PER_YEAR);
|
|
29
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_YEAR) {
|
|
30
|
+
const years = mathFn(remaining / constants_js_1.MILLISECONDS_PER_YEAR);
|
|
17
31
|
parts.push(years + (short ? 'y' : ` year${years !== 1 ? 's' : ''}`));
|
|
18
|
-
remaining %= MILLISECONDS_PER_YEAR;
|
|
32
|
+
remaining %= constants_js_1.MILLISECONDS_PER_YEAR;
|
|
19
33
|
}
|
|
20
34
|
// Months
|
|
21
|
-
if (remaining >= MILLISECONDS_PER_MONTH && parts.length < maxUnits) {
|
|
22
|
-
const months = mathFn(remaining / MILLISECONDS_PER_MONTH);
|
|
35
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_MONTH && parts.length < maxUnits) {
|
|
36
|
+
const months = mathFn(remaining / constants_js_1.MILLISECONDS_PER_MONTH);
|
|
23
37
|
parts.push(months + (short ? 'mo' : ` month${months !== 1 ? 's' : ''}`));
|
|
24
|
-
remaining %= MILLISECONDS_PER_MONTH;
|
|
38
|
+
remaining %= constants_js_1.MILLISECONDS_PER_MONTH;
|
|
25
39
|
}
|
|
26
40
|
// Weeks
|
|
27
|
-
if (remaining >= MILLISECONDS_PER_WEEK && parts.length < maxUnits) {
|
|
28
|
-
const weeks = mathFn(remaining / MILLISECONDS_PER_WEEK);
|
|
41
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_WEEK && parts.length < maxUnits) {
|
|
42
|
+
const weeks = mathFn(remaining / constants_js_1.MILLISECONDS_PER_WEEK);
|
|
29
43
|
parts.push(weeks + (short ? 'w' : ` week${weeks !== 1 ? 's' : ''}`));
|
|
30
|
-
remaining %= MILLISECONDS_PER_WEEK;
|
|
44
|
+
remaining %= constants_js_1.MILLISECONDS_PER_WEEK;
|
|
31
45
|
}
|
|
32
46
|
// Days
|
|
33
|
-
if (remaining >= MILLISECONDS_PER_DAY && parts.length < maxUnits) {
|
|
34
|
-
const days = mathFn(remaining / MILLISECONDS_PER_DAY);
|
|
47
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_DAY && parts.length < maxUnits) {
|
|
48
|
+
const days = mathFn(remaining / constants_js_1.MILLISECONDS_PER_DAY);
|
|
35
49
|
parts.push(days + (short ? 'd' : ` day${days !== 1 ? 's' : ''}`));
|
|
36
|
-
remaining %= MILLISECONDS_PER_DAY;
|
|
50
|
+
remaining %= constants_js_1.MILLISECONDS_PER_DAY;
|
|
37
51
|
}
|
|
38
52
|
// Hours
|
|
39
|
-
if (remaining >= MILLISECONDS_PER_HOUR && parts.length < maxUnits) {
|
|
40
|
-
const hours = mathFn(remaining / MILLISECONDS_PER_HOUR);
|
|
53
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_HOUR && parts.length < maxUnits) {
|
|
54
|
+
const hours = mathFn(remaining / constants_js_1.MILLISECONDS_PER_HOUR);
|
|
41
55
|
parts.push(hours + (short ? 'h' : ` hour${hours !== 1 ? 's' : ''}`));
|
|
42
|
-
remaining %= MILLISECONDS_PER_HOUR;
|
|
56
|
+
remaining %= constants_js_1.MILLISECONDS_PER_HOUR;
|
|
43
57
|
}
|
|
44
58
|
// Minutes
|
|
45
|
-
if (remaining >= MILLISECONDS_PER_MINUTE && parts.length < maxUnits) {
|
|
46
|
-
const minutes = mathFn(remaining / MILLISECONDS_PER_MINUTE);
|
|
59
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_MINUTE && parts.length < maxUnits) {
|
|
60
|
+
const minutes = mathFn(remaining / constants_js_1.MILLISECONDS_PER_MINUTE);
|
|
47
61
|
parts.push(minutes + (short ? 'm' : ` minute${minutes !== 1 ? 's' : ''}`));
|
|
48
|
-
remaining %= MILLISECONDS_PER_MINUTE;
|
|
62
|
+
remaining %= constants_js_1.MILLISECONDS_PER_MINUTE;
|
|
49
63
|
}
|
|
50
64
|
// Seconds
|
|
51
|
-
if (remaining >= MILLISECONDS_PER_SECOND && parts.length < maxUnits) {
|
|
52
|
-
const seconds = mathFn(remaining / MILLISECONDS_PER_SECOND);
|
|
65
|
+
if (remaining >= constants_js_1.MILLISECONDS_PER_SECOND && parts.length < maxUnits) {
|
|
66
|
+
const seconds = mathFn(remaining / constants_js_1.MILLISECONDS_PER_SECOND);
|
|
53
67
|
parts.push(seconds + (short ? 's' : ` second${seconds !== 1 ? 's' : ''}`));
|
|
54
|
-
remaining %= MILLISECONDS_PER_SECOND;
|
|
68
|
+
remaining %= constants_js_1.MILLISECONDS_PER_SECOND;
|
|
55
69
|
}
|
|
56
70
|
// Milliseconds
|
|
57
71
|
if ((remaining > 0 || parts.length === 0) && includeMs && parts.length < maxUnits) {
|
|
@@ -68,43 +82,43 @@ export function formatDuration(ms, options = {}) {
|
|
|
68
82
|
* @param date - past or future date
|
|
69
83
|
* @param options - formatting options
|
|
70
84
|
*/
|
|
71
|
-
|
|
85
|
+
function timeAgo(date, options = {}) {
|
|
72
86
|
const now = new Date();
|
|
73
87
|
const diffMs = now.getTime() - date.getTime();
|
|
74
88
|
const { short = false } = options;
|
|
75
89
|
const isFuture = diffMs < 0;
|
|
76
90
|
const absDiffMs = Math.abs(diffMs);
|
|
77
|
-
if (absDiffMs < MILLISECONDS_PER_MINUTE) {
|
|
78
|
-
const seconds = Math.floor(absDiffMs / MILLISECONDS_PER_SECOND);
|
|
91
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_MINUTE) {
|
|
92
|
+
const seconds = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_SECOND);
|
|
79
93
|
const unit = short ? 's' : ` second${seconds !== 1 ? 's' : ''}`;
|
|
80
94
|
return isFuture ? `in ${seconds}${unit}` : `${seconds}${unit} ago`;
|
|
81
95
|
}
|
|
82
|
-
if (absDiffMs < MILLISECONDS_PER_HOUR) {
|
|
83
|
-
const minutes = Math.floor(absDiffMs / MILLISECONDS_PER_MINUTE);
|
|
96
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_HOUR) {
|
|
97
|
+
const minutes = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_MINUTE);
|
|
84
98
|
const unit = short ? 'm' : ` minute${minutes !== 1 ? 's' : ''}`;
|
|
85
99
|
return isFuture ? `in ${minutes}${unit}` : `${minutes}${unit} ago`;
|
|
86
100
|
}
|
|
87
|
-
if (absDiffMs < MILLISECONDS_PER_DAY) {
|
|
88
|
-
const hours = Math.floor(absDiffMs / MILLISECONDS_PER_HOUR);
|
|
101
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_DAY) {
|
|
102
|
+
const hours = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_HOUR);
|
|
89
103
|
const unit = short ? 'h' : ` hour${hours !== 1 ? 's' : ''}`;
|
|
90
104
|
return isFuture ? `in ${hours}${unit}` : `${hours}${unit} ago`;
|
|
91
105
|
}
|
|
92
|
-
if (absDiffMs < MILLISECONDS_PER_WEEK) {
|
|
93
|
-
const days = Math.floor(absDiffMs / MILLISECONDS_PER_DAY);
|
|
106
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_WEEK) {
|
|
107
|
+
const days = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_DAY);
|
|
94
108
|
const unit = short ? 'd' : ` day${days !== 1 ? 's' : ''}`;
|
|
95
109
|
return isFuture ? `in ${days}${unit}` : `${days}${unit} ago`;
|
|
96
110
|
}
|
|
97
|
-
if (absDiffMs < MILLISECONDS_PER_MONTH) {
|
|
98
|
-
const weeks = Math.floor(absDiffMs / MILLISECONDS_PER_WEEK);
|
|
111
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_MONTH) {
|
|
112
|
+
const weeks = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_WEEK);
|
|
99
113
|
const unit = short ? 'w' : ` week${weeks !== 1 ? 's' : ''}`;
|
|
100
114
|
return isFuture ? `in ${weeks}${unit}` : `${weeks}${unit} ago`;
|
|
101
115
|
}
|
|
102
|
-
if (absDiffMs < MILLISECONDS_PER_YEAR) {
|
|
103
|
-
const months = Math.floor(absDiffMs / MILLISECONDS_PER_MONTH);
|
|
116
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_YEAR) {
|
|
117
|
+
const months = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_MONTH);
|
|
104
118
|
const unit = short ? 'mo' : ` month${months !== 1 ? 's' : ''}`;
|
|
105
119
|
return isFuture ? `in ${months}${unit}` : `${months}${unit} ago`;
|
|
106
120
|
}
|
|
107
|
-
const years = Math.floor(absDiffMs / MILLISECONDS_PER_YEAR);
|
|
121
|
+
const years = Math.floor(absDiffMs / constants_js_1.MILLISECONDS_PER_YEAR);
|
|
108
122
|
const unit = short ? 'y' : ` year${years !== 1 ? 's' : ''}`;
|
|
109
123
|
return isFuture ? `in ${years}${unit}` : `${years}${unit} ago`;
|
|
110
124
|
}
|
|
@@ -113,7 +127,7 @@ export function timeAgo(date, options = {}) {
|
|
|
113
127
|
* @param date - date to format
|
|
114
128
|
* @param format - format type
|
|
115
129
|
*/
|
|
116
|
-
|
|
130
|
+
function formatTime(date, format = '24h') {
|
|
117
131
|
switch (format) {
|
|
118
132
|
case '12h':
|
|
119
133
|
return date.toLocaleTimeString('en-US', {
|
|
@@ -132,7 +146,7 @@ export function formatTime(date, format = '24h') {
|
|
|
132
146
|
* Parse a duration string like "1h 30m" into milliseconds
|
|
133
147
|
* @param duration - duration string (e.g., "1h 30m", "2d", "45s")
|
|
134
148
|
*/
|
|
135
|
-
|
|
149
|
+
function parseDuration(duration) {
|
|
136
150
|
const regex = /(\d+(?:\.\d+)?)\s*([a-zA-Z]+)/g;
|
|
137
151
|
let totalMs = 0;
|
|
138
152
|
let match;
|
|
@@ -149,39 +163,39 @@ export function parseDuration(duration) {
|
|
|
149
163
|
case 'sec':
|
|
150
164
|
case 'second':
|
|
151
165
|
case 'seconds':
|
|
152
|
-
totalMs += value * MILLISECONDS_PER_SECOND;
|
|
166
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_SECOND;
|
|
153
167
|
break;
|
|
154
168
|
case 'm':
|
|
155
169
|
case 'min':
|
|
156
170
|
case 'minute':
|
|
157
171
|
case 'minutes':
|
|
158
|
-
totalMs += value * MILLISECONDS_PER_MINUTE;
|
|
172
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_MINUTE;
|
|
159
173
|
break;
|
|
160
174
|
case 'h':
|
|
161
175
|
case 'hr':
|
|
162
176
|
case 'hour':
|
|
163
177
|
case 'hours':
|
|
164
|
-
totalMs += value * MILLISECONDS_PER_HOUR;
|
|
178
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_HOUR;
|
|
165
179
|
break;
|
|
166
180
|
case 'd':
|
|
167
181
|
case 'day':
|
|
168
182
|
case 'days':
|
|
169
|
-
totalMs += value * MILLISECONDS_PER_DAY;
|
|
183
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_DAY;
|
|
170
184
|
break;
|
|
171
185
|
case 'w':
|
|
172
186
|
case 'week':
|
|
173
187
|
case 'weeks':
|
|
174
|
-
totalMs += value * MILLISECONDS_PER_WEEK;
|
|
188
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_WEEK;
|
|
175
189
|
break;
|
|
176
190
|
case 'mo':
|
|
177
191
|
case 'month':
|
|
178
192
|
case 'months':
|
|
179
|
-
totalMs += value * MILLISECONDS_PER_MONTH;
|
|
193
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_MONTH;
|
|
180
194
|
break;
|
|
181
195
|
case 'y':
|
|
182
196
|
case 'year':
|
|
183
197
|
case 'years':
|
|
184
|
-
totalMs += value * MILLISECONDS_PER_YEAR;
|
|
198
|
+
totalMs += value * constants_js_1.MILLISECONDS_PER_YEAR;
|
|
185
199
|
break;
|
|
186
200
|
}
|
|
187
201
|
}
|
|
@@ -225,7 +239,7 @@ const DAY_NAMES_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
|
225
239
|
* - A: AM/PM
|
|
226
240
|
* - a: am/pm
|
|
227
241
|
*/
|
|
228
|
-
|
|
242
|
+
function formatDate(date, pattern) {
|
|
229
243
|
const year = date.getFullYear();
|
|
230
244
|
const month = date.getMonth();
|
|
231
245
|
const day = date.getDate();
|
|
@@ -270,36 +284,36 @@ export function formatDate(date, pattern) {
|
|
|
270
284
|
* @param date - target date
|
|
271
285
|
* @param baseDate - base date (default: now)
|
|
272
286
|
*/
|
|
273
|
-
|
|
287
|
+
function formatRelativeTime(date, baseDate = new Date()) {
|
|
274
288
|
const diffMs = date.getTime() - baseDate.getTime();
|
|
275
289
|
const isFuture = diffMs > 0;
|
|
276
290
|
const absDiffMs = Math.abs(diffMs);
|
|
277
291
|
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
|
|
278
|
-
if (absDiffMs < MILLISECONDS_PER_MINUTE) {
|
|
279
|
-
const seconds = Math.round(absDiffMs / MILLISECONDS_PER_SECOND);
|
|
292
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_MINUTE) {
|
|
293
|
+
const seconds = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_SECOND);
|
|
280
294
|
return rtf.format(isFuture ? seconds : -seconds, 'second');
|
|
281
295
|
}
|
|
282
|
-
if (absDiffMs < MILLISECONDS_PER_HOUR) {
|
|
283
|
-
const minutes = Math.round(absDiffMs / MILLISECONDS_PER_MINUTE);
|
|
296
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_HOUR) {
|
|
297
|
+
const minutes = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_MINUTE);
|
|
284
298
|
return rtf.format(isFuture ? minutes : -minutes, 'minute');
|
|
285
299
|
}
|
|
286
|
-
if (absDiffMs < MILLISECONDS_PER_DAY) {
|
|
287
|
-
const hours = Math.round(absDiffMs / MILLISECONDS_PER_HOUR);
|
|
300
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_DAY) {
|
|
301
|
+
const hours = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_HOUR);
|
|
288
302
|
return rtf.format(isFuture ? hours : -hours, 'hour');
|
|
289
303
|
}
|
|
290
|
-
if (absDiffMs < MILLISECONDS_PER_WEEK) {
|
|
291
|
-
const days = Math.round(absDiffMs / MILLISECONDS_PER_DAY);
|
|
304
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_WEEK) {
|
|
305
|
+
const days = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_DAY);
|
|
292
306
|
return rtf.format(isFuture ? days : -days, 'day');
|
|
293
307
|
}
|
|
294
|
-
if (absDiffMs < MILLISECONDS_PER_MONTH) {
|
|
295
|
-
const weeks = Math.round(absDiffMs / MILLISECONDS_PER_WEEK);
|
|
308
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_MONTH) {
|
|
309
|
+
const weeks = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_WEEK);
|
|
296
310
|
return rtf.format(isFuture ? weeks : -weeks, 'week');
|
|
297
311
|
}
|
|
298
|
-
if (absDiffMs < MILLISECONDS_PER_YEAR) {
|
|
299
|
-
const months = Math.round(absDiffMs / MILLISECONDS_PER_MONTH);
|
|
312
|
+
if (absDiffMs < constants_js_1.MILLISECONDS_PER_YEAR) {
|
|
313
|
+
const months = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_MONTH);
|
|
300
314
|
return rtf.format(isFuture ? months : -months, 'month');
|
|
301
315
|
}
|
|
302
|
-
const years = Math.round(absDiffMs / MILLISECONDS_PER_YEAR);
|
|
316
|
+
const years = Math.round(absDiffMs / constants_js_1.MILLISECONDS_PER_YEAR);
|
|
303
317
|
return rtf.format(isFuture ? years : -years, 'year');
|
|
304
318
|
}
|
|
305
319
|
/**
|
|
@@ -308,7 +322,7 @@ export function formatRelativeTime(date, baseDate = new Date()) {
|
|
|
308
322
|
* @param end - end date
|
|
309
323
|
* @param options - formatting options
|
|
310
324
|
*/
|
|
311
|
-
|
|
325
|
+
function formatDateRange(start, end, options = {}) {
|
|
312
326
|
const { separator = ' - ', includeTime = false, format = 'medium' } = options;
|
|
313
327
|
const sameYear = start.getFullYear() === end.getFullYear();
|
|
314
328
|
const sameMonth = sameYear && start.getMonth() === end.getMonth();
|
|
@@ -335,7 +349,7 @@ export function formatDateRange(start, end, options = {}) {
|
|
|
335
349
|
* Format a number as an ordinal (1st, 2nd, 3rd, etc.)
|
|
336
350
|
* @param n - number to format
|
|
337
351
|
*/
|
|
338
|
-
|
|
352
|
+
function formatOrdinal(n) {
|
|
339
353
|
const suffixes = ['th', 'st', 'nd', 'rd'];
|
|
340
354
|
const v = n % 100;
|
|
341
355
|
return n + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);
|
|
@@ -344,7 +358,7 @@ export function formatOrdinal(n) {
|
|
|
344
358
|
* Format a day of month as an ordinal (1st, 2nd, 3rd, etc.)
|
|
345
359
|
* @param date - date to format
|
|
346
360
|
*/
|
|
347
|
-
|
|
361
|
+
function formatDayOrdinal(date) {
|
|
348
362
|
return formatOrdinal(date.getDate());
|
|
349
363
|
}
|
|
350
364
|
/**
|
|
@@ -352,10 +366,10 @@ export function formatDayOrdinal(date) {
|
|
|
352
366
|
* @param ms - milliseconds
|
|
353
367
|
* @param showHours - always show hours even if 0
|
|
354
368
|
*/
|
|
355
|
-
|
|
356
|
-
const hours = Math.floor(ms / MILLISECONDS_PER_HOUR);
|
|
357
|
-
const minutes = Math.floor((ms % MILLISECONDS_PER_HOUR) / MILLISECONDS_PER_MINUTE);
|
|
358
|
-
const seconds = Math.floor((ms % MILLISECONDS_PER_MINUTE) / MILLISECONDS_PER_SECOND);
|
|
369
|
+
function formatDurationCompact(ms, showHours = true) {
|
|
370
|
+
const hours = Math.floor(ms / constants_js_1.MILLISECONDS_PER_HOUR);
|
|
371
|
+
const minutes = Math.floor((ms % constants_js_1.MILLISECONDS_PER_HOUR) / constants_js_1.MILLISECONDS_PER_MINUTE);
|
|
372
|
+
const seconds = Math.floor((ms % constants_js_1.MILLISECONDS_PER_MINUTE) / constants_js_1.MILLISECONDS_PER_SECOND);
|
|
359
373
|
const pad = (n) => String(n).padStart(2, '0');
|
|
360
374
|
if (showHours || hours > 0) {
|
|
361
375
|
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
|
@@ -366,11 +380,10 @@ export function formatDurationCompact(ms, showHours = true) {
|
|
|
366
380
|
* Format a date/time for display in a calendar
|
|
367
381
|
* @param date - date to format
|
|
368
382
|
*/
|
|
369
|
-
|
|
383
|
+
function formatCalendarDate(date) {
|
|
370
384
|
const now = new Date();
|
|
371
|
-
const
|
|
372
|
-
const
|
|
373
|
-
const diffDays = Math.round((dateOnly.getTime() - today.getTime()) / MILLISECONDS_PER_DAY);
|
|
385
|
+
const dayDistance = (0, calculate_js_1.differenceInCalendarDays)(date, now);
|
|
386
|
+
const diffDays = date.getTime() >= now.getTime() ? dayDistance : -dayDistance;
|
|
374
387
|
if (diffDays === 0)
|
|
375
388
|
return 'Today';
|
|
376
389
|
if (diffDays === -1)
|
package/dist/format.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,aAAa,EACd,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,aAAa,EACd,MAAM,gBAAgB,CAAC;AAIxB;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA2E9E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA+CvE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,KAAK,GAAG,KAAK,GAAG,KAAa,GAAG,MAAM,CAcpF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyDtD;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA4C9D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAE,IAAiB,GAAG,MAAM,CAuClF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,IAAI,EACT,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CACjC,GACL,MAAM,CA6BR;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,GAAE,OAAc,GAAG,MAAM,CAYnF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuBrD"}
|
|
@@ -1,15 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* @fileoverview Healthcare utilities for medical scheduling and compliance timing
|
|
3
4
|
* Provides medication schedules, shift patterns, on-call rotations, and compliance windows
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_MEDICATION_CONFIG = exports.SHIFT_DURATIONS = exports.MEDICATION_FREQUENCIES = void 0;
|
|
8
|
+
exports.getMedicationTimes = getMedicationTimes;
|
|
9
|
+
exports.getNextMedicationTime = getNextMedicationTime;
|
|
10
|
+
exports.parseMedicationFrequency = parseMedicationFrequency;
|
|
11
|
+
exports.generateShiftSchedule = generateShiftSchedule;
|
|
12
|
+
exports.getShiftForTime = getShiftForTime;
|
|
13
|
+
exports.isOnShift = isOnShift;
|
|
14
|
+
exports.createOnCallRotation = createOnCallRotation;
|
|
15
|
+
exports.getOnCallStaff = getOnCallStaff;
|
|
16
|
+
exports.isWithinComplianceWindow = isWithinComplianceWindow;
|
|
17
|
+
exports.getComplianceDeadline = getComplianceDeadline;
|
|
18
|
+
exports.timeUntilDeadline = timeUntilDeadline;
|
|
19
|
+
exports.calculateRestBetweenShifts = calculateRestBetweenShifts;
|
|
20
|
+
const duration_js_1 = require("./duration.cjs");
|
|
6
21
|
// ============================================================================
|
|
7
22
|
// Constants
|
|
8
23
|
// ============================================================================
|
|
9
24
|
/**
|
|
10
25
|
* Number of doses per day for each frequency
|
|
11
26
|
*/
|
|
12
|
-
|
|
27
|
+
exports.MEDICATION_FREQUENCIES = {
|
|
13
28
|
'QD': 1,
|
|
14
29
|
'BID': 2,
|
|
15
30
|
'TID': 3,
|
|
@@ -23,7 +38,7 @@ export const MEDICATION_FREQUENCIES = {
|
|
|
23
38
|
/**
|
|
24
39
|
* Hours per shift pattern
|
|
25
40
|
*/
|
|
26
|
-
|
|
41
|
+
exports.SHIFT_DURATIONS = {
|
|
27
42
|
'8hr': 8,
|
|
28
43
|
'12hr': 12,
|
|
29
44
|
'24hr': 24
|
|
@@ -31,7 +46,7 @@ export const SHIFT_DURATIONS = {
|
|
|
31
46
|
/**
|
|
32
47
|
* Default medication timing config
|
|
33
48
|
*/
|
|
34
|
-
|
|
49
|
+
exports.DEFAULT_MEDICATION_CONFIG = {
|
|
35
50
|
wakeTime: '07:00',
|
|
36
51
|
sleepTime: '22:00',
|
|
37
52
|
withMeals: false
|
|
@@ -76,10 +91,10 @@ function setTimeOnDate(date, hour, minute) {
|
|
|
76
91
|
* // Returns [6:00 AM, 1:30 PM, 9:00 PM] (three times daily)
|
|
77
92
|
* ```
|
|
78
93
|
*/
|
|
79
|
-
|
|
94
|
+
function getMedicationTimes(date, frequency, config) {
|
|
80
95
|
const d = toDate(date);
|
|
81
|
-
const cfg = { ...DEFAULT_MEDICATION_CONFIG, ...config };
|
|
82
|
-
const doses = MEDICATION_FREQUENCIES[frequency];
|
|
96
|
+
const cfg = { ...exports.DEFAULT_MEDICATION_CONFIG, ...config };
|
|
97
|
+
const doses = exports.MEDICATION_FREQUENCIES[frequency];
|
|
83
98
|
if (doses === null) {
|
|
84
99
|
return []; // PRN - as needed
|
|
85
100
|
}
|
|
@@ -125,7 +140,7 @@ export function getMedicationTimes(date, frequency, config) {
|
|
|
125
140
|
* // Returns 7:00 PM on same day (next BID dose after 10 AM)
|
|
126
141
|
* ```
|
|
127
142
|
*/
|
|
128
|
-
|
|
143
|
+
function getNextMedicationTime(after, frequency, config) {
|
|
129
144
|
if (frequency === 'PRN') {
|
|
130
145
|
return null;
|
|
131
146
|
}
|
|
@@ -156,7 +171,7 @@ export function getNextMedicationTime(after, frequency, config) {
|
|
|
156
171
|
* parseMedicationFrequency('invalid'); // null
|
|
157
172
|
* ```
|
|
158
173
|
*/
|
|
159
|
-
|
|
174
|
+
function parseMedicationFrequency(freq) {
|
|
160
175
|
const normalized = freq.toLowerCase();
|
|
161
176
|
const mapping = {
|
|
162
177
|
'qd': 'QD',
|
|
@@ -202,10 +217,10 @@ export function parseMedicationFrequency(freq) {
|
|
|
202
217
|
* // Returns 4 shifts: day/night on 15th, day/night on 16th
|
|
203
218
|
* ```
|
|
204
219
|
*/
|
|
205
|
-
|
|
220
|
+
function generateShiftSchedule(start, end, config) {
|
|
206
221
|
const startDate = toDate(start);
|
|
207
222
|
const endDate = toDate(end);
|
|
208
|
-
const shiftHours = SHIFT_DURATIONS[config.pattern];
|
|
223
|
+
const shiftHours = exports.SHIFT_DURATIONS[config.pattern];
|
|
209
224
|
const shiftsPerDay = 24 / shiftHours;
|
|
210
225
|
const shifts = [];
|
|
211
226
|
const current = new Date(startDate.getTime());
|
|
@@ -241,9 +256,9 @@ export function generateShiftSchedule(start, end, config) {
|
|
|
241
256
|
* // Returns { start: 7:00 AM, end: 3:00 PM } (day shift)
|
|
242
257
|
* ```
|
|
243
258
|
*/
|
|
244
|
-
|
|
259
|
+
function getShiftForTime(date, config) {
|
|
245
260
|
const d = toDate(date);
|
|
246
|
-
const shiftHours = SHIFT_DURATIONS[config.pattern];
|
|
261
|
+
const shiftHours = exports.SHIFT_DURATIONS[config.pattern];
|
|
247
262
|
const shiftMs = shiftHours * 60 * 60 * 1000;
|
|
248
263
|
// Find the shift start that contains this time
|
|
249
264
|
const dayStart = new Date(d.getTime());
|
|
@@ -277,10 +292,10 @@ export function getShiftForTime(date, config) {
|
|
|
277
292
|
* ); // true (10 AM is during 7 AM - 3 PM shift)
|
|
278
293
|
* ```
|
|
279
294
|
*/
|
|
280
|
-
|
|
295
|
+
function isOnShift(date, shiftStart, config) {
|
|
281
296
|
const d = toDate(date);
|
|
282
297
|
const start = toDate(shiftStart);
|
|
283
|
-
const shiftHours = SHIFT_DURATIONS[config.pattern];
|
|
298
|
+
const shiftHours = exports.SHIFT_DURATIONS[config.pattern];
|
|
284
299
|
const shiftEnd = new Date(start.getTime() + shiftHours * 60 * 60 * 1000);
|
|
285
300
|
return d.getTime() >= start.getTime() && d.getTime() < shiftEnd.getTime();
|
|
286
301
|
}
|
|
@@ -307,7 +322,7 @@ export function isOnShift(date, shiftStart, config) {
|
|
|
307
322
|
* // Returns 3 slots, one per doctor per day
|
|
308
323
|
* ```
|
|
309
324
|
*/
|
|
310
|
-
|
|
325
|
+
function createOnCallRotation(start, end, staff, hoursPerShift = 24) {
|
|
311
326
|
if (staff.length === 0) {
|
|
312
327
|
return [];
|
|
313
328
|
}
|
|
@@ -343,7 +358,7 @@ export function createOnCallRotation(start, end, staff, hoursPerShift = 24) {
|
|
|
343
358
|
* // Returns 'Dr. Jones' (whoever is on call at 3 AM on the 16th)
|
|
344
359
|
* ```
|
|
345
360
|
*/
|
|
346
|
-
|
|
361
|
+
function getOnCallStaff(date, rotation) {
|
|
347
362
|
const d = toDate(date);
|
|
348
363
|
for (const slot of rotation) {
|
|
349
364
|
if (d.getTime() >= slot.start.getTime() && d.getTime() < slot.end.getTime()) {
|
|
@@ -370,7 +385,7 @@ export function getOnCallStaff(date, rotation) {
|
|
|
370
385
|
* ); // true (event occurred before deadline)
|
|
371
386
|
* ```
|
|
372
387
|
*/
|
|
373
|
-
|
|
388
|
+
function isWithinComplianceWindow(event, deadline) {
|
|
374
389
|
const eventDate = toDate(event);
|
|
375
390
|
const deadlineDate = toDate(deadline);
|
|
376
391
|
return eventDate.getTime() <= deadlineDate.getTime();
|
|
@@ -391,7 +406,7 @@ export function isWithinComplianceWindow(event, deadline) {
|
|
|
391
406
|
* // Returns 2024-01-18T08:00:00 (72 hours later)
|
|
392
407
|
* ```
|
|
393
408
|
*/
|
|
394
|
-
|
|
409
|
+
function getComplianceDeadline(event, windowHours) {
|
|
395
410
|
const eventDate = toDate(event);
|
|
396
411
|
return new Date(eventDate.getTime() + windowHours * 60 * 60 * 1000);
|
|
397
412
|
}
|
|
@@ -411,14 +426,14 @@ export function getComplianceDeadline(event, windowHours) {
|
|
|
411
426
|
* // Returns Duration of 24 hours
|
|
412
427
|
* ```
|
|
413
428
|
*/
|
|
414
|
-
|
|
429
|
+
function timeUntilDeadline(event, deadline) {
|
|
415
430
|
const eventDate = toDate(event);
|
|
416
431
|
const deadlineDate = toDate(deadline);
|
|
417
432
|
const diff = deadlineDate.getTime() - eventDate.getTime();
|
|
418
433
|
if (diff < 0) {
|
|
419
434
|
return null; // Already past deadline
|
|
420
435
|
}
|
|
421
|
-
return Duration.fromMilliseconds(diff);
|
|
436
|
+
return duration_js_1.Duration.fromMilliseconds(diff);
|
|
422
437
|
}
|
|
423
438
|
// ============================================================================
|
|
424
439
|
// Utility Functions
|
|
@@ -439,7 +454,7 @@ export function timeUntilDeadline(event, deadline) {
|
|
|
439
454
|
* // Returns 12 (hours of rest)
|
|
440
455
|
* ```
|
|
441
456
|
*/
|
|
442
|
-
|
|
457
|
+
function calculateRestBetweenShifts(shift1End, shift2Start) {
|
|
443
458
|
const end = toDate(shift1End);
|
|
444
459
|
const start = toDate(shift2Start);
|
|
445
460
|
const diffMs = start.getTime() - end.getTime();
|