@thi.ng/date 2.3.19 → 2.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2022-12-20T16:33:11Z
3
+ - **Last updated**: 2022-12-29T20:56:59Z
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
@@ -29,7 +29,7 @@ This project is part of the
29
29
 
30
30
  ## About
31
31
 
32
- Datetime types, relative dates, math, iterators, composable formatters, locales
32
+ Datetime types, relative dates, math, iterators, composable formatters, locales.
33
33
 
34
34
  ## Status
35
35
 
@@ -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.07 KB
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
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 { LOCALE } from "./i18n.js";
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
@@ -1,6 +1,7 @@
1
1
  export * from "./api.js";
2
2
  export * from "./checks.js";
3
3
  export * from "./datetime.js";
4
+ export * from "./duration.js";
4
5
  export * from "./format.js";
5
6
  export * from "./i18n.js";
6
7
  export * from "./iterators.js";
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./api.js";
2
2
  export * from "./checks.js";
3
3
  export * from "./datetime.js";
4
+ export * from "./duration.js";
4
5
  export * from "./format.js";
5
6
  export * from "./i18n.js";
6
7
  export * from "./iterators.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/date",
3
- "version": "2.3.19",
3
+ "version": "2.4.0",
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.1",
38
- "@thi.ng/checks": "^3.3.5",
39
- "@thi.ng/strings": "^3.3.21"
37
+ "@thi.ng/api": "^8.6.2",
38
+ "@thi.ng/checks": "^3.3.6",
39
+ "@thi.ng/strings": "^3.3.22"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@microsoft/api-extractor": "^7.33.7",
43
- "@thi.ng/testament": "^0.3.7",
43
+ "@thi.ng/testament": "^0.3.8",
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": "7b2af448da8a63fb21704a79cc4cdf1f3d7d7a64\n"
135
+ "gitHead": "28bb74c67217a352d673b6efdab234921d4a370e\n"
133
136
  }
package/relative.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MaybeDate, Period, Precision } from "./api.js";
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, MONTH, SECOND, YEAR, } from "./api.js";
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 { DAY, HOUR, MINUTE, MONTH, SECOND, YEAR } from "./api.js";
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
- };