@thi.ng/date 2.3.20 → 2.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/CHANGELOG.md +13 -1
- package/README.md +12 -2
- package/duration.d.ts +22 -0
- package/duration.js +44 -0
- package/format.d.ts +93 -1
- package/format.js +164 -3
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +9 -6
- package/relative.d.ts +1 -64
- package/relative.js +1 -131
- package/timecode.d.ts +0 -7
- package/timecode.js +1 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**:
|
|
3
|
+
- **Last updated**: 2023-01-10T15:20:18Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,18 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [2.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/date@2.4.0) (2022-12-29)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add formatDuration(), internal restructure ([d610a8a](https://github.com/thi-ng/umbrella/commit/d610a8a))
|
|
17
|
+
- add formatDuration() & formatDurationParts()
|
|
18
|
+
- add composeDuration()
|
|
19
|
+
- refactor formatRelativeParts()
|
|
20
|
+
- move all formatting fns to format.ts
|
|
21
|
+
- move decomposeDuration() to duration.ts
|
|
22
|
+
- add tests
|
|
23
|
+
|
|
12
24
|
## [2.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/date@2.3.0) (2022-06-15)
|
|
13
25
|
|
|
14
26
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ For Node.js REPL:
|
|
|
57
57
|
const date = await import("@thi.ng/date");
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 5.
|
|
60
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 5.12 KB
|
|
61
61
|
|
|
62
62
|
## Dependencies
|
|
63
63
|
|
|
@@ -296,6 +296,16 @@ withLocale(DE_LONG, () => formatRelativeParts("2020-01-01 12:34"))
|
|
|
296
296
|
// returns tuple of: [sign, years, months, days, hours, mins, secs, millis]
|
|
297
297
|
decomposeDifference("2020-01-01 12:34", Date.now())
|
|
298
298
|
// [-1, 1, 6, 15, 23, 38, 9, 703]
|
|
299
|
+
|
|
300
|
+
// format a duration (in ms), optionally with given precision
|
|
301
|
+
formatDuration(45296000)
|
|
302
|
+
// "12 h, 34 min, 56 s"
|
|
303
|
+
|
|
304
|
+
formatDuration(45296000, "h")
|
|
305
|
+
// "13 h"
|
|
306
|
+
|
|
307
|
+
formatDuration(45296000,"d")
|
|
308
|
+
// "< 1 d"
|
|
299
309
|
```
|
|
300
310
|
|
|
301
311
|
### Date & time formatters
|
|
@@ -449,4 +459,4 @@ If this project contributes to an academic publication, please cite it as:
|
|
|
449
459
|
|
|
450
460
|
## License
|
|
451
461
|
|
|
452
|
-
© 2020 -
|
|
462
|
+
© 2020 - 2023 Karsten Schmidt // Apache License 2.0
|
package/duration.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Precision } from "./api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Decomposes given duration (in milliseconds) into a tuple of: `[year, month,
|
|
4
|
+
* day, hour, minute, second, millis]`.
|
|
5
|
+
*
|
|
6
|
+
* @param dur -
|
|
7
|
+
*/
|
|
8
|
+
export declare const decomposeDuration: (dur: number) => number[];
|
|
9
|
+
/**
|
|
10
|
+
* Computes a duration (in milliseconds) from given parts. Also see
|
|
11
|
+
* {@link decomposeDuration}.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* composeDuration({ h: 12, m: 34, s: 56 })
|
|
16
|
+
* // 45296000
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @param parts
|
|
20
|
+
*/
|
|
21
|
+
export declare const composeDuration: (parts: Partial<Record<Precision, number>>) => number;
|
|
22
|
+
//# sourceMappingURL=duration.d.ts.map
|
package/duration.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, } from "./api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Decomposes given duration (in milliseconds) into a tuple of: `[year, month,
|
|
4
|
+
* day, hour, minute, second, millis]`.
|
|
5
|
+
*
|
|
6
|
+
* @param dur -
|
|
7
|
+
*/
|
|
8
|
+
export const decomposeDuration = (dur) => {
|
|
9
|
+
const year = (dur / YEAR) | 0;
|
|
10
|
+
dur -= year * YEAR;
|
|
11
|
+
const month = (dur / MONTH) | 0;
|
|
12
|
+
dur -= month * MONTH;
|
|
13
|
+
const day = (dur / DAY) | 0;
|
|
14
|
+
dur -= day * DAY;
|
|
15
|
+
const hour = (dur / HOUR) | 0;
|
|
16
|
+
dur -= hour * HOUR;
|
|
17
|
+
const min = (dur / MINUTE) | 0;
|
|
18
|
+
dur -= min * MINUTE;
|
|
19
|
+
const sec = (dur / SECOND) | 0;
|
|
20
|
+
dur -= sec * SECOND;
|
|
21
|
+
return [year, month, day, hour, min, sec, dur];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Computes a duration (in milliseconds) from given parts. Also see
|
|
25
|
+
* {@link decomposeDuration}.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* composeDuration({ h: 12, m: 34, s: 56 })
|
|
30
|
+
* // 45296000
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param parts
|
|
34
|
+
*/
|
|
35
|
+
export const composeDuration = (parts) => {
|
|
36
|
+
let dur = (parts.y || 0) * YEAR;
|
|
37
|
+
dur += (parts.M || 0) * MONTH;
|
|
38
|
+
dur += (parts.d || 0) * DAY;
|
|
39
|
+
dur += (parts.h || 0) * HOUR;
|
|
40
|
+
dur += (parts.m || 0) * MINUTE;
|
|
41
|
+
dur += (parts.s || 0) * SECOND;
|
|
42
|
+
dur += parts.t || 0;
|
|
43
|
+
return dur;
|
|
44
|
+
};
|
package/format.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormatFn, MaybeDate } from "./api.js";
|
|
1
|
+
import { FormatFn, MaybeDate, Precision } from "./api.js";
|
|
2
2
|
export declare const FORMATTERS: Record<string, FormatFn>;
|
|
3
3
|
/**
|
|
4
4
|
* Returns a new date formatter for given array of format strings (or
|
|
@@ -78,4 +78,96 @@ export declare const FMT_ISO_SHORT: (x?: MaybeDate, utc?: boolean) => string;
|
|
|
78
78
|
* `2020-09-19T17:08:01.123Z`
|
|
79
79
|
*/
|
|
80
80
|
export declare const FMT_ISO: (x?: MaybeDate, utc?: boolean) => string;
|
|
81
|
+
/**
|
|
82
|
+
* Takes a `date` and optional reference `base` date and (also optional
|
|
83
|
+
* `prec`ision, i.e. number of fractional digits, default: 0). Computes the
|
|
84
|
+
* difference between given dates and returns it as formatted string.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
88
|
+
* (default: 100).
|
|
89
|
+
*
|
|
90
|
+
* @see {@link formatRelativeParts} for alternative output.
|
|
91
|
+
*
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* formatRelative("2020-06-01", "2021-07-01")
|
|
96
|
+
* // "1 year ago"
|
|
97
|
+
*
|
|
98
|
+
* formatRelative("2020-08-01", "2021-07-01")
|
|
99
|
+
* // "11 months ago"
|
|
100
|
+
*
|
|
101
|
+
* formatRelative("2021-07-01 13:45", "2021-07-01 12:05")
|
|
102
|
+
* // "in 2 hours"
|
|
103
|
+
*
|
|
104
|
+
* formatRelative("2021-07-01 12:23:24", "2021-07-01 12:05")
|
|
105
|
+
* // "in 18 minutes"
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @param date -
|
|
109
|
+
* @param base -
|
|
110
|
+
* @param prec -
|
|
111
|
+
* @param eps -
|
|
112
|
+
*/
|
|
113
|
+
export declare const formatRelative: (date: MaybeDate, base?: MaybeDate, prec?: number, eps?: number) => string;
|
|
114
|
+
/**
|
|
115
|
+
* Similar to {@link formatRelative}, however precision is specified as
|
|
116
|
+
* {@link Precision} (default: seconds). The result will be formatted as a
|
|
117
|
+
* string made up of parts of increasing precision (years, months, days, hours,
|
|
118
|
+
* etc.). Only non-zero parts will be mentioned.
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
122
|
+
* (default: 100). In all other cases uses {@link decomposeDifference} for
|
|
123
|
+
* given dates to extract parts for formatting.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* // with default precision (seconds)
|
|
128
|
+
* formatRelativeParts("2022-09-01 12:23:24", "2021-07-01 12:05")
|
|
129
|
+
* // "in 1 year, 2 months, 21 hours, 18 minutes, 24 seconds"
|
|
130
|
+
*
|
|
131
|
+
* // with day precision
|
|
132
|
+
* formatRelativeParts("2012-12-25 17:59", "2021-07-01 12:05", "d")
|
|
133
|
+
* // "8 years, 6 months, 5 days ago"
|
|
134
|
+
*
|
|
135
|
+
* formatRelativeParts("2021-07-01 17:59", "2021-07-01 12:05", "d")
|
|
136
|
+
* // "in less than a day"
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @param date -
|
|
140
|
+
* @param base -
|
|
141
|
+
* @param prec -
|
|
142
|
+
* @param eps -
|
|
143
|
+
*/
|
|
144
|
+
export declare const formatRelativeParts: (date: MaybeDate, base?: MaybeDate, prec?: Precision, eps?: number) => string;
|
|
145
|
+
/**
|
|
146
|
+
* Formats given duration (in ms) to given precision and using current
|
|
147
|
+
* {@link LOCALE}.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* formatDuration(45296000)
|
|
152
|
+
* // "12 h, 34 min, 56 s"
|
|
153
|
+
*
|
|
154
|
+
* formatDuration(45296000, "h")
|
|
155
|
+
* // "13 h"
|
|
156
|
+
*
|
|
157
|
+
* formatDuration(45296000,"d")
|
|
158
|
+
* // "< 1 d"
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @param dur
|
|
162
|
+
* @param prec
|
|
163
|
+
*/
|
|
164
|
+
export declare const formatDuration: (dur: number, prec?: Precision) => string;
|
|
165
|
+
/**
|
|
166
|
+
* Formats an already decomposed duration (in most case you'll want to use
|
|
167
|
+
* {@link formatDuration}).
|
|
168
|
+
*
|
|
169
|
+
* @param parts
|
|
170
|
+
* @param prec
|
|
171
|
+
*/
|
|
172
|
+
export declare const formatDurationParts: (parts: number[], prec?: Precision) => string;
|
|
81
173
|
//# sourceMappingURL=format.d.ts.map
|
package/format.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { isFunction } from "@thi.ng/checks/is-function";
|
|
2
2
|
import { isString } from "@thi.ng/checks/is-string";
|
|
3
3
|
import { Z2, Z3, Z4 } from "@thi.ng/strings/pad-left";
|
|
4
|
-
import { MINUTE } from "./api.js";
|
|
5
|
-
import { ensureDate } from "./checks.js";
|
|
6
|
-
import {
|
|
4
|
+
import { DAY, HOUR, MINUTE, MONTH, SECOND, YEAR, } from "./api.js";
|
|
5
|
+
import { ensureDate, ensureEpoch } from "./checks.js";
|
|
6
|
+
import { decomposeDuration } from "./duration.js";
|
|
7
|
+
import { LOCALE, tense, units, unitsLessThan } from "./i18n.js";
|
|
8
|
+
import { __idToPrecision, __precisionToID } from "./internal/precision.js";
|
|
9
|
+
import { decomposeDifference, difference } from "./relative.js";
|
|
7
10
|
import { weekInYear } from "./units.js";
|
|
8
11
|
export const FORMATTERS = {
|
|
9
12
|
/**
|
|
@@ -239,3 +242,161 @@ export const FMT_ISO_SHORT = defFormat(["yyyy", "-", "MM", "-", "dd", "T", "HH",
|
|
|
239
242
|
*/
|
|
240
243
|
// prettier-ignore
|
|
241
244
|
export const FMT_ISO = defFormat(["yyyy", "-", "MM", "-", "dd", "T", "HH", ":", "mm", ":", "ss", ".", "SS", "ZZ"]);
|
|
245
|
+
/**
|
|
246
|
+
* Takes a `date` and optional reference `base` date and (also optional
|
|
247
|
+
* `prec`ision, i.e. number of fractional digits, default: 0). Computes the
|
|
248
|
+
* difference between given dates and returns it as formatted string.
|
|
249
|
+
*
|
|
250
|
+
* @remarks
|
|
251
|
+
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
252
|
+
* (default: 100).
|
|
253
|
+
*
|
|
254
|
+
* @see {@link formatRelativeParts} for alternative output.
|
|
255
|
+
*
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```ts
|
|
259
|
+
* formatRelative("2020-06-01", "2021-07-01")
|
|
260
|
+
* // "1 year ago"
|
|
261
|
+
*
|
|
262
|
+
* formatRelative("2020-08-01", "2021-07-01")
|
|
263
|
+
* // "11 months ago"
|
|
264
|
+
*
|
|
265
|
+
* formatRelative("2021-07-01 13:45", "2021-07-01 12:05")
|
|
266
|
+
* // "in 2 hours"
|
|
267
|
+
*
|
|
268
|
+
* formatRelative("2021-07-01 12:23:24", "2021-07-01 12:05")
|
|
269
|
+
* // "in 18 minutes"
|
|
270
|
+
* ```
|
|
271
|
+
*
|
|
272
|
+
* @param date -
|
|
273
|
+
* @param base -
|
|
274
|
+
* @param prec -
|
|
275
|
+
* @param eps -
|
|
276
|
+
*/
|
|
277
|
+
export const formatRelative = (date, base = new Date(), prec = 0, eps = 100) => {
|
|
278
|
+
const delta = difference(date, base);
|
|
279
|
+
if (Math.abs(delta) < eps)
|
|
280
|
+
return LOCALE.now;
|
|
281
|
+
let abs = Math.abs(delta);
|
|
282
|
+
let unit;
|
|
283
|
+
if (abs < SECOND) {
|
|
284
|
+
unit = "t";
|
|
285
|
+
}
|
|
286
|
+
else if (abs < MINUTE) {
|
|
287
|
+
abs /= SECOND;
|
|
288
|
+
unit = "s";
|
|
289
|
+
}
|
|
290
|
+
else if (abs < HOUR) {
|
|
291
|
+
abs /= MINUTE;
|
|
292
|
+
unit = "m";
|
|
293
|
+
}
|
|
294
|
+
else if (abs < DAY) {
|
|
295
|
+
abs /= HOUR;
|
|
296
|
+
unit = "h";
|
|
297
|
+
}
|
|
298
|
+
else if (abs < MONTH) {
|
|
299
|
+
abs /= DAY;
|
|
300
|
+
unit = "d";
|
|
301
|
+
}
|
|
302
|
+
else if (abs < YEAR) {
|
|
303
|
+
abs /= MONTH;
|
|
304
|
+
unit = "M";
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
abs /= YEAR;
|
|
308
|
+
unit = "y";
|
|
309
|
+
}
|
|
310
|
+
const exp = 10 ** -prec;
|
|
311
|
+
abs = Math.round(abs / exp) * exp;
|
|
312
|
+
return tense(delta, `${abs.toFixed(prec)} ${units(abs, unit, true, true)}`);
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Similar to {@link formatRelative}, however precision is specified as
|
|
316
|
+
* {@link Precision} (default: seconds). The result will be formatted as a
|
|
317
|
+
* string made up of parts of increasing precision (years, months, days, hours,
|
|
318
|
+
* etc.). Only non-zero parts will be mentioned.
|
|
319
|
+
*
|
|
320
|
+
* @remarks
|
|
321
|
+
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
322
|
+
* (default: 100). In all other cases uses {@link decomposeDifference} for
|
|
323
|
+
* given dates to extract parts for formatting.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* // with default precision (seconds)
|
|
328
|
+
* formatRelativeParts("2022-09-01 12:23:24", "2021-07-01 12:05")
|
|
329
|
+
* // "in 1 year, 2 months, 21 hours, 18 minutes, 24 seconds"
|
|
330
|
+
*
|
|
331
|
+
* // with day precision
|
|
332
|
+
* formatRelativeParts("2012-12-25 17:59", "2021-07-01 12:05", "d")
|
|
333
|
+
* // "8 years, 6 months, 5 days ago"
|
|
334
|
+
*
|
|
335
|
+
* formatRelativeParts("2021-07-01 17:59", "2021-07-01 12:05", "d")
|
|
336
|
+
* // "in less than a day"
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* @param date -
|
|
340
|
+
* @param base -
|
|
341
|
+
* @param prec -
|
|
342
|
+
* @param eps -
|
|
343
|
+
*/
|
|
344
|
+
export const formatRelativeParts = (date, base = Date.now(), prec = "s", eps = 1000) => {
|
|
345
|
+
date = ensureEpoch(date);
|
|
346
|
+
base = ensureEpoch(base);
|
|
347
|
+
if (Math.abs(date - base) < eps)
|
|
348
|
+
return LOCALE.now;
|
|
349
|
+
const [sign, ...parts] = decomposeDifference(date, base);
|
|
350
|
+
return tense(sign, formatDurationParts(parts, prec));
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Formats given duration (in ms) to given precision and using current
|
|
354
|
+
* {@link LOCALE}.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* formatDuration(45296000)
|
|
359
|
+
* // "12 h, 34 min, 56 s"
|
|
360
|
+
*
|
|
361
|
+
* formatDuration(45296000, "h")
|
|
362
|
+
* // "13 h"
|
|
363
|
+
*
|
|
364
|
+
* formatDuration(45296000,"d")
|
|
365
|
+
* // "< 1 d"
|
|
366
|
+
* ```
|
|
367
|
+
*
|
|
368
|
+
* @param dur
|
|
369
|
+
* @param prec
|
|
370
|
+
*/
|
|
371
|
+
export const formatDuration = (dur, prec = "s") => formatDurationParts(decomposeDuration(dur), prec);
|
|
372
|
+
/**
|
|
373
|
+
* Formats an already decomposed duration (in most case you'll want to use
|
|
374
|
+
* {@link formatDuration}).
|
|
375
|
+
*
|
|
376
|
+
* @param parts
|
|
377
|
+
* @param prec
|
|
378
|
+
*/
|
|
379
|
+
export const formatDurationParts = (parts, prec = "s") => {
|
|
380
|
+
const precID = __precisionToID(prec);
|
|
381
|
+
let maxID = precID;
|
|
382
|
+
while (!parts[maxID] && maxID > 0)
|
|
383
|
+
maxID--;
|
|
384
|
+
let minID = parts.findIndex((x) => x > 0);
|
|
385
|
+
minID < 0 && (minID = maxID);
|
|
386
|
+
maxID = Math.min(Math.max(maxID, minID), precID);
|
|
387
|
+
if (minID <= precID && precID < 6) {
|
|
388
|
+
parts[maxID] = Math.round(parts[maxID] + parts[maxID + 1] / [12, 31, 24, 60, 60, 1000][maxID]);
|
|
389
|
+
}
|
|
390
|
+
return parts
|
|
391
|
+
.slice(0, maxID + 1)
|
|
392
|
+
.map((x, i) => {
|
|
393
|
+
let unit = LOCALE.units[__idToPrecision(i)];
|
|
394
|
+
return x > 0
|
|
395
|
+
? units(x, unit, true)
|
|
396
|
+
: i === maxID && maxID < 6
|
|
397
|
+
? unitsLessThan(1, unit, true)
|
|
398
|
+
: "";
|
|
399
|
+
})
|
|
400
|
+
.filter((x) => !!x)
|
|
401
|
+
.join(", ");
|
|
402
|
+
};
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/date",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Datetime types, relative dates, math, iterators, composable formatters, locales",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"test": "testament test"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@thi.ng/api": "^8.6.
|
|
38
|
-
"@thi.ng/checks": "^3.3.
|
|
39
|
-
"@thi.ng/strings": "^3.3.
|
|
37
|
+
"@thi.ng/api": "^8.6.3",
|
|
38
|
+
"@thi.ng/checks": "^3.3.7",
|
|
39
|
+
"@thi.ng/strings": "^3.3.23"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@microsoft/api-extractor": "^7.33.7",
|
|
43
|
-
"@thi.ng/testament": "^0.3.
|
|
43
|
+
"@thi.ng/testament": "^0.3.9",
|
|
44
44
|
"rimraf": "^3.0.2",
|
|
45
45
|
"tools": "^0.0.1",
|
|
46
46
|
"typedoc": "^0.23.22",
|
|
@@ -89,6 +89,9 @@
|
|
|
89
89
|
"./datetime": {
|
|
90
90
|
"default": "./datetime.js"
|
|
91
91
|
},
|
|
92
|
+
"./duration": {
|
|
93
|
+
"default": "./duration.js"
|
|
94
|
+
},
|
|
92
95
|
"./format": {
|
|
93
96
|
"default": "./format.js"
|
|
94
97
|
},
|
|
@@ -129,5 +132,5 @@
|
|
|
129
132
|
"thi.ng": {
|
|
130
133
|
"year": 2020
|
|
131
134
|
},
|
|
132
|
-
"gitHead": "
|
|
135
|
+
"gitHead": "3f0b3e2a7c82aefc7e46fb4338369836b5e1b8cf\n"
|
|
133
136
|
}
|
package/relative.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MaybeDate, Period
|
|
1
|
+
import { MaybeDate, Period } from "./api.js";
|
|
2
2
|
import { DateTime } from "./datetime.js";
|
|
3
3
|
/**
|
|
4
4
|
* Takes a relative time `offset` string in plain english and an optional `base`
|
|
@@ -66,67 +66,4 @@ export declare const difference: (a: MaybeDate, b: MaybeDate) => number;
|
|
|
66
66
|
* @param b -
|
|
67
67
|
*/
|
|
68
68
|
export declare const decomposeDifference: (a: MaybeDate, b?: MaybeDate) => number[];
|
|
69
|
-
/**
|
|
70
|
-
* Takes a `date` and optional reference `base` date and (also optional
|
|
71
|
-
* `prec`ision, i.e. number of fractional digits, default: 0). Computes the difference
|
|
72
|
-
* between given dates and returns it as formatted string.
|
|
73
|
-
*
|
|
74
|
-
* @remarks
|
|
75
|
-
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds (default: 100).
|
|
76
|
-
*
|
|
77
|
-
* @see {@link formatRelativeParts} for alternative output.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```ts
|
|
82
|
-
* formatRelative("2020-06-01", "2021-07-01")
|
|
83
|
-
* // "1 year ago"
|
|
84
|
-
*
|
|
85
|
-
* formatRelative("2020-08-01", "2021-07-01")
|
|
86
|
-
* // "11 months ago"
|
|
87
|
-
*
|
|
88
|
-
* formatRelative("2021-07-01 13:45", "2021-07-01 12:05")
|
|
89
|
-
* // "in 2 hours"
|
|
90
|
-
*
|
|
91
|
-
* formatRelative("2021-07-01 12:23:24", "2021-07-01 12:05")
|
|
92
|
-
* // "in 18 minutes"
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
|
-
* @param date -
|
|
96
|
-
* @param base -
|
|
97
|
-
* @param prec -
|
|
98
|
-
* @param eps -
|
|
99
|
-
*/
|
|
100
|
-
export declare const formatRelative: (date: MaybeDate, base?: MaybeDate, prec?: number, eps?: number) => string;
|
|
101
|
-
/**
|
|
102
|
-
* Similar to {@link formatRelative}, however precision is specified as
|
|
103
|
-
* {@link Precision} (default: seconds). The result will be formatted as a
|
|
104
|
-
* string made up of parts of increasing precision (years, months, days, hours,
|
|
105
|
-
* etc.). Only non-zero parts will be mentioned.
|
|
106
|
-
*
|
|
107
|
-
* @remarks
|
|
108
|
-
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
109
|
-
* (default: 100). In all other cases uses {@link decomposeDifference} for
|
|
110
|
-
* given dates to extract parts for formatting.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```ts
|
|
114
|
-
* // with default precision (seconds)
|
|
115
|
-
* formatRelativeParts("2022-09-01 12:23:24", "2021-07-01 12:05")
|
|
116
|
-
* // "in 1 year, 2 months, 21 hours, 18 minutes, 24 seconds"
|
|
117
|
-
*
|
|
118
|
-
* // with day precision
|
|
119
|
-
* formatRelativeParts("2012-12-25 17:59", "2021-07-01 12:05", "d")
|
|
120
|
-
* // "8 years, 6 months, 5 days ago"
|
|
121
|
-
*
|
|
122
|
-
* formatRelativeParts("2021-07-01 17:59", "2021-07-01 12:05", "d")
|
|
123
|
-
* // "in less than a day"
|
|
124
|
-
* ```
|
|
125
|
-
*
|
|
126
|
-
* @param date -
|
|
127
|
-
* @param base -
|
|
128
|
-
* @param prec -
|
|
129
|
-
* @param eps -
|
|
130
|
-
*/
|
|
131
|
-
export declare const formatRelativeParts: (date: MaybeDate, base?: MaybeDate, prec?: Precision, eps?: number) => string;
|
|
132
69
|
//# sourceMappingURL=relative.d.ts.map
|
package/relative.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { DAY, HOUR, MINUTE,
|
|
1
|
+
import { DAY, HOUR, MINUTE, SECOND } from "./api.js";
|
|
2
2
|
import { ensureEpoch } from "./checks.js";
|
|
3
3
|
import { dateTime, ensureDateTime } from "./datetime.js";
|
|
4
|
-
import { LOCALE, tense, units, unitsLessThan } from "./i18n.js";
|
|
5
4
|
import { EN_LONG, EN_SHORT } from "./i18n/en.js";
|
|
6
|
-
import { __idToPrecision, __precisionToID } from "./internal/precision.js";
|
|
7
5
|
/**
|
|
8
6
|
* Takes a relative time `offset` string in plain english and an optional `base`
|
|
9
7
|
* date (default: now). Parses `offset` and returns new date with relative
|
|
@@ -165,131 +163,3 @@ export const decomposeDifference = (a, b = new Date()) => {
|
|
|
165
163
|
parts[3] = dur < 0 ? days(aa, bb) : days(bb, aa);
|
|
166
164
|
return parts;
|
|
167
165
|
};
|
|
168
|
-
/**
|
|
169
|
-
* Takes a `date` and optional reference `base` date and (also optional
|
|
170
|
-
* `prec`ision, i.e. number of fractional digits, default: 0). Computes the difference
|
|
171
|
-
* between given dates and returns it as formatted string.
|
|
172
|
-
*
|
|
173
|
-
* @remarks
|
|
174
|
-
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds (default: 100).
|
|
175
|
-
*
|
|
176
|
-
* @see {@link formatRelativeParts} for alternative output.
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* @example
|
|
180
|
-
* ```ts
|
|
181
|
-
* formatRelative("2020-06-01", "2021-07-01")
|
|
182
|
-
* // "1 year ago"
|
|
183
|
-
*
|
|
184
|
-
* formatRelative("2020-08-01", "2021-07-01")
|
|
185
|
-
* // "11 months ago"
|
|
186
|
-
*
|
|
187
|
-
* formatRelative("2021-07-01 13:45", "2021-07-01 12:05")
|
|
188
|
-
* // "in 2 hours"
|
|
189
|
-
*
|
|
190
|
-
* formatRelative("2021-07-01 12:23:24", "2021-07-01 12:05")
|
|
191
|
-
* // "in 18 minutes"
|
|
192
|
-
* ```
|
|
193
|
-
*
|
|
194
|
-
* @param date -
|
|
195
|
-
* @param base -
|
|
196
|
-
* @param prec -
|
|
197
|
-
* @param eps -
|
|
198
|
-
*/
|
|
199
|
-
export const formatRelative = (date, base = new Date(), prec = 0, eps = 100) => {
|
|
200
|
-
const delta = difference(date, base);
|
|
201
|
-
if (Math.abs(delta) < eps)
|
|
202
|
-
return LOCALE.now;
|
|
203
|
-
let abs = Math.abs(delta);
|
|
204
|
-
let unit;
|
|
205
|
-
if (abs < SECOND) {
|
|
206
|
-
unit = "t";
|
|
207
|
-
}
|
|
208
|
-
else if (abs < MINUTE) {
|
|
209
|
-
abs /= SECOND;
|
|
210
|
-
unit = "s";
|
|
211
|
-
}
|
|
212
|
-
else if (abs < HOUR) {
|
|
213
|
-
abs /= MINUTE;
|
|
214
|
-
unit = "m";
|
|
215
|
-
}
|
|
216
|
-
else if (abs < DAY) {
|
|
217
|
-
abs /= HOUR;
|
|
218
|
-
unit = "h";
|
|
219
|
-
}
|
|
220
|
-
else if (abs < MONTH) {
|
|
221
|
-
abs /= DAY;
|
|
222
|
-
unit = "d";
|
|
223
|
-
}
|
|
224
|
-
else if (abs < YEAR) {
|
|
225
|
-
abs /= MONTH;
|
|
226
|
-
unit = "M";
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
abs /= YEAR;
|
|
230
|
-
unit = "y";
|
|
231
|
-
}
|
|
232
|
-
const exp = 10 ** -prec;
|
|
233
|
-
abs = Math.round(abs / exp) * exp;
|
|
234
|
-
return tense(delta, `${abs.toFixed(prec)} ${units(abs, unit, true, true)}`);
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* Similar to {@link formatRelative}, however precision is specified as
|
|
238
|
-
* {@link Precision} (default: seconds). The result will be formatted as a
|
|
239
|
-
* string made up of parts of increasing precision (years, months, days, hours,
|
|
240
|
-
* etc.). Only non-zero parts will be mentioned.
|
|
241
|
-
*
|
|
242
|
-
* @remarks
|
|
243
|
-
* Returns {@link LOCALE.now} if absolute difference is < `eps` milliseconds
|
|
244
|
-
* (default: 100). In all other cases uses {@link decomposeDifference} for
|
|
245
|
-
* given dates to extract parts for formatting.
|
|
246
|
-
*
|
|
247
|
-
* @example
|
|
248
|
-
* ```ts
|
|
249
|
-
* // with default precision (seconds)
|
|
250
|
-
* formatRelativeParts("2022-09-01 12:23:24", "2021-07-01 12:05")
|
|
251
|
-
* // "in 1 year, 2 months, 21 hours, 18 minutes, 24 seconds"
|
|
252
|
-
*
|
|
253
|
-
* // with day precision
|
|
254
|
-
* formatRelativeParts("2012-12-25 17:59", "2021-07-01 12:05", "d")
|
|
255
|
-
* // "8 years, 6 months, 5 days ago"
|
|
256
|
-
*
|
|
257
|
-
* formatRelativeParts("2021-07-01 17:59", "2021-07-01 12:05", "d")
|
|
258
|
-
* // "in less than a day"
|
|
259
|
-
* ```
|
|
260
|
-
*
|
|
261
|
-
* @param date -
|
|
262
|
-
* @param base -
|
|
263
|
-
* @param prec -
|
|
264
|
-
* @param eps -
|
|
265
|
-
*/
|
|
266
|
-
export const formatRelativeParts = (date, base = Date.now(), prec = "s", eps = 1000) => {
|
|
267
|
-
date = ensureEpoch(date);
|
|
268
|
-
base = ensureEpoch(base);
|
|
269
|
-
if (Math.abs(date - base) < eps)
|
|
270
|
-
return LOCALE.now;
|
|
271
|
-
const [sign, ...parts] = decomposeDifference(date, base);
|
|
272
|
-
const precID = __precisionToID(prec);
|
|
273
|
-
let maxID = precID;
|
|
274
|
-
while (!parts[maxID] && maxID > 0)
|
|
275
|
-
maxID--;
|
|
276
|
-
let minID = parts.findIndex((x) => x > 0);
|
|
277
|
-
minID < 0 && (minID = maxID);
|
|
278
|
-
maxID = Math.min(Math.max(maxID, minID), precID);
|
|
279
|
-
if (minID <= precID && precID < 6) {
|
|
280
|
-
parts[maxID] = Math.round(parts[maxID] + parts[maxID + 1] / [12, 31, 24, 60, 60, 1000][maxID]);
|
|
281
|
-
}
|
|
282
|
-
const res = parts
|
|
283
|
-
.slice(0, maxID + 1)
|
|
284
|
-
.map((x, i) => {
|
|
285
|
-
let unit = LOCALE.units[__idToPrecision(i)];
|
|
286
|
-
return x > 0
|
|
287
|
-
? units(x, unit, true)
|
|
288
|
-
: i === maxID && maxID < 6
|
|
289
|
-
? unitsLessThan(1, unit, true)
|
|
290
|
-
: "";
|
|
291
|
-
})
|
|
292
|
-
.filter((x) => !!x)
|
|
293
|
-
.join(", ");
|
|
294
|
-
return tense(sign, res);
|
|
295
|
-
};
|
package/timecode.d.ts
CHANGED
|
@@ -26,11 +26,4 @@
|
|
|
26
26
|
* @param sep -
|
|
27
27
|
*/
|
|
28
28
|
export declare const defTimecode: (fps: number, sep?: ArrayLike<string>) => (t: number) => string;
|
|
29
|
-
/**
|
|
30
|
-
* Decomposes given duration (in milliseconds) into a tuple of: `[year, month,
|
|
31
|
-
* day, hour, minute, second, millis]`.
|
|
32
|
-
*
|
|
33
|
-
* @param dur -
|
|
34
|
-
*/
|
|
35
|
-
export declare const decomposeDuration: (dur: number) => number[];
|
|
36
29
|
//# sourceMappingURL=timecode.d.ts.map
|
package/timecode.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Z2 } from "@thi.ng/strings/pad-left";
|
|
2
|
-
import {
|
|
2
|
+
import { decomposeDuration } from "./duration.js";
|
|
3
3
|
/**
|
|
4
4
|
* Returns a time formatter for given FPS (frames / second, in [1..1000] range),
|
|
5
5
|
* e.g. `HH:mm:ss:ff`. The returned function takes a single arg (time in
|
|
@@ -44,24 +44,3 @@ export const defTimecode = (fps, sep = "::::") => {
|
|
|
44
44
|
return parts.join("");
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
/**
|
|
48
|
-
* Decomposes given duration (in milliseconds) into a tuple of: `[year, month,
|
|
49
|
-
* day, hour, minute, second, millis]`.
|
|
50
|
-
*
|
|
51
|
-
* @param dur -
|
|
52
|
-
*/
|
|
53
|
-
export const decomposeDuration = (dur) => {
|
|
54
|
-
const year = (dur / YEAR) | 0;
|
|
55
|
-
dur -= year * YEAR;
|
|
56
|
-
const month = (dur / MONTH) | 0;
|
|
57
|
-
dur -= month * MONTH;
|
|
58
|
-
const day = (dur / DAY) | 0;
|
|
59
|
-
dur -= day * DAY;
|
|
60
|
-
const hour = (dur / HOUR) | 0;
|
|
61
|
-
dur -= hour * HOUR;
|
|
62
|
-
const min = (dur / MINUTE) | 0;
|
|
63
|
-
dur -= min * MINUTE;
|
|
64
|
-
const sec = (dur / SECOND) | 0;
|
|
65
|
-
dur -= sec * SECOND;
|
|
66
|
-
return [year, month, day, hour, min, sec, dur];
|
|
67
|
-
};
|