@pvorona/duration 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -42
- package/dist/index.js +203 -152
- package/dist/lib/duration.d.ts +66 -12
- package/dist/lib/duration.d.ts.map +1 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @pvorona/duration
|
|
2
2
|
|
|
3
|
-
An immutable duration type with unit conversions, comparisons, and basic arithmetic.
|
|
3
|
+
An immutable ESM-only duration type with unit conversions, comparisons, and basic arithmetic.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,25 +8,44 @@ An immutable duration type with unit conversions, comparisons, and basic arithme
|
|
|
8
8
|
npm i @pvorona/duration
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
This package is ESM-only. Import it from ESM modules instead of `require(...)`.
|
|
12
|
+
|
|
11
13
|
## Usage
|
|
12
14
|
|
|
13
15
|
### Create and convert
|
|
14
16
|
|
|
15
17
|
```ts
|
|
16
|
-
import {
|
|
18
|
+
import { duration, TimeUnit } from '@pvorona/duration';
|
|
17
19
|
|
|
18
|
-
const d =
|
|
19
|
-
d.toSeconds(); //
|
|
20
|
-
d.
|
|
20
|
+
const d = duration(2, TimeUnit.Minute);
|
|
21
|
+
d.toSeconds(); // 120
|
|
22
|
+
d.toMilliseconds(); // 120_000
|
|
23
|
+
duration(250, TimeUnit.Millisecond).toSeconds(); // 0.25
|
|
21
24
|
```
|
|
22
25
|
|
|
26
|
+
### Compose from multiple units
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { duration } from '@pvorona/duration';
|
|
30
|
+
|
|
31
|
+
const total = duration({ minutes: 1, seconds: 30 });
|
|
32
|
+
total.toSeconds(); // 90
|
|
33
|
+
|
|
34
|
+
const negative = duration({ hours: -1, minutes: -30 });
|
|
35
|
+
negative.toMilliseconds(); // -5_400_000
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`duration(parts)` accepts only the exact plural keys `milliseconds`, `seconds`, `minutes`, `hours`, `days`, `weeks`, `months`, and `years`.
|
|
39
|
+
|
|
40
|
+
All non-zero parts must share the same sign. For example, `duration({ hours: 1, minutes: -30 })` throws `TypeError`.
|
|
41
|
+
|
|
23
42
|
### Compare
|
|
24
43
|
|
|
25
44
|
```ts
|
|
26
|
-
import {
|
|
45
|
+
import { milliseconds, seconds } from '@pvorona/duration';
|
|
27
46
|
|
|
28
47
|
const a = seconds(1);
|
|
29
|
-
const b =
|
|
48
|
+
const b = milliseconds(900);
|
|
30
49
|
|
|
31
50
|
a.greaterThan(b); // true
|
|
32
51
|
a.compare(b); // 1
|
|
@@ -35,10 +54,10 @@ a.compare(b); // 1
|
|
|
35
54
|
### Arithmetic
|
|
36
55
|
|
|
37
56
|
```ts
|
|
38
|
-
import { add,
|
|
57
|
+
import { add, milliseconds, seconds } from '@pvorona/duration';
|
|
39
58
|
|
|
40
|
-
const total = add(seconds(1),
|
|
41
|
-
total.
|
|
59
|
+
const total = add(seconds(1), milliseconds(500));
|
|
60
|
+
total.toMilliseconds(); // 1500
|
|
42
61
|
```
|
|
43
62
|
|
|
44
63
|
### Between dates
|
|
@@ -51,52 +70,69 @@ const elapsed = since(startedAt);
|
|
|
51
70
|
elapsed.toSeconds(); // ~2
|
|
52
71
|
```
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
### Apply a duration to a date
|
|
55
74
|
|
|
56
|
-
|
|
75
|
+
```ts
|
|
76
|
+
import { addTo, seconds, subtractFrom } from '@pvorona/duration';
|
|
57
77
|
|
|
58
|
-
|
|
78
|
+
const start = new Date(1_000);
|
|
59
79
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
MilliSecond,
|
|
63
|
-
Second,
|
|
64
|
-
Minute,
|
|
65
|
-
Hour,
|
|
66
|
-
Day,
|
|
67
|
-
Week,
|
|
68
|
-
Month,
|
|
69
|
-
Year,
|
|
70
|
-
}
|
|
80
|
+
addTo(start, seconds(2)).getTime(); // 3_000
|
|
81
|
+
subtractFrom(start, seconds(2)).getTime(); // -1_000
|
|
71
82
|
```
|
|
72
83
|
|
|
73
|
-
|
|
84
|
+
## Important semantics
|
|
85
|
+
|
|
86
|
+
- ESM-only package: use `import`, not `require(...)`.
|
|
87
|
+
- Duration values are frozen branded objects created by this package. Use `isDuration(...)` for unknown inputs instead of duck typing.
|
|
88
|
+
- Compare durations by value with `d.equals(other)` or `isEqual(a, b)`, not `===`.
|
|
89
|
+
- Do not spread, JSON-serialize, or structured-clone `Duration` values as a transport format. Serialize your own explicit shape and reconstruct with `milliseconds(...)` for finite values or `infinite` for the sentinel.
|
|
90
|
+
- `DurationParts` is constructor input only. It is not a serialized `Duration` format and should not be treated as one.
|
|
91
|
+
- `instant` is the exported zero-duration constant, but any zero-valued duration has `isInstant === true`.
|
|
92
|
+
- The public millisecond APIs are `TimeUnit.Millisecond`, `milliseconds(...)`, and `toMilliseconds()`.
|
|
93
|
+
- `Month` is treated as 30 days and `Year` as 365.25 days. These are approximations, not calendar-aware durations.
|
|
94
|
+
- Negative finite durations are valid. `between(...)`, `since(...)`, arithmetic, and comparisons can produce or operate on negative values.
|
|
95
|
+
- Constructors accept only finite numeric inputs. `infinite` is the only supported non-finite duration.
|
|
96
|
+
- `duration(parts)` requires at least one supported plural key, rejects unknown keys, rejects non-finite part values, and rejects mixed-sign non-zero parts.
|
|
97
|
+
- `add(infinite, x)`, `subtract(infinite, finite)`, `multiply(infinite, positive finite)`, and `divide(infinite, positive finite)` return `infinite`.
|
|
98
|
+
- `addTo(date, duration)` and `subtractFrom(date, duration)` do exact timestamp arithmetic equivalent to `new Date(date.getTime() +/- duration.toMilliseconds())`.
|
|
99
|
+
- `addTo(...)` and `subtractFrom(...)` reject invalid dates, reject `infinite`, and reject result timestamps outside the JavaScript `Date` range.
|
|
100
|
+
- `addTo(...)` and `subtractFrom(...)` are timestamp-based, not calendar-aware. Local clock time may shift across DST or timezone offset transitions.
|
|
101
|
+
- `Date` values only have millisecond precision, so the date helpers follow native JavaScript `Date` semantics for fractional-millisecond timestamps.
|
|
102
|
+
- Invalid units, invalid dates, non-finite scalar inputs, divide-by-zero, `subtract(infinite, infinite)`, `subtract(finite, infinite)`, `multiply(infinite, 0)`, `multiply(infinite, negative)`, and `divide(infinite, negative)` throw `TypeError`.
|
|
74
103
|
|
|
75
|
-
|
|
76
|
-
- `Year` is treated as **365.25 days**
|
|
104
|
+
## API
|
|
77
105
|
|
|
78
|
-
|
|
106
|
+
### `TimeUnit`
|
|
79
107
|
|
|
80
|
-
|
|
81
|
-
import { duration, TimeUnit } from '@pvorona/duration';
|
|
108
|
+
The package exports both:
|
|
82
109
|
|
|
83
|
-
|
|
84
|
-
|
|
110
|
+
- `type TimeUnit`: the union of the supported runtime unit values
|
|
111
|
+
- `const TimeUnit`: the runtime constants accepted by `duration(value, unit)` and `d.to(unit)`
|
|
112
|
+
|
|
113
|
+
- `TimeUnit.Millisecond`
|
|
114
|
+
- `TimeUnit.Second`
|
|
115
|
+
- `TimeUnit.Minute`
|
|
116
|
+
- `TimeUnit.Hour`
|
|
117
|
+
- `TimeUnit.Day`
|
|
118
|
+
- `TimeUnit.Week`
|
|
119
|
+
- `TimeUnit.Month`
|
|
120
|
+
- `TimeUnit.Year`
|
|
85
121
|
|
|
86
122
|
### `type Duration`
|
|
87
123
|
|
|
88
|
-
An opaque, immutable duration value.
|
|
124
|
+
An opaque, immutable duration value. Duration instances are branded by the package, so use `isDuration(...)` for unknown inputs and compare values with `equals(...)` / `isEqual(...)` rather than `===`.
|
|
89
125
|
|
|
90
126
|
#### Properties
|
|
91
127
|
|
|
92
|
-
- **`isFinite: boolean`**: `true`
|
|
93
|
-
- **`isInfinite: boolean`**: `true` for `infinite`
|
|
94
|
-
- **`isInstant: boolean`**: `true` for zero duration (`instant`)
|
|
128
|
+
- **`isFinite: boolean`**: `true` for finite durations
|
|
129
|
+
- **`isInfinite: boolean`**: `true` only for `infinite`
|
|
130
|
+
- **`isInstant: boolean`**: `true` for any zero duration (including `instant`)
|
|
95
131
|
|
|
96
132
|
#### Conversions
|
|
97
133
|
|
|
98
134
|
- **`to(unit: TimeUnit): number`**: convert to an arbitrary unit
|
|
99
|
-
- **`
|
|
135
|
+
- **`toMilliseconds(): number`**
|
|
100
136
|
- **`toSeconds(): number`**
|
|
101
137
|
- **`toMinutes(): number`**
|
|
102
138
|
- **`toHours(): number`**
|
|
@@ -114,28 +150,44 @@ An opaque, immutable duration value.
|
|
|
114
150
|
- **`greaterThanOrEqual(other: Duration): boolean`**
|
|
115
151
|
- **`compare(other: Duration): -1 | 0 | 1`**
|
|
116
152
|
|
|
117
|
-
Example
|
|
153
|
+
Example:
|
|
118
154
|
|
|
119
155
|
```ts
|
|
120
|
-
import {
|
|
156
|
+
import { milliseconds, seconds, type Duration } from '@pvorona/duration';
|
|
121
157
|
|
|
122
158
|
function isShort(d: Duration) {
|
|
123
159
|
return d.isFinite && d.toSeconds() < 5;
|
|
124
160
|
}
|
|
125
161
|
|
|
126
162
|
const a = seconds(1);
|
|
127
|
-
const b =
|
|
163
|
+
const b = milliseconds(900);
|
|
128
164
|
|
|
129
165
|
isShort(a); // true
|
|
130
166
|
a.greaterThan(b); // true
|
|
131
167
|
```
|
|
132
168
|
|
|
169
|
+
### `type DurationParts`
|
|
170
|
+
|
|
171
|
+
Strict constructor input for `duration(parts)`. Supported keys:
|
|
172
|
+
|
|
173
|
+
- `milliseconds?: number`
|
|
174
|
+
- `seconds?: number`
|
|
175
|
+
- `minutes?: number`
|
|
176
|
+
- `hours?: number`
|
|
177
|
+
- `days?: number`
|
|
178
|
+
- `weeks?: number`
|
|
179
|
+
- `months?: number`
|
|
180
|
+
- `years?: number`
|
|
181
|
+
|
|
182
|
+
At least one key is required. All non-zero keys must share the same sign.
|
|
183
|
+
|
|
133
184
|
### Function API
|
|
134
185
|
|
|
135
186
|
#### Constructors
|
|
136
187
|
|
|
137
188
|
- `duration(value: number, unit: TimeUnit): Duration`
|
|
138
|
-
- `
|
|
189
|
+
- `duration(parts: DurationParts): Duration`
|
|
190
|
+
- `milliseconds(value: number): Duration`
|
|
139
191
|
- `seconds(value: number): Duration`
|
|
140
192
|
- `minutes(value: number): Duration`
|
|
141
193
|
- `hours(value: number): Duration`
|
|
@@ -148,6 +200,8 @@ a.greaterThan(b); // true
|
|
|
148
200
|
|
|
149
201
|
- `between(start: Date, end: Date): Duration`
|
|
150
202
|
- `since(start: Date): Duration`
|
|
203
|
+
- `addTo(date: Date, duration: Duration): Date`
|
|
204
|
+
- `subtractFrom(date: Date, duration: Duration): Date`
|
|
151
205
|
|
|
152
206
|
#### Arithmetic helpers
|
|
153
207
|
|
|
@@ -173,6 +227,6 @@ import { isDuration, seconds } from '@pvorona/duration';
|
|
|
173
227
|
|
|
174
228
|
const maybe: unknown = seconds(1);
|
|
175
229
|
if (isDuration(maybe)) {
|
|
176
|
-
maybe.
|
|
230
|
+
maybe.toMilliseconds(); // ok, narrowed
|
|
177
231
|
}
|
|
178
232
|
```
|
package/dist/index.js
CHANGED
|
@@ -1,205 +1,256 @@
|
|
|
1
|
-
import { isObject as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { isObject as T, hasOwnKey as b } from "@pvorona/assert";
|
|
2
|
+
const N = {
|
|
3
|
+
Millisecond: 0,
|
|
4
|
+
Second: 1,
|
|
5
|
+
Minute: 2,
|
|
6
|
+
Hour: 3,
|
|
7
|
+
Day: 4,
|
|
8
|
+
Week: 5,
|
|
9
|
+
Month: 6,
|
|
10
|
+
Year: 7
|
|
11
|
+
}, e = N, w = {
|
|
12
|
+
milliseconds: e.Millisecond,
|
|
13
|
+
seconds: e.Second,
|
|
14
|
+
minutes: e.Minute,
|
|
15
|
+
hours: e.Hour,
|
|
16
|
+
days: e.Day,
|
|
17
|
+
weeks: e.Week,
|
|
18
|
+
months: e.Month,
|
|
19
|
+
years: e.Year
|
|
20
|
+
}, r = /* @__PURE__ */ Symbol("milliseconds"), D = new Set(Object.values(e)), S = new Set(
|
|
21
|
+
Object.keys(w)
|
|
22
|
+
), d = {
|
|
23
|
+
[e.Millisecond]: 1,
|
|
24
|
+
[e.Second]: 1e3,
|
|
25
|
+
[e.Minute]: 60 * 1e3,
|
|
26
|
+
[e.Hour]: 3600 * 1e3,
|
|
8
27
|
/** Note: Does not account for leap second */
|
|
9
|
-
|
|
10
|
-
|
|
28
|
+
[e.Day]: 1440 * 60 * 1e3,
|
|
29
|
+
[e.Week]: 10080 * 60 * 1e3,
|
|
11
30
|
/** Note: Does not account for leap year */
|
|
12
|
-
|
|
31
|
+
[e.Month]: (
|
|
13
32
|
/* 30 days */
|
|
14
33
|
720 * 60 * 60 * 1e3
|
|
15
34
|
),
|
|
16
35
|
/** Note: Does not account for leap year */
|
|
17
|
-
|
|
36
|
+
[e.Year]: (
|
|
18
37
|
/* 365.25 days */
|
|
19
38
|
365.25 * 24 * 60 * 60 * 1e3
|
|
20
39
|
)
|
|
21
|
-
}
|
|
22
|
-
|
|
40
|
+
};
|
|
41
|
+
function p(n) {
|
|
42
|
+
if (D.has(n))
|
|
43
|
+
return n;
|
|
44
|
+
throw new TypeError("Expected a valid time unit.");
|
|
45
|
+
}
|
|
46
|
+
function c(n, t) {
|
|
47
|
+
if (Number.isFinite(n))
|
|
48
|
+
return n;
|
|
49
|
+
throw new TypeError(`Expected \`${t}\` to be finite.`);
|
|
50
|
+
}
|
|
51
|
+
function a(n, t) {
|
|
52
|
+
const i = n.getTime();
|
|
53
|
+
if (!Number.isNaN(i))
|
|
54
|
+
return i;
|
|
55
|
+
throw new TypeError(`Expected \`${t}\` to be a valid date.`);
|
|
56
|
+
}
|
|
57
|
+
function y(n, t) {
|
|
58
|
+
const i = new Date(n);
|
|
59
|
+
return a(i, t), i;
|
|
60
|
+
}
|
|
61
|
+
function g(n) {
|
|
62
|
+
if (S.has(n))
|
|
63
|
+
return n;
|
|
64
|
+
throw new TypeError(`Expected \`${n}\` to be a supported duration part.`);
|
|
65
|
+
}
|
|
66
|
+
function _(n) {
|
|
67
|
+
const t = Object.entries(n);
|
|
68
|
+
if (t.length === 0)
|
|
69
|
+
throw new TypeError("Expected `parts` to include at least one duration part.");
|
|
70
|
+
let i = 0, o;
|
|
71
|
+
for (const [E, M] of t) {
|
|
72
|
+
const h = g(E), l = c(M, `parts.${h}`);
|
|
73
|
+
if (l === 0)
|
|
74
|
+
continue;
|
|
75
|
+
const m = Math.sign(l);
|
|
76
|
+
if (o == null && (o = m), o !== m)
|
|
77
|
+
throw new TypeError("Expected non-zero duration parts to share the same sign.");
|
|
78
|
+
i += l * d[w[h]];
|
|
79
|
+
}
|
|
80
|
+
return i;
|
|
81
|
+
}
|
|
82
|
+
function O(n, t) {
|
|
83
|
+
if (Number.isNaN(n) || n === Number.NEGATIVE_INFINITY)
|
|
84
|
+
throw new TypeError("Expected duration milliseconds to be finite or `Infinity`.");
|
|
85
|
+
if (n !== 1 / 0 || t?.allowInfinite)
|
|
86
|
+
return n;
|
|
87
|
+
throw new TypeError("Expected duration milliseconds to be finite.");
|
|
88
|
+
}
|
|
89
|
+
const U = {
|
|
90
|
+
[r]: 0,
|
|
23
91
|
isFinite: !1,
|
|
24
92
|
isInfinite: !1,
|
|
25
93
|
isInstant: !1,
|
|
26
|
-
to(
|
|
27
|
-
return this[
|
|
94
|
+
to(n) {
|
|
95
|
+
return this[r] / d[p(n)];
|
|
28
96
|
},
|
|
29
|
-
|
|
30
|
-
return this.to(
|
|
31
|
-
0
|
|
32
|
-
/* MilliSecond */
|
|
33
|
-
);
|
|
97
|
+
toMilliseconds() {
|
|
98
|
+
return this.to(e.Millisecond);
|
|
34
99
|
},
|
|
35
100
|
toSeconds() {
|
|
36
|
-
return this.to(
|
|
37
|
-
1
|
|
38
|
-
/* Second */
|
|
39
|
-
);
|
|
101
|
+
return this.to(e.Second);
|
|
40
102
|
},
|
|
41
103
|
toMinutes() {
|
|
42
|
-
return this.to(
|
|
43
|
-
2
|
|
44
|
-
/* Minute */
|
|
45
|
-
);
|
|
104
|
+
return this.to(e.Minute);
|
|
46
105
|
},
|
|
47
106
|
toHours() {
|
|
48
|
-
return this.to(
|
|
49
|
-
3
|
|
50
|
-
/* Hour */
|
|
51
|
-
);
|
|
107
|
+
return this.to(e.Hour);
|
|
52
108
|
},
|
|
53
109
|
toDays() {
|
|
54
|
-
return this.to(
|
|
55
|
-
4
|
|
56
|
-
/* Day */
|
|
57
|
-
);
|
|
110
|
+
return this.to(e.Day);
|
|
58
111
|
},
|
|
59
112
|
toWeeks() {
|
|
60
|
-
return this.to(
|
|
61
|
-
5
|
|
62
|
-
/* Week */
|
|
63
|
-
);
|
|
113
|
+
return this.to(e.Week);
|
|
64
114
|
},
|
|
65
115
|
toMonths() {
|
|
66
|
-
return this.to(
|
|
67
|
-
6
|
|
68
|
-
/* Month */
|
|
69
|
-
);
|
|
116
|
+
return this.to(e.Month);
|
|
70
117
|
},
|
|
71
118
|
toYears() {
|
|
72
|
-
return this.to(
|
|
73
|
-
7
|
|
74
|
-
/* Year */
|
|
75
|
-
);
|
|
119
|
+
return this.to(e.Year);
|
|
76
120
|
},
|
|
77
|
-
equals(
|
|
78
|
-
return this[
|
|
121
|
+
equals(n) {
|
|
122
|
+
return this[r] === n[r];
|
|
79
123
|
},
|
|
80
|
-
lessThan(
|
|
81
|
-
return this[
|
|
124
|
+
lessThan(n) {
|
|
125
|
+
return this[r] < n[r];
|
|
82
126
|
},
|
|
83
|
-
lessThanOrEqual(
|
|
84
|
-
return this[
|
|
127
|
+
lessThanOrEqual(n) {
|
|
128
|
+
return this[r] <= n[r];
|
|
85
129
|
},
|
|
86
|
-
greaterThan(
|
|
87
|
-
return this[
|
|
130
|
+
greaterThan(n) {
|
|
131
|
+
return this[r] > n[r];
|
|
88
132
|
},
|
|
89
|
-
greaterThanOrEqual(
|
|
90
|
-
return this[
|
|
133
|
+
greaterThanOrEqual(n) {
|
|
134
|
+
return this[r] >= n[r];
|
|
91
135
|
},
|
|
92
|
-
compare(
|
|
93
|
-
return this.lessThan(
|
|
136
|
+
compare(n) {
|
|
137
|
+
return this.lessThan(n) ? -1 : this.greaterThan(n) ? 1 : 0;
|
|
94
138
|
}
|
|
95
139
|
};
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
function e(t, r) {
|
|
101
|
-
return f(t, r);
|
|
102
|
-
}
|
|
103
|
-
function u(t) {
|
|
104
|
-
return e(
|
|
105
|
-
t,
|
|
106
|
-
0
|
|
107
|
-
/* MilliSecond */
|
|
108
|
-
);
|
|
140
|
+
function s(n, t) {
|
|
141
|
+
const i = O(n, t), o = Object.create(U);
|
|
142
|
+
return o[r] = i, o.isFinite = Number.isFinite(i), o.isInfinite = i === 1 / 0, o.isInstant = i === 0, Object.freeze(o);
|
|
109
143
|
}
|
|
110
|
-
function
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
);
|
|
144
|
+
function u(n, t) {
|
|
145
|
+
if (T(n))
|
|
146
|
+
return s(_(n));
|
|
147
|
+
const i = c(n, "value"), o = p(t);
|
|
148
|
+
return s(i * d[o]);
|
|
116
149
|
}
|
|
117
|
-
function
|
|
118
|
-
return e
|
|
119
|
-
t,
|
|
120
|
-
2
|
|
121
|
-
/* Minute */
|
|
122
|
-
);
|
|
150
|
+
function x(n) {
|
|
151
|
+
return u(n, e.Millisecond);
|
|
123
152
|
}
|
|
124
|
-
function
|
|
125
|
-
return e
|
|
126
|
-
t,
|
|
127
|
-
3
|
|
128
|
-
/* Hour */
|
|
129
|
-
);
|
|
153
|
+
function z(n) {
|
|
154
|
+
return u(n, e.Second);
|
|
130
155
|
}
|
|
131
|
-
function
|
|
132
|
-
return e
|
|
133
|
-
t,
|
|
134
|
-
4
|
|
135
|
-
/* Day */
|
|
136
|
-
);
|
|
156
|
+
function A(n) {
|
|
157
|
+
return u(n, e.Minute);
|
|
137
158
|
}
|
|
138
|
-
function
|
|
139
|
-
return e
|
|
140
|
-
t,
|
|
141
|
-
5
|
|
142
|
-
/* Week */
|
|
143
|
-
);
|
|
159
|
+
function Y(n) {
|
|
160
|
+
return u(n, e.Hour);
|
|
144
161
|
}
|
|
145
|
-
function
|
|
146
|
-
return e
|
|
147
|
-
t,
|
|
148
|
-
6
|
|
149
|
-
/* Month */
|
|
150
|
-
);
|
|
162
|
+
function v(n) {
|
|
163
|
+
return u(n, e.Day);
|
|
151
164
|
}
|
|
152
|
-
function
|
|
153
|
-
return e
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
);
|
|
165
|
+
function j(n) {
|
|
166
|
+
return u(n, e.Week);
|
|
167
|
+
}
|
|
168
|
+
function C(n) {
|
|
169
|
+
return u(n, e.Month);
|
|
158
170
|
}
|
|
159
|
-
function
|
|
160
|
-
return u(
|
|
171
|
+
function H(n) {
|
|
172
|
+
return u(n, e.Year);
|
|
161
173
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
174
|
+
function F(n, t) {
|
|
175
|
+
const i = a(n, "start"), o = a(t, "end");
|
|
176
|
+
return s(o - i);
|
|
164
177
|
}
|
|
165
|
-
function
|
|
166
|
-
return
|
|
178
|
+
function V(n) {
|
|
179
|
+
return F(n, /* @__PURE__ */ new Date());
|
|
180
|
+
}
|
|
181
|
+
function I(n) {
|
|
182
|
+
if (!n.isInfinite)
|
|
183
|
+
return n.toMilliseconds();
|
|
184
|
+
throw new TypeError("Expected `duration` to be finite.");
|
|
185
|
+
}
|
|
186
|
+
function W(n, t) {
|
|
187
|
+
return n.isInfinite || t.isInfinite ? f : s(n[r] + t[r]);
|
|
188
|
+
}
|
|
189
|
+
function R(n, t) {
|
|
190
|
+
if (n.isInfinite && t.isInfinite)
|
|
191
|
+
throw new TypeError("Cannot subtract `infinite` from `infinite`.");
|
|
192
|
+
if (n.isInfinite)
|
|
193
|
+
return f;
|
|
194
|
+
if (t.isInfinite)
|
|
195
|
+
throw new TypeError("Cannot subtract `infinite` from a finite duration.");
|
|
196
|
+
return s(n[r] - t[r]);
|
|
197
|
+
}
|
|
198
|
+
function q(n, t) {
|
|
199
|
+
const i = c(t, "multiplier");
|
|
200
|
+
if (!n.isInfinite)
|
|
201
|
+
return s(n[r] * i);
|
|
202
|
+
if (i > 0)
|
|
203
|
+
return f;
|
|
204
|
+
throw new TypeError(
|
|
205
|
+
"Cannot multiply `infinite` by zero or a negative number."
|
|
206
|
+
);
|
|
167
207
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
208
|
+
function K(n, t) {
|
|
209
|
+
const i = c(t, "divisor");
|
|
210
|
+
if (i === 0)
|
|
211
|
+
throw new TypeError("Cannot divide by zero.");
|
|
212
|
+
if (!n.isInfinite)
|
|
213
|
+
return s(n[r] / i);
|
|
214
|
+
if (i > 0)
|
|
215
|
+
return f;
|
|
216
|
+
throw new TypeError("Cannot divide `infinite` by a negative number.");
|
|
170
217
|
}
|
|
171
|
-
function
|
|
172
|
-
|
|
218
|
+
function $(n, t) {
|
|
219
|
+
const i = a(n, "date"), o = I(t);
|
|
220
|
+
return y(i + o, "result");
|
|
173
221
|
}
|
|
174
|
-
function
|
|
175
|
-
|
|
222
|
+
function L(n, t) {
|
|
223
|
+
const i = a(n, "date"), o = I(t);
|
|
224
|
+
return y(i - o, "result");
|
|
176
225
|
}
|
|
177
|
-
const
|
|
178
|
-
function
|
|
179
|
-
return
|
|
226
|
+
const f = s(1 / 0, { allowInfinite: !0 }), P = x(0);
|
|
227
|
+
function B(n) {
|
|
228
|
+
return T(n) && b(n, r);
|
|
180
229
|
}
|
|
181
|
-
function
|
|
182
|
-
return
|
|
230
|
+
function G(n, t) {
|
|
231
|
+
return n[r] === t[r];
|
|
183
232
|
}
|
|
184
233
|
export {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
e as TimeUnit,
|
|
235
|
+
W as add,
|
|
236
|
+
$ as addTo,
|
|
237
|
+
F as between,
|
|
238
|
+
v as days,
|
|
239
|
+
K as divide,
|
|
240
|
+
u as duration,
|
|
241
|
+
Y as hours,
|
|
242
|
+
f as infinite,
|
|
243
|
+
P as instant,
|
|
244
|
+
B as isDuration,
|
|
245
|
+
G as isEqual,
|
|
246
|
+
x as milliseconds,
|
|
247
|
+
A as minutes,
|
|
248
|
+
C as months,
|
|
249
|
+
q as multiply,
|
|
250
|
+
z as seconds,
|
|
251
|
+
V as since,
|
|
252
|
+
R as subtract,
|
|
253
|
+
L as subtractFrom,
|
|
254
|
+
j as weeks,
|
|
255
|
+
H as years
|
|
205
256
|
};
|
package/dist/lib/duration.d.ts
CHANGED
|
@@ -1,21 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Second
|
|
4
|
-
Minute
|
|
5
|
-
Hour
|
|
6
|
-
Day
|
|
7
|
-
Week
|
|
8
|
-
Month
|
|
9
|
-
Year
|
|
10
|
-
}
|
|
1
|
+
declare const TIME_UNIT_VALUES: {
|
|
2
|
+
readonly Millisecond: 0;
|
|
3
|
+
readonly Second: 1;
|
|
4
|
+
readonly Minute: 2;
|
|
5
|
+
readonly Hour: 3;
|
|
6
|
+
readonly Day: 4;
|
|
7
|
+
readonly Week: 5;
|
|
8
|
+
readonly Month: 6;
|
|
9
|
+
readonly Year: 7;
|
|
10
|
+
};
|
|
11
|
+
/** Supported runtime unit values used by `TimeUnit`. */
|
|
12
|
+
export type TimeUnit = (typeof TIME_UNIT_VALUES)[keyof typeof TIME_UNIT_VALUES];
|
|
13
|
+
/**
|
|
14
|
+
* Runtime time-unit constants accepted by `duration(value, unit)` and `d.to(unit)`.
|
|
15
|
+
*
|
|
16
|
+
* `Month` uses a 30-day approximation and `Year` uses a 365.25-day approximation.
|
|
17
|
+
*/
|
|
18
|
+
export declare const TimeUnit: {
|
|
19
|
+
readonly [Key in keyof typeof TIME_UNIT_VALUES]: TimeUnit;
|
|
20
|
+
};
|
|
21
|
+
declare const DURATION_PART_TIME_UNITS: {
|
|
22
|
+
readonly milliseconds: TimeUnit;
|
|
23
|
+
readonly seconds: TimeUnit;
|
|
24
|
+
readonly minutes: TimeUnit;
|
|
25
|
+
readonly hours: TimeUnit;
|
|
26
|
+
readonly days: TimeUnit;
|
|
27
|
+
readonly weeks: TimeUnit;
|
|
28
|
+
readonly months: TimeUnit;
|
|
29
|
+
readonly years: TimeUnit;
|
|
30
|
+
};
|
|
31
|
+
type DurationPartKey = keyof typeof DURATION_PART_TIME_UNITS;
|
|
32
|
+
type RequireAtLeastOne<T> = {
|
|
33
|
+
[Key in keyof T]-?: Required<Pick<T, Key>> & Partial<Omit<T, Key>>;
|
|
34
|
+
}[keyof T];
|
|
35
|
+
/** Input bag accepted by `duration(parts)` for strict multi-unit construction. */
|
|
36
|
+
export type DurationParts = RequireAtLeastOne<{
|
|
37
|
+
readonly [Key in DurationPartKey]?: number;
|
|
38
|
+
}>;
|
|
11
39
|
declare const millisecondsTag: unique symbol;
|
|
40
|
+
/** Immutable duration value with conversions, comparisons, and state flags. */
|
|
12
41
|
export type Duration = {
|
|
13
42
|
readonly [millisecondsTag]: number;
|
|
14
43
|
readonly isFinite: boolean;
|
|
15
44
|
readonly isInfinite: boolean;
|
|
16
45
|
readonly isInstant: boolean;
|
|
17
46
|
to(unit: TimeUnit): number;
|
|
18
|
-
|
|
47
|
+
toMilliseconds(): number;
|
|
19
48
|
toSeconds(): number;
|
|
20
49
|
toMinutes(): number;
|
|
21
50
|
toHours(): number;
|
|
@@ -30,24 +59,49 @@ export type Duration = {
|
|
|
30
59
|
greaterThanOrEqual(other: Duration): boolean;
|
|
31
60
|
compare(other: Duration): -1 | 0 | 1;
|
|
32
61
|
};
|
|
62
|
+
/** Creates a duration from a finite numeric value in the provided unit. */
|
|
33
63
|
export declare function duration(value: number, unit: TimeUnit): Duration;
|
|
34
|
-
|
|
64
|
+
/** Creates a duration from strict multi-unit parts. */
|
|
65
|
+
export declare function duration(parts: DurationParts): Duration;
|
|
66
|
+
/** Creates a duration from a finite millisecond value. */
|
|
67
|
+
export declare function milliseconds(value: number): Duration;
|
|
68
|
+
/** Creates a duration from a finite second value. */
|
|
35
69
|
export declare function seconds(value: number): Duration;
|
|
70
|
+
/** Creates a duration from a finite minute value. */
|
|
36
71
|
export declare function minutes(value: number): Duration;
|
|
72
|
+
/** Creates a duration from a finite hour value. */
|
|
37
73
|
export declare function hours(value: number): Duration;
|
|
74
|
+
/** Creates a duration from a finite day value. */
|
|
38
75
|
export declare function days(value: number): Duration;
|
|
76
|
+
/** Creates a duration from a finite week value. */
|
|
39
77
|
export declare function weeks(value: number): Duration;
|
|
78
|
+
/** Creates a duration from a finite approximate month value (30 days each). */
|
|
40
79
|
export declare function months(value: number): Duration;
|
|
80
|
+
/** Creates a duration from a finite approximate year value (365.25 days each). */
|
|
41
81
|
export declare function years(value: number): Duration;
|
|
82
|
+
/** Returns the duration between two valid dates. The result may be negative. */
|
|
42
83
|
export declare function between(start: Date, end: Date): Duration;
|
|
84
|
+
/** Returns the duration since a valid start date. The result may be negative. */
|
|
43
85
|
export declare function since(start: Date): Duration;
|
|
86
|
+
/** Adds two durations and preserves the explicit `infinite` sentinel. */
|
|
44
87
|
export declare function add(a: Duration, b: Duration): Duration;
|
|
88
|
+
/** Subtracts one duration from another and rejects undefined `infinite` cases. */
|
|
45
89
|
export declare function subtract(a: Duration, b: Duration): Duration;
|
|
90
|
+
/** Multiplies a duration by a finite scalar. */
|
|
46
91
|
export declare function multiply(a: Duration, b: number): Duration;
|
|
92
|
+
/** Divides a duration by a finite, non-zero scalar. */
|
|
47
93
|
export declare function divide(a: Duration, b: number): Duration;
|
|
94
|
+
/** Returns a new date shifted forward by an exact duration timestamp delta. */
|
|
95
|
+
export declare function addTo(date: Date, duration: Duration): Date;
|
|
96
|
+
/** Returns a new date shifted backward by an exact duration timestamp delta. */
|
|
97
|
+
export declare function subtractFrom(date: Date, duration: Duration): Date;
|
|
98
|
+
/** The explicit non-finite duration sentinel supported by this package. */
|
|
48
99
|
export declare const infinite: Duration;
|
|
100
|
+
/** The zero-length duration constant. */
|
|
49
101
|
export declare const instant: Duration;
|
|
102
|
+
/** Returns `true` when the value is a duration created by this package. */
|
|
50
103
|
export declare function isDuration(value: unknown): value is Duration;
|
|
104
|
+
/** Compares two durations by their normalized millisecond payload. */
|
|
51
105
|
export declare function isEqual(a: Duration, b: Duration): boolean;
|
|
52
106
|
export {};
|
|
53
107
|
//# sourceMappingURL=duration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../src/lib/duration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../src/lib/duration.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pvorona/duration",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
"./package.json": "./package.json",
|
|
11
11
|
".": {
|
|
12
|
-
"@pvorona/source": "./src/index.ts",
|
|
13
12
|
"types": "./dist/index.d.ts",
|
|
14
13
|
"import": "./dist/index.js",
|
|
15
14
|
"default": "./dist/index.js"
|
|
@@ -19,10 +18,15 @@
|
|
|
19
18
|
"dist",
|
|
20
19
|
"!**/*.tsbuildinfo"
|
|
21
20
|
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"check-consumer-types": "node ./scripts/check-consumer-types.mjs",
|
|
23
|
+
"check-package-surface": "node ./scripts/check-package-surface.mjs",
|
|
24
|
+
"prepublishOnly": "npm run check-consumer-types && npm run check-package-surface"
|
|
25
|
+
},
|
|
22
26
|
"publishConfig": {
|
|
23
27
|
"access": "public"
|
|
24
28
|
},
|
|
25
29
|
"dependencies": {
|
|
26
|
-
"@pvorona/assert": "~0.0
|
|
30
|
+
"@pvorona/assert": "~0.1.0"
|
|
27
31
|
}
|
|
28
32
|
}
|