@thi.ng/date 2.5.4 → 2.5.6
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 +1 -1
- package/README.md +1 -1
- package/api.js +45 -55
- package/checks.js +8 -17
- package/datetime.js +318 -321
- package/duration.js +53 -97
- package/format.js +243 -388
- package/i18n/de.js +77 -81
- package/i18n/en.js +77 -81
- package/i18n/es.js +42 -43
- package/i18n/fr.js +44 -45
- package/i18n/it.js +44 -45
- package/i18n.js +47 -118
- package/internal/precision.js +6 -16
- package/iterators.js +41 -93
- package/package.json +9 -7
- package/relative.js +108 -168
- package/round.js +77 -124
- package/timecode.js +19 -43
- package/units.js +21 -16
package/i18n.js
CHANGED
|
@@ -1,124 +1,53 @@
|
|
|
1
1
|
import { isString } from "@thi.ng/checks/is-string";
|
|
2
2
|
import { EN_SHORT } from "./i18n/en.js";
|
|
3
3
|
const prepLocale = (spec) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return locale;
|
|
4
|
+
const locale = {
|
|
5
|
+
sepED: " ",
|
|
6
|
+
sepDM: "/",
|
|
7
|
+
sepMY: "/",
|
|
8
|
+
sepHM: ":",
|
|
9
|
+
date: ["E", "/ED", "d", "/DM", "MMM", "/MY", "yyyy"],
|
|
10
|
+
time: ["H", "/HM", "mm"],
|
|
11
|
+
...spec
|
|
12
|
+
};
|
|
13
|
+
!locale.dateTime && (locale.dateTime = [...locale.date, ", ", ...locale.time]);
|
|
14
|
+
return locale;
|
|
16
15
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* restored even if `fn` throws an error.
|
|
30
|
-
*
|
|
31
|
-
* @param locale -
|
|
32
|
-
* @param fn -
|
|
33
|
-
*/
|
|
34
|
-
export const withLocale = (locale, fn) => {
|
|
35
|
-
const old = LOCALE;
|
|
36
|
-
setLocale(locale);
|
|
37
|
-
try {
|
|
38
|
-
const res = fn();
|
|
39
|
-
setLocale(old);
|
|
40
|
-
return res;
|
|
41
|
-
}
|
|
42
|
-
catch (e) {
|
|
43
|
-
setLocale(old);
|
|
44
|
-
throw e;
|
|
45
|
-
}
|
|
16
|
+
const setLocale = (locale) => LOCALE = prepLocale(locale);
|
|
17
|
+
const withLocale = (locale, fn) => {
|
|
18
|
+
const old = LOCALE;
|
|
19
|
+
setLocale(locale);
|
|
20
|
+
try {
|
|
21
|
+
const res = fn();
|
|
22
|
+
setLocale(old);
|
|
23
|
+
return res;
|
|
24
|
+
} catch (e) {
|
|
25
|
+
setLocale(old);
|
|
26
|
+
throw e;
|
|
27
|
+
}
|
|
46
28
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* // "1 an"
|
|
72
|
-
*
|
|
73
|
-
* withLocale(FR_LONG, () => units(2, "y"));
|
|
74
|
-
* // "2 ans"
|
|
75
|
-
*
|
|
76
|
-
* withLocale(FR_LONG, () => units(2, "y", true));
|
|
77
|
-
* // "2 ans"
|
|
78
|
-
*
|
|
79
|
-
* withLocale(DE_LONG, () => units(2, "y"));
|
|
80
|
-
* // "2 Jahre"
|
|
81
|
-
*
|
|
82
|
-
* withLocale(DE_LONG, () => units(2, "y", true));
|
|
83
|
-
* // "2 Jahren"
|
|
84
|
-
* ```
|
|
85
|
-
*
|
|
86
|
-
* @param x -
|
|
87
|
-
* @param unit -
|
|
88
|
-
* @param isDativ -
|
|
89
|
-
* @param unitsOnly -
|
|
90
|
-
*/
|
|
91
|
-
export const units = (x, unit, isDativ = false, unitsOnly = false) => {
|
|
92
|
-
unit = isString(unit) ? LOCALE.units[unit] : unit;
|
|
93
|
-
const res = x > 1 || x === 0
|
|
94
|
-
? isDativ
|
|
95
|
-
? unit.pd || unit.p
|
|
96
|
-
: unit.p
|
|
97
|
-
: isDativ
|
|
98
|
-
? unit.sd || unit.s
|
|
99
|
-
: unit.s;
|
|
100
|
-
return unitsOnly ? res : `${x} ${res}`;
|
|
29
|
+
let LOCALE = prepLocale(EN_SHORT);
|
|
30
|
+
const weekdayNames = () => LOCALE.days.slice();
|
|
31
|
+
const monthNames = () => LOCALE.months.slice();
|
|
32
|
+
const units = (x, unit, isDativ = false, unitsOnly = false) => {
|
|
33
|
+
unit = isString(unit) ? LOCALE.units[unit] : unit;
|
|
34
|
+
const res = x > 1 || x === 0 ? isDativ ? unit.pd || unit.p : unit.p : isDativ ? unit.sd || unit.s : unit.s;
|
|
35
|
+
return unitsOnly ? res : `${x} ${res}`;
|
|
36
|
+
};
|
|
37
|
+
const unitsLessThan = (x, unit, isDativ = false) => `${LOCALE.less.replace("%s", String(x))} ${units(
|
|
38
|
+
Math.max(x, 1),
|
|
39
|
+
unit,
|
|
40
|
+
isDativ,
|
|
41
|
+
true
|
|
42
|
+
)}`;
|
|
43
|
+
const tense = (sign, res) => (sign < 0 ? LOCALE.past : LOCALE.future).replace("%s", res);
|
|
44
|
+
export {
|
|
45
|
+
LOCALE,
|
|
46
|
+
monthNames,
|
|
47
|
+
setLocale,
|
|
48
|
+
tense,
|
|
49
|
+
units,
|
|
50
|
+
unitsLessThan,
|
|
51
|
+
weekdayNames,
|
|
52
|
+
withLocale
|
|
101
53
|
};
|
|
102
|
-
/**
|
|
103
|
-
* Similar to {@link units}, but for cases to express/format the phrase `less
|
|
104
|
-
* than {x} {unit(s)}`.
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```ts
|
|
108
|
-
* withLocale(DE_LONG, () => unitsLessThan(1, "y"));
|
|
109
|
-
* // "weniger als 1 Jahr"
|
|
110
|
-
* ```
|
|
111
|
-
*
|
|
112
|
-
* @param x -
|
|
113
|
-
* @param unit -
|
|
114
|
-
* @param isDativ -
|
|
115
|
-
*/
|
|
116
|
-
export const unitsLessThan = (x, unit, isDativ = false) => `${LOCALE.less.replace("%s", String(x))} ${units(Math.max(x, 1), unit, isDativ, true)}`;
|
|
117
|
-
/**
|
|
118
|
-
* Wraps given (presumably localized) string in current {@link LOCALE}'s `past`
|
|
119
|
-
* or `future` phrases, depending on given `sign`.
|
|
120
|
-
*
|
|
121
|
-
* @param sign -
|
|
122
|
-
* @param res -
|
|
123
|
-
*/
|
|
124
|
-
export const tense = (sign, res) => (sign < 0 ? LOCALE.past : LOCALE.future).replace("%s", res);
|
package/internal/precision.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
export const __precisionToID = (prec) => "yMdhmst".indexOf(prec);
|
|
9
|
-
/**
|
|
10
|
-
* Inverse op of {@link __precisionToID}.
|
|
11
|
-
*
|
|
12
|
-
* @param id -
|
|
13
|
-
*
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
export const __idToPrecision = (id) => "yMdhmst".charAt(id);
|
|
1
|
+
const __precisionToID = (prec) => "yMdhmst".indexOf(prec);
|
|
2
|
+
const __idToPrecision = (id) => "yMdhmst".charAt(id);
|
|
3
|
+
export {
|
|
4
|
+
__idToPrecision,
|
|
5
|
+
__precisionToID
|
|
6
|
+
};
|
package/iterators.js
CHANGED
|
@@ -1,97 +1,45 @@
|
|
|
1
1
|
import { isString } from "@thi.ng/checks/is-string";
|
|
2
2
|
import { DateTime } from "./datetime.js";
|
|
3
3
|
import { floorQuarter, floorWeek } from "./round.js";
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
const defIterator = (prec, tick) => {
|
|
5
|
+
return function* (...xs) {
|
|
6
|
+
let [from, to] = (xs.length > 1 ? xs : xs[0]).map(
|
|
7
|
+
(x) => new DateTime(x).getTime()
|
|
8
|
+
);
|
|
9
|
+
let state = isString(prec) ? new DateTime(from, prec) : prec(from);
|
|
10
|
+
let epoch = from;
|
|
11
|
+
while (epoch < to) {
|
|
12
|
+
epoch = state.getTime();
|
|
13
|
+
if (epoch >= from && epoch < to)
|
|
14
|
+
yield epoch;
|
|
15
|
+
tick(state);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
const years = defIterator("y", (d) => d.incYear());
|
|
20
|
+
const quarters = defIterator(
|
|
21
|
+
(from) => new DateTime(floorQuarter(from)),
|
|
22
|
+
(d) => d.incQuarter()
|
|
23
|
+
);
|
|
24
|
+
const months = defIterator("M", (d) => d.incMonth());
|
|
25
|
+
const weeks = defIterator(
|
|
26
|
+
(from) => new DateTime(floorWeek(from)),
|
|
27
|
+
(d) => d.incWeek()
|
|
28
|
+
);
|
|
29
|
+
const days = defIterator("d", (d) => d.incDay());
|
|
30
|
+
const hours = defIterator("h", (d) => d.incHour());
|
|
31
|
+
const minutes = defIterator("m", (d) => d.incMinute());
|
|
32
|
+
const seconds = defIterator("s", (d) => d.incSecond());
|
|
33
|
+
const milliseconds = defIterator("t", (d) => d.incMillisecond());
|
|
34
|
+
export {
|
|
35
|
+
days,
|
|
36
|
+
defIterator,
|
|
37
|
+
hours,
|
|
38
|
+
milliseconds,
|
|
39
|
+
minutes,
|
|
40
|
+
months,
|
|
41
|
+
quarters,
|
|
42
|
+
seconds,
|
|
43
|
+
weeks,
|
|
44
|
+
years
|
|
23
45
|
};
|
|
24
|
-
/**
|
|
25
|
-
* Yields iterator of UTC timestamps in given semi-open interval in yearly
|
|
26
|
-
* precision (each timestamp is at beginning of each year).
|
|
27
|
-
*
|
|
28
|
-
* @param from -
|
|
29
|
-
* @param to -
|
|
30
|
-
*/
|
|
31
|
-
export const years = defIterator("y", (d) => d.incYear());
|
|
32
|
-
/**
|
|
33
|
-
* Yields iterator of UTC timestamps in given semi-open interval in monthly
|
|
34
|
-
* precision (each timestamp is at beginning of a month), but spaced at 3 month
|
|
35
|
-
* intervals.
|
|
36
|
-
*
|
|
37
|
-
* @param from -
|
|
38
|
-
* @param to -
|
|
39
|
-
*/
|
|
40
|
-
export const quarters = defIterator((from) => new DateTime(floorQuarter(from)), (d) => d.incQuarter());
|
|
41
|
-
/**
|
|
42
|
-
* Yields iterator of UTC timestamps in given semi-open interval in monthly
|
|
43
|
-
* precision (each timestamp is at beginning of each month).
|
|
44
|
-
*
|
|
45
|
-
* @param from -
|
|
46
|
-
* @param to -
|
|
47
|
-
*/
|
|
48
|
-
export const months = defIterator("M", (d) => d.incMonth());
|
|
49
|
-
/**
|
|
50
|
-
* Yields iterator of UTC timestamps in given semi-open interval in daily
|
|
51
|
-
* precision (each timestamp is 7 days apart). As per ISO8601, weeks start on
|
|
52
|
-
* Mondays.
|
|
53
|
-
*
|
|
54
|
-
* @param from -
|
|
55
|
-
* @param to -
|
|
56
|
-
*/
|
|
57
|
-
export const weeks = defIterator((from) => new DateTime(floorWeek(from)), (d) => d.incWeek());
|
|
58
|
-
/**
|
|
59
|
-
* Yields iterator of UTC timestamps in given semi-open interval in daily
|
|
60
|
-
* precision (each timestamp is at midnight/beginning of each day).
|
|
61
|
-
*
|
|
62
|
-
* @param from -
|
|
63
|
-
* @param to -
|
|
64
|
-
*/
|
|
65
|
-
export const days = defIterator("d", (d) => d.incDay());
|
|
66
|
-
/**
|
|
67
|
-
* Yields iterator of UTC timestamps in given semi-open interval in hourly
|
|
68
|
-
* precision.
|
|
69
|
-
*
|
|
70
|
-
* @param from -
|
|
71
|
-
* @param to -
|
|
72
|
-
*/
|
|
73
|
-
export const hours = defIterator("h", (d) => d.incHour());
|
|
74
|
-
/**
|
|
75
|
-
* Yields iterator of UTC timestamps in given semi-open interval in minute
|
|
76
|
-
* precision.
|
|
77
|
-
*
|
|
78
|
-
* @param from -
|
|
79
|
-
* @param to -
|
|
80
|
-
*/
|
|
81
|
-
export const minutes = defIterator("m", (d) => d.incMinute());
|
|
82
|
-
/**
|
|
83
|
-
* Yields iterator of UTC timestamps in given semi-open interval in second
|
|
84
|
-
* precision.
|
|
85
|
-
*
|
|
86
|
-
* @param from -
|
|
87
|
-
* @param to -
|
|
88
|
-
*/
|
|
89
|
-
export const seconds = defIterator("s", (d) => d.incSecond());
|
|
90
|
-
/**
|
|
91
|
-
* Yields iterator of UTC timestamps in given semi-open interval in millisecond
|
|
92
|
-
* precision.
|
|
93
|
-
*
|
|
94
|
-
* @param from -
|
|
95
|
-
* @param to -
|
|
96
|
-
*/
|
|
97
|
-
export const milliseconds = defIterator("t", (d) => d.incMillisecond());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/date",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.6",
|
|
4
4
|
"description": "Datetime types, relative dates, math, iterators, composable formatters, locales",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"author": "Karsten Schmidt (https://thi.ng)",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "yarn
|
|
27
|
+
"build": "yarn build:esbuild && yarn build:decl",
|
|
28
|
+
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
29
|
+
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
28
30
|
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc internal i18n",
|
|
29
31
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
30
32
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
@@ -33,13 +35,13 @@
|
|
|
33
35
|
"test": "bun test"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@thi.ng/api": "^8.9.
|
|
37
|
-
"@thi.ng/checks": "^3.4.
|
|
38
|
-
"@thi.ng/strings": "^3.7.
|
|
38
|
+
"@thi.ng/api": "^8.9.12",
|
|
39
|
+
"@thi.ng/checks": "^3.4.12",
|
|
40
|
+
"@thi.ng/strings": "^3.7.3"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@microsoft/api-extractor": "^7.38.3",
|
|
42
|
-
"
|
|
44
|
+
"esbuild": "^0.19.8",
|
|
43
45
|
"rimraf": "^5.0.5",
|
|
44
46
|
"tools": "^0.0.1",
|
|
45
47
|
"typedoc": "^0.25.4",
|
|
@@ -131,5 +133,5 @@
|
|
|
131
133
|
"thi.ng": {
|
|
132
134
|
"year": 2020
|
|
133
135
|
},
|
|
134
|
-
"gitHead": "
|
|
136
|
+
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
|
|
135
137
|
}
|
package/relative.js
CHANGED
|
@@ -1,178 +1,118 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DAY,
|
|
3
|
+
HOUR,
|
|
4
|
+
MINUTE,
|
|
5
|
+
SECOND
|
|
6
|
+
} from "./api.js";
|
|
2
7
|
import { ensureEpoch } from "./checks.js";
|
|
3
8
|
import { dateTime, ensureDateTime } from "./datetime.js";
|
|
4
9
|
import { EN_LONG, EN_SHORT } from "./i18n/en.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* - `q` / `quarter` / `quarters`
|
|
37
|
-
* - `y` / `year` / `years`
|
|
38
|
-
*
|
|
39
|
-
* @param offset -
|
|
40
|
-
* @param base -
|
|
41
|
-
*/
|
|
42
|
-
export const parseRelative = (offset, base) => {
|
|
43
|
-
offset = offset.toLowerCase();
|
|
44
|
-
const epoch = dateTime(base);
|
|
45
|
-
switch (offset) {
|
|
46
|
-
case "today":
|
|
47
|
-
return epoch;
|
|
48
|
-
case "tomorrow":
|
|
49
|
-
epoch.incDay();
|
|
50
|
-
return epoch;
|
|
51
|
-
case "yesterday":
|
|
52
|
-
epoch.decDay();
|
|
53
|
-
return epoch;
|
|
54
|
-
default: {
|
|
55
|
-
let idx = findIndex(EN_SHORT.days, offset);
|
|
56
|
-
if (idx < 0) {
|
|
57
|
-
idx = findIndex(EN_LONG.days, offset);
|
|
58
|
-
}
|
|
59
|
-
if (idx >= 0) {
|
|
60
|
-
do {
|
|
61
|
-
epoch.incDay();
|
|
62
|
-
} while (epoch.toDate().getDay() != idx);
|
|
63
|
-
return epoch;
|
|
64
|
-
}
|
|
65
|
-
const match = /^(an? |next |[-+]?\d+\s?)((ms|milli(?:(s?|seconds?)))|s(?:(ecs?|econds?))?|min(?:(s|utes?))?|h(?:ours?)?|d(?:ays?)?|w(?:eeks?)?|mo(?:nths?)?|q(?:uarters?)?|y(?:ears?)?)(\s+ago)?$/.exec(offset);
|
|
66
|
-
return match
|
|
67
|
-
? relative(parseNum(match[1], !!match[7]), parsePeriod(match[2]), base)
|
|
68
|
-
: undefined;
|
|
69
|
-
}
|
|
10
|
+
const parseRelative = (offset, base) => {
|
|
11
|
+
offset = offset.toLowerCase();
|
|
12
|
+
const epoch = dateTime(base);
|
|
13
|
+
switch (offset) {
|
|
14
|
+
case "today":
|
|
15
|
+
return epoch;
|
|
16
|
+
case "tomorrow":
|
|
17
|
+
epoch.incDay();
|
|
18
|
+
return epoch;
|
|
19
|
+
case "yesterday":
|
|
20
|
+
epoch.decDay();
|
|
21
|
+
return epoch;
|
|
22
|
+
default: {
|
|
23
|
+
let idx = findIndex(EN_SHORT.days, offset);
|
|
24
|
+
if (idx < 0) {
|
|
25
|
+
idx = findIndex(EN_LONG.days, offset);
|
|
26
|
+
}
|
|
27
|
+
if (idx >= 0) {
|
|
28
|
+
do {
|
|
29
|
+
epoch.incDay();
|
|
30
|
+
} while (epoch.toDate().getDay() != idx);
|
|
31
|
+
return epoch;
|
|
32
|
+
}
|
|
33
|
+
const match = /^(an? |next |[-+]?\d+\s?)((ms|milli(?:(s?|seconds?)))|s(?:(ecs?|econds?))?|min(?:(s|utes?))?|h(?:ours?)?|d(?:ays?)?|w(?:eeks?)?|mo(?:nths?)?|q(?:uarters?)?|y(?:ears?)?)(\s+ago)?$/.exec(
|
|
34
|
+
offset
|
|
35
|
+
);
|
|
36
|
+
return match ? relative(
|
|
37
|
+
parseNum(match[1], !!match[7]),
|
|
38
|
+
parsePeriod(match[2]),
|
|
39
|
+
base
|
|
40
|
+
) : void 0;
|
|
70
41
|
}
|
|
42
|
+
}
|
|
71
43
|
};
|
|
72
44
|
const findIndex = (items, x) => items.findIndex((y) => y.toLowerCase() === x);
|
|
73
|
-
const parseNum = (x, past) => (x === "next " || x === "a " || x === "an " ? 1 : Number(x)) *
|
|
74
|
-
(past ? -1 : 1);
|
|
45
|
+
const parseNum = (x, past) => (x === "next " || x === "a " || x === "an " ? 1 : Number(x)) * (past ? -1 : 1);
|
|
75
46
|
const parsePeriod = (x) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
quarter: "q",
|
|
94
|
-
year: "y",
|
|
95
|
-
}[x] || x;
|
|
47
|
+
x = x !== "s" && x !== "ms" && x.endsWith("s") ? x.substring(0, x.length - 1) : x;
|
|
48
|
+
return {
|
|
49
|
+
ms: "t",
|
|
50
|
+
milli: "t",
|
|
51
|
+
millisecond: "t",
|
|
52
|
+
sec: "s",
|
|
53
|
+
second: "s",
|
|
54
|
+
min: "m",
|
|
55
|
+
minute: "m",
|
|
56
|
+
hour: "h",
|
|
57
|
+
day: "d",
|
|
58
|
+
week: "w",
|
|
59
|
+
mo: "M",
|
|
60
|
+
month: "M",
|
|
61
|
+
quarter: "q",
|
|
62
|
+
year: "y"
|
|
63
|
+
}[x] || x;
|
|
96
64
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* @param b
|
|
126
|
-
*/
|
|
127
|
-
export const absDifference = (a, b) => Math.abs(difference(a, b));
|
|
128
|
-
/**
|
|
129
|
-
* Computes and decomposes difference between given dates. Returns tuple of:
|
|
130
|
-
* `[sign, years, months, days, hours, mins, secs, millis]`. The `sign` is used
|
|
131
|
-
* to indicate the relative order of `a` compared to `b`, i.e. same contract as
|
|
132
|
-
* [`ICompare`](https://docs.thi.ng/umbrella/api/interfaces/ICompare.html).
|
|
133
|
-
*
|
|
134
|
-
* @param a -
|
|
135
|
-
* @param b -
|
|
136
|
-
*/
|
|
137
|
-
export const decomposeDifference = (a, b = new Date()) => {
|
|
138
|
-
const dur = ensureEpoch(a) - ensureEpoch(b);
|
|
139
|
-
let abs = Math.abs(dur);
|
|
140
|
-
const milli = abs % SECOND;
|
|
141
|
-
abs -= milli;
|
|
142
|
-
const sec = abs % MINUTE;
|
|
143
|
-
abs -= sec;
|
|
144
|
-
const min = abs % HOUR;
|
|
145
|
-
abs -= min;
|
|
146
|
-
const hour = abs % DAY;
|
|
147
|
-
abs -= hour;
|
|
148
|
-
const parts = [
|
|
149
|
-
Math.sign(dur),
|
|
150
|
-
0, // year
|
|
151
|
-
0, // month
|
|
152
|
-
0, // day
|
|
153
|
-
hour / HOUR,
|
|
154
|
-
min / MINUTE,
|
|
155
|
-
sec / SECOND,
|
|
156
|
-
milli,
|
|
157
|
-
];
|
|
158
|
-
if (!abs)
|
|
159
|
-
return parts;
|
|
160
|
-
const diff = (a, b) => {
|
|
161
|
-
const months = (b.y - a.y) * 12 + (b.M - a.M);
|
|
162
|
-
const bstart = +a.add(months, "M");
|
|
163
|
-
let frac = +b - bstart;
|
|
164
|
-
frac /=
|
|
165
|
-
frac < 0
|
|
166
|
-
? bstart - +a.add(months - 1, "M")
|
|
167
|
-
: +a.add(months + 1, "M") - bstart;
|
|
168
|
-
return -(months + frac) || 0;
|
|
169
|
-
};
|
|
170
|
-
const aa = ensureDateTime(a, "d");
|
|
171
|
-
const bb = ensureDateTime(b, "d");
|
|
172
|
-
const months = Math.abs(aa.d < bb.d ? -diff(bb, aa) : diff(aa, bb)) | 0;
|
|
173
|
-
const days = (start, end) => Math.abs(+start.withPrecision("d").add(months, "M") - +end.withPrecision("d")) / DAY;
|
|
174
|
-
parts[1] = (months / 12) | 0;
|
|
175
|
-
parts[2] = months % 12;
|
|
176
|
-
parts[3] = dur < 0 ? days(aa, bb) : days(bb, aa);
|
|
65
|
+
const relative = (num, period, base = dateTime()) => dateTime(base).add(num, period);
|
|
66
|
+
const difference = (a, b) => ensureEpoch(a) - ensureEpoch(b);
|
|
67
|
+
const absDifference = (a, b) => Math.abs(difference(a, b));
|
|
68
|
+
const decomposeDifference = (a, b = /* @__PURE__ */ new Date()) => {
|
|
69
|
+
const dur = ensureEpoch(a) - ensureEpoch(b);
|
|
70
|
+
let abs = Math.abs(dur);
|
|
71
|
+
const milli = abs % SECOND;
|
|
72
|
+
abs -= milli;
|
|
73
|
+
const sec = abs % MINUTE;
|
|
74
|
+
abs -= sec;
|
|
75
|
+
const min = abs % HOUR;
|
|
76
|
+
abs -= min;
|
|
77
|
+
const hour = abs % DAY;
|
|
78
|
+
abs -= hour;
|
|
79
|
+
const parts = [
|
|
80
|
+
Math.sign(dur),
|
|
81
|
+
0,
|
|
82
|
+
// year
|
|
83
|
+
0,
|
|
84
|
+
// month
|
|
85
|
+
0,
|
|
86
|
+
// day
|
|
87
|
+
hour / HOUR,
|
|
88
|
+
min / MINUTE,
|
|
89
|
+
sec / SECOND,
|
|
90
|
+
milli
|
|
91
|
+
];
|
|
92
|
+
if (!abs)
|
|
177
93
|
return parts;
|
|
94
|
+
const diff = (a2, b2) => {
|
|
95
|
+
const months2 = (b2.y - a2.y) * 12 + (b2.M - a2.M);
|
|
96
|
+
const bstart = +a2.add(months2, "M");
|
|
97
|
+
let frac = +b2 - bstart;
|
|
98
|
+
frac /= frac < 0 ? bstart - +a2.add(months2 - 1, "M") : +a2.add(months2 + 1, "M") - bstart;
|
|
99
|
+
return -(months2 + frac) || 0;
|
|
100
|
+
};
|
|
101
|
+
const aa = ensureDateTime(a, "d");
|
|
102
|
+
const bb = ensureDateTime(b, "d");
|
|
103
|
+
const months = Math.abs(aa.d < bb.d ? -diff(bb, aa) : diff(aa, bb)) | 0;
|
|
104
|
+
const days = (start, end) => Math.abs(
|
|
105
|
+
+start.withPrecision("d").add(months, "M") - +end.withPrecision("d")
|
|
106
|
+
) / DAY;
|
|
107
|
+
parts[1] = months / 12 | 0;
|
|
108
|
+
parts[2] = months % 12;
|
|
109
|
+
parts[3] = dur < 0 ? days(aa, bb) : days(bb, aa);
|
|
110
|
+
return parts;
|
|
111
|
+
};
|
|
112
|
+
export {
|
|
113
|
+
absDifference,
|
|
114
|
+
decomposeDifference,
|
|
115
|
+
difference,
|
|
116
|
+
parseRelative,
|
|
117
|
+
relative
|
|
178
118
|
};
|