@naturalcycles/js-lib 14.96.1 → 14.98.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/dist/datetime/dateInterval.d.ts +8 -7
- package/dist/datetime/dateInterval.js +18 -15
- package/dist/datetime/localDate.d.ts +20 -17
- package/dist/datetime/localDate.js +130 -102
- package/dist/datetime/localTime.d.ts +14 -12
- package/dist/datetime/localTime.js +34 -11
- package/dist/datetime/timeInterval.d.ts +38 -0
- package/dist/datetime/timeInterval.js +91 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/json-schema/jsonSchemaBuilder.d.ts +2 -2
- package/dist/math/math.util.d.ts +4 -0
- package/dist/math/math.util.js +8 -1
- package/dist/math/sma.d.ts +4 -0
- package/dist/math/sma.js +4 -0
- package/dist/types.d.ts +19 -11
- package/dist-esm/datetime/dateInterval.js +18 -15
- package/dist-esm/datetime/localDate.js +130 -102
- package/dist-esm/datetime/localTime.js +34 -11
- package/dist-esm/datetime/timeInterval.js +87 -0
- package/dist-esm/index.js +1 -0
- package/dist-esm/math/math.util.js +6 -0
- package/dist-esm/math/sma.js +4 -0
- package/package.json +1 -1
- package/src/datetime/dateInterval.ts +22 -18
- package/src/datetime/localDate.ts +149 -132
- package/src/datetime/localTime.ts +48 -22
- package/src/datetime/timeInterval.ts +104 -0
- package/src/index.ts +10 -2
- package/src/json-schema/jsonSchemaBuilder.ts +6 -2
- package/src/math/math.util.ts +7 -0
- package/src/math/sma.ts +4 -0
- package/src/types.ts +23 -11
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { _assert } from '../error/assert';
|
|
2
|
-
import { Sequence } from '../seq/seq';
|
|
3
|
-
import { END } from '../types';
|
|
4
2
|
import { LocalTime } from './localTime';
|
|
5
|
-
const
|
|
3
|
+
const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
4
|
+
const DATE_REGEX = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
5
|
+
/* eslint-disable no-dupe-class-members */
|
|
6
6
|
/**
|
|
7
7
|
* @experimental
|
|
8
8
|
*/
|
|
9
9
|
export class LocalDate {
|
|
10
|
-
constructor(year, month, day) {
|
|
11
|
-
this
|
|
12
|
-
this
|
|
13
|
-
this
|
|
10
|
+
constructor($year, $month, $day) {
|
|
11
|
+
this.$year = $year;
|
|
12
|
+
this.$month = $month;
|
|
13
|
+
this.$day = $day;
|
|
14
14
|
}
|
|
15
15
|
static create(year, month, day) {
|
|
16
16
|
return new LocalDate(year, month, day);
|
|
@@ -47,8 +47,13 @@ export class LocalDate {
|
|
|
47
47
|
return null;
|
|
48
48
|
if (d instanceof LocalDate)
|
|
49
49
|
return d;
|
|
50
|
-
//
|
|
51
|
-
const
|
|
50
|
+
// const [year, month, day] = d.slice(0, 10).split('-').map(Number)
|
|
51
|
+
const matches = DATE_REGEX.exec(d.slice(0, 10));
|
|
52
|
+
if (!matches)
|
|
53
|
+
return null;
|
|
54
|
+
const year = Number(matches[1]);
|
|
55
|
+
const month = Number(matches[2]);
|
|
56
|
+
const day = Number(matches[3]);
|
|
52
57
|
if (!year ||
|
|
53
58
|
!month ||
|
|
54
59
|
month < 1 ||
|
|
@@ -60,6 +65,10 @@ export class LocalDate {
|
|
|
60
65
|
}
|
|
61
66
|
return new LocalDate(year, month, day);
|
|
62
67
|
}
|
|
68
|
+
// Can use just .toString()
|
|
69
|
+
// static parseToString(d: LocalDateConfig): IsoDateString {
|
|
70
|
+
// return typeof d === 'string' ? d : d.toString()
|
|
71
|
+
// }
|
|
63
72
|
static isValid(iso) {
|
|
64
73
|
return this.parseOrNull(iso) !== null;
|
|
65
74
|
}
|
|
@@ -87,45 +96,63 @@ export class LocalDate {
|
|
|
87
96
|
_assert(items.length, 'LocalDate.latest called on empty array');
|
|
88
97
|
return items.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
|
|
89
98
|
}
|
|
90
|
-
static range(
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const max = LocalDate.of(
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
static range(min, max, incl = '[)', step = 1, stepUnit = 'day') {
|
|
100
|
+
const dates = [];
|
|
101
|
+
const $min = LocalDate.of(min);
|
|
102
|
+
const $max = LocalDate.of(max).startOf(stepUnit);
|
|
103
|
+
let current = $min.startOf(stepUnit);
|
|
104
|
+
if (current.isAfter($min, incl[0] === '[')) {
|
|
105
|
+
// ok
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
current.add(1, stepUnit, true);
|
|
109
|
+
}
|
|
110
|
+
const incl2 = incl[1] === ']';
|
|
111
|
+
while (current.isBefore($max, incl2)) {
|
|
112
|
+
dates.push(current);
|
|
96
113
|
current = current.add(step, stepUnit);
|
|
97
|
-
}
|
|
98
|
-
return
|
|
114
|
+
}
|
|
115
|
+
return dates;
|
|
116
|
+
}
|
|
117
|
+
get(unit) {
|
|
118
|
+
return unit === 'year' ? this.$year : unit === 'month' ? this.$month : this.$day;
|
|
99
119
|
}
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
set(unit, v, mutate = false) {
|
|
121
|
+
const t = mutate ? this : this.clone();
|
|
122
|
+
if (unit === 'year') {
|
|
123
|
+
t.$year = v;
|
|
124
|
+
}
|
|
125
|
+
else if (unit === 'month') {
|
|
126
|
+
t.$month = v;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
t.$day = v;
|
|
130
|
+
}
|
|
131
|
+
return t;
|
|
107
132
|
}
|
|
108
|
-
|
|
109
|
-
return
|
|
133
|
+
year(v) {
|
|
134
|
+
return v === undefined ? this.$year : this.set('year', v);
|
|
110
135
|
}
|
|
111
|
-
|
|
112
|
-
return
|
|
136
|
+
month(v) {
|
|
137
|
+
return v === undefined ? this.$month : this.set('month', v);
|
|
113
138
|
}
|
|
114
|
-
|
|
115
|
-
return
|
|
139
|
+
day(v) {
|
|
140
|
+
return v === undefined ? this.$day : this.set('day', v);
|
|
116
141
|
}
|
|
117
142
|
isSame(d) {
|
|
118
143
|
d = LocalDate.of(d);
|
|
119
|
-
return this
|
|
144
|
+
return this.$day === d.$day && this.$month === d.$month && this.$year === d.$year;
|
|
120
145
|
}
|
|
121
|
-
isBefore(d) {
|
|
122
|
-
|
|
146
|
+
isBefore(d, inclusive = false) {
|
|
147
|
+
const r = this.cmp(d);
|
|
148
|
+
return r === -1 || (r === 0 && inclusive);
|
|
123
149
|
}
|
|
124
150
|
isSameOrBefore(d) {
|
|
125
151
|
return this.cmp(d) <= 0;
|
|
126
152
|
}
|
|
127
|
-
isAfter(d) {
|
|
128
|
-
|
|
153
|
+
isAfter(d, inclusive = false) {
|
|
154
|
+
const r = this.cmp(d);
|
|
155
|
+
return r === 1 || (r === 0 && inclusive);
|
|
129
156
|
}
|
|
130
157
|
isSameOrAfter(d) {
|
|
131
158
|
return this.cmp(d) >= 0;
|
|
@@ -146,17 +173,17 @@ export class LocalDate {
|
|
|
146
173
|
*/
|
|
147
174
|
cmp(d) {
|
|
148
175
|
d = LocalDate.of(d);
|
|
149
|
-
if (this
|
|
176
|
+
if (this.$year < d.$year)
|
|
150
177
|
return -1;
|
|
151
|
-
if (this
|
|
178
|
+
if (this.$year > d.$year)
|
|
152
179
|
return 1;
|
|
153
|
-
if (this
|
|
180
|
+
if (this.$month < d.$month)
|
|
154
181
|
return -1;
|
|
155
|
-
if (this
|
|
182
|
+
if (this.$month > d.$month)
|
|
156
183
|
return 1;
|
|
157
|
-
if (this
|
|
184
|
+
if (this.$day < d.$day)
|
|
158
185
|
return -1;
|
|
159
|
-
if (this
|
|
186
|
+
if (this.$day > d.$day)
|
|
160
187
|
return 1;
|
|
161
188
|
return 0;
|
|
162
189
|
}
|
|
@@ -174,82 +201,87 @@ export class LocalDate {
|
|
|
174
201
|
diff(d, unit) {
|
|
175
202
|
d = LocalDate.of(d);
|
|
176
203
|
if (unit === 'year') {
|
|
177
|
-
return this
|
|
204
|
+
return this.$year - d.$year;
|
|
178
205
|
}
|
|
179
206
|
if (unit === 'month') {
|
|
180
|
-
return (this
|
|
207
|
+
return (this.$year - d.$year) * 12 + (this.$month - d.$month);
|
|
181
208
|
}
|
|
182
209
|
// unit is 'day'
|
|
183
|
-
let days = this
|
|
184
|
-
if (d
|
|
185
|
-
for (let year = d
|
|
210
|
+
let days = this.$day - d.$day;
|
|
211
|
+
if (d.$year < this.$year) {
|
|
212
|
+
for (let year = d.$year; year < this.$year; year++) {
|
|
186
213
|
days += LocalDate.getYearLength(year);
|
|
187
214
|
}
|
|
188
215
|
}
|
|
189
|
-
else if (this
|
|
190
|
-
for (let year = this
|
|
216
|
+
else if (this.$year < d.$year) {
|
|
217
|
+
for (let year = this.$year; year < d.$year; year++) {
|
|
191
218
|
days -= LocalDate.getYearLength(year);
|
|
192
219
|
}
|
|
193
220
|
}
|
|
194
|
-
if (d
|
|
195
|
-
for (let month = d
|
|
196
|
-
days += LocalDate.getMonthLength(this
|
|
221
|
+
if (d.$month < this.$month) {
|
|
222
|
+
for (let month = d.$month; month < this.$month; month++) {
|
|
223
|
+
days += LocalDate.getMonthLength(this.$year, month);
|
|
197
224
|
}
|
|
198
225
|
}
|
|
199
|
-
else if (this
|
|
200
|
-
for (let month = this
|
|
201
|
-
days -= LocalDate.getMonthLength(d
|
|
226
|
+
else if (this.$month < d.$month) {
|
|
227
|
+
for (let month = this.$month; month < d.$month; month++) {
|
|
228
|
+
days -= LocalDate.getMonthLength(d.$year, month);
|
|
202
229
|
}
|
|
203
230
|
}
|
|
204
231
|
return days;
|
|
205
232
|
}
|
|
206
233
|
add(num, unit, mutate = false) {
|
|
207
|
-
let { day, month, year } = this;
|
|
234
|
+
let { $day, $month, $year } = this;
|
|
208
235
|
if (unit === 'day') {
|
|
209
|
-
day += num;
|
|
236
|
+
$day += num;
|
|
210
237
|
}
|
|
211
238
|
else if (unit === 'month') {
|
|
212
|
-
month += num;
|
|
239
|
+
$month += num;
|
|
213
240
|
}
|
|
214
241
|
else if (unit === 'year') {
|
|
215
|
-
year += num;
|
|
242
|
+
$year += num;
|
|
216
243
|
}
|
|
217
244
|
// check day overflow
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
if (unit === 'day') {
|
|
246
|
+
if ($day < 1) {
|
|
247
|
+
while ($day < 1) {
|
|
248
|
+
$month -= 1;
|
|
249
|
+
if ($month < 1) {
|
|
250
|
+
$year -= 1;
|
|
251
|
+
$month += 12;
|
|
252
|
+
}
|
|
253
|
+
$day += LocalDate.getMonthLength($year, $month);
|
|
254
|
+
}
|
|
225
255
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
256
|
+
else {
|
|
257
|
+
let monLen = LocalDate.getMonthLength($year, $month);
|
|
258
|
+
while ($day > monLen) {
|
|
259
|
+
$day -= monLen;
|
|
260
|
+
$month += 1;
|
|
261
|
+
if ($month > 12) {
|
|
262
|
+
$year += 1;
|
|
263
|
+
$month -= 12;
|
|
264
|
+
}
|
|
265
|
+
monLen = LocalDate.getMonthLength($year, $month);
|
|
266
|
+
}
|
|
234
267
|
}
|
|
235
|
-
monLen = LocalDate.getMonthLength(year, month);
|
|
236
268
|
}
|
|
237
269
|
// check month overflow
|
|
238
|
-
while (month > 12) {
|
|
239
|
-
year += 1;
|
|
240
|
-
month -= 12;
|
|
270
|
+
while ($month > 12) {
|
|
271
|
+
$year += 1;
|
|
272
|
+
$month -= 12;
|
|
241
273
|
}
|
|
242
|
-
while (month < 1) {
|
|
243
|
-
year -= 1;
|
|
244
|
-
month += 12;
|
|
274
|
+
while ($month < 1) {
|
|
275
|
+
$year -= 1;
|
|
276
|
+
$month += 12;
|
|
245
277
|
}
|
|
246
278
|
if (mutate) {
|
|
247
|
-
this
|
|
248
|
-
this
|
|
249
|
-
this
|
|
279
|
+
this.$year = $year;
|
|
280
|
+
this.$month = $month;
|
|
281
|
+
this.$day = $day;
|
|
250
282
|
return this;
|
|
251
283
|
}
|
|
252
|
-
return new LocalDate(year, month, day);
|
|
284
|
+
return new LocalDate($year, $month, $day);
|
|
253
285
|
}
|
|
254
286
|
subtract(num, unit, mutate = false) {
|
|
255
287
|
return this.add(-num, unit, mutate);
|
|
@@ -258,17 +290,17 @@ export class LocalDate {
|
|
|
258
290
|
if (unit === 'day')
|
|
259
291
|
return this;
|
|
260
292
|
if (unit === 'month')
|
|
261
|
-
return LocalDate.create(this
|
|
293
|
+
return LocalDate.create(this.$year, this.$month, 1);
|
|
262
294
|
// year
|
|
263
|
-
return LocalDate.create(this
|
|
295
|
+
return LocalDate.create(this.$year, 1, 1);
|
|
264
296
|
}
|
|
265
297
|
endOf(unit) {
|
|
266
298
|
if (unit === 'day')
|
|
267
299
|
return this;
|
|
268
300
|
if (unit === 'month')
|
|
269
|
-
return LocalDate.create(this
|
|
301
|
+
return LocalDate.create(this.$year, this.$month, LocalDate.getMonthLength(this.$year, this.$month));
|
|
270
302
|
// year
|
|
271
|
-
return LocalDate.create(this
|
|
303
|
+
return LocalDate.create(this.$year, 12, 31);
|
|
272
304
|
}
|
|
273
305
|
static getYearLength(year) {
|
|
274
306
|
return this.isLeapYear(year) ? 366 : 365;
|
|
@@ -276,17 +308,13 @@ export class LocalDate {
|
|
|
276
308
|
static getMonthLength(year, month) {
|
|
277
309
|
if (month === 2)
|
|
278
310
|
return this.isLeapYear(year) ? 29 : 28;
|
|
279
|
-
return
|
|
311
|
+
return MDAYS[month];
|
|
280
312
|
}
|
|
281
313
|
static isLeapYear(year) {
|
|
282
|
-
|
|
283
|
-
return false;
|
|
284
|
-
if (year % 100 !== 0)
|
|
285
|
-
return true;
|
|
286
|
-
return year % 400 === 0;
|
|
314
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
287
315
|
}
|
|
288
316
|
clone() {
|
|
289
|
-
return new LocalDate(this
|
|
317
|
+
return new LocalDate(this.$year, this.$month, this.$day);
|
|
290
318
|
}
|
|
291
319
|
/**
|
|
292
320
|
* Converts LocalDate into instance of Date.
|
|
@@ -295,7 +323,7 @@ export class LocalDate {
|
|
|
295
323
|
* Timezone will match local timezone.
|
|
296
324
|
*/
|
|
297
325
|
toDate() {
|
|
298
|
-
return new Date(this
|
|
326
|
+
return new Date(this.$year, this.$month - 1, this.$day);
|
|
299
327
|
}
|
|
300
328
|
toLocalTime() {
|
|
301
329
|
return LocalTime.of(this.toDate());
|
|
@@ -305,16 +333,16 @@ export class LocalDate {
|
|
|
305
333
|
}
|
|
306
334
|
toString() {
|
|
307
335
|
return [
|
|
308
|
-
String(this
|
|
309
|
-
String(this
|
|
310
|
-
String(this
|
|
336
|
+
String(this.$year).padStart(4, '0'),
|
|
337
|
+
String(this.$month).padStart(2, '0'),
|
|
338
|
+
String(this.$day).padStart(2, '0'),
|
|
311
339
|
].join('-');
|
|
312
340
|
}
|
|
313
341
|
toStringCompact() {
|
|
314
342
|
return [
|
|
315
|
-
String(this
|
|
316
|
-
String(this
|
|
317
|
-
String(this
|
|
343
|
+
String(this.$year).padStart(4, '0'),
|
|
344
|
+
String(this.$month).padStart(2, '0'),
|
|
345
|
+
String(this.$day).padStart(2, '0'),
|
|
318
346
|
].join('');
|
|
319
347
|
}
|
|
320
348
|
// May be not optimal, as LocalTime better suits it
|
|
@@ -45,7 +45,7 @@ export class LocalTime {
|
|
|
45
45
|
date = new Date(d * 1000);
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
|
-
date = new Date(d);
|
|
48
|
+
date = new Date(d.slice(0, 19));
|
|
49
49
|
}
|
|
50
50
|
// validation
|
|
51
51
|
if (isNaN(date.getDate())) {
|
|
@@ -57,6 +57,28 @@ export class LocalTime {
|
|
|
57
57
|
// }
|
|
58
58
|
return new LocalTime(date, false);
|
|
59
59
|
}
|
|
60
|
+
static parseToDate(d) {
|
|
61
|
+
if (d instanceof LocalTime)
|
|
62
|
+
return d.$date;
|
|
63
|
+
if (d instanceof Date)
|
|
64
|
+
return d;
|
|
65
|
+
const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
|
|
66
|
+
if (isNaN(date.getDate())) {
|
|
67
|
+
throw new TypeError(`Cannot parse "${d}" to Date`);
|
|
68
|
+
}
|
|
69
|
+
return date;
|
|
70
|
+
}
|
|
71
|
+
static parseToUnixTimestamp(d) {
|
|
72
|
+
if (typeof d === 'number')
|
|
73
|
+
return d;
|
|
74
|
+
if (d instanceof LocalTime)
|
|
75
|
+
return d.unix();
|
|
76
|
+
const date = d instanceof Date ? d : new Date(d);
|
|
77
|
+
if (isNaN(date.getDate())) {
|
|
78
|
+
throw new TypeError(`Cannot parse "${d}" to UnixTimestamp`);
|
|
79
|
+
}
|
|
80
|
+
return date.valueOf() / 1000;
|
|
81
|
+
}
|
|
60
82
|
static isValid(d) {
|
|
61
83
|
return this.parseOrNull(d) !== null;
|
|
62
84
|
}
|
|
@@ -115,7 +137,7 @@ export class LocalTime {
|
|
|
115
137
|
month(v) {
|
|
116
138
|
return v === undefined ? this.get('month') : this.set('month', v);
|
|
117
139
|
}
|
|
118
|
-
|
|
140
|
+
day(v) {
|
|
119
141
|
return v === undefined ? this.get('day') : this.set('day', v);
|
|
120
142
|
}
|
|
121
143
|
hour(v) {
|
|
@@ -161,7 +183,7 @@ export class LocalTime {
|
|
|
161
183
|
return Math.abs(this.diff(other, unit));
|
|
162
184
|
}
|
|
163
185
|
diff(other, unit) {
|
|
164
|
-
const date2 = LocalTime.
|
|
186
|
+
const date2 = LocalTime.parseToDate(other);
|
|
165
187
|
if (unit === 'year') {
|
|
166
188
|
return this.$date.getFullYear() - date2.getFullYear();
|
|
167
189
|
}
|
|
@@ -238,14 +260,16 @@ export class LocalTime {
|
|
|
238
260
|
isSame(d) {
|
|
239
261
|
return this.cmp(d) === 0;
|
|
240
262
|
}
|
|
241
|
-
isBefore(d) {
|
|
242
|
-
|
|
263
|
+
isBefore(d, inclusive = false) {
|
|
264
|
+
const r = this.cmp(d);
|
|
265
|
+
return r === -1 || (r === 0 && inclusive);
|
|
243
266
|
}
|
|
244
267
|
isSameOrBefore(d) {
|
|
245
268
|
return this.cmp(d) <= 0;
|
|
246
269
|
}
|
|
247
|
-
isAfter(d) {
|
|
248
|
-
|
|
270
|
+
isAfter(d, inclusive = false) {
|
|
271
|
+
const r = this.cmp(d);
|
|
272
|
+
return r === 1 || (r === 0 && inclusive);
|
|
249
273
|
}
|
|
250
274
|
isSameOrAfter(d) {
|
|
251
275
|
return this.cmp(d) >= 0;
|
|
@@ -266,7 +290,7 @@ export class LocalTime {
|
|
|
266
290
|
*/
|
|
267
291
|
cmp(d) {
|
|
268
292
|
const t1 = this.$date.valueOf();
|
|
269
|
-
const t2 = LocalTime.
|
|
293
|
+
const t2 = LocalTime.parseToDate(d).valueOf();
|
|
270
294
|
if (t1 === t2)
|
|
271
295
|
return 0;
|
|
272
296
|
return t1 < t2 ? -1 : 1;
|
|
@@ -292,8 +316,8 @@ export class LocalTime {
|
|
|
292
316
|
second: this.$date.getSeconds(),
|
|
293
317
|
};
|
|
294
318
|
}
|
|
295
|
-
fromNow(now =
|
|
296
|
-
const msDiff = LocalTime.
|
|
319
|
+
fromNow(now = new Date()) {
|
|
320
|
+
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
297
321
|
if (msDiff === 0)
|
|
298
322
|
return 'now';
|
|
299
323
|
if (msDiff >= 0) {
|
|
@@ -403,4 +427,3 @@ export class LocalTime {
|
|
|
403
427
|
export function localTime(d) {
|
|
404
428
|
return d ? LocalTime.of(d) : LocalTime.now();
|
|
405
429
|
}
|
|
406
|
-
// todo: range
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { LocalTime } from './localTime';
|
|
2
|
+
/**
|
|
3
|
+
* Class that supports an "interval of time" between 2 timestamps - start and end.
|
|
4
|
+
* Example: `1649267185/1649267187`.
|
|
5
|
+
*
|
|
6
|
+
* @experimental
|
|
7
|
+
*/
|
|
8
|
+
export class TimeInterval {
|
|
9
|
+
constructor($start, $end) {
|
|
10
|
+
this.$start = $start;
|
|
11
|
+
this.$end = $end;
|
|
12
|
+
}
|
|
13
|
+
static of(start, end) {
|
|
14
|
+
return new TimeInterval(LocalTime.parseToUnixTimestamp(start), LocalTime.parseToUnixTimestamp(end));
|
|
15
|
+
}
|
|
16
|
+
get start() {
|
|
17
|
+
return this.$start;
|
|
18
|
+
}
|
|
19
|
+
get end() {
|
|
20
|
+
return this.$end;
|
|
21
|
+
}
|
|
22
|
+
get startTime() {
|
|
23
|
+
return LocalTime.of(this.$start);
|
|
24
|
+
}
|
|
25
|
+
get endTime() {
|
|
26
|
+
return LocalTime.of(this.$end);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parses string like `1649267185/1649267187` into a TimeInterval.
|
|
30
|
+
*/
|
|
31
|
+
static parse(d) {
|
|
32
|
+
if (d instanceof TimeInterval)
|
|
33
|
+
return d;
|
|
34
|
+
const [start, end] = d.split('/').map(Number);
|
|
35
|
+
if (!end || !start) {
|
|
36
|
+
throw new Error(`Cannot parse "${d}" into TimeInterval`);
|
|
37
|
+
}
|
|
38
|
+
return new TimeInterval(start, end);
|
|
39
|
+
}
|
|
40
|
+
isSame(d) {
|
|
41
|
+
return this.cmp(d) === 0;
|
|
42
|
+
}
|
|
43
|
+
isBefore(d, inclusive = false) {
|
|
44
|
+
const r = this.cmp(d);
|
|
45
|
+
return r === -1 || (r === 0 && inclusive);
|
|
46
|
+
}
|
|
47
|
+
isSameOrBefore(d) {
|
|
48
|
+
return this.cmp(d) <= 0;
|
|
49
|
+
}
|
|
50
|
+
isAfter(d, inclusive = false) {
|
|
51
|
+
const r = this.cmp(d);
|
|
52
|
+
return r === 1 || (r === 0 && inclusive);
|
|
53
|
+
}
|
|
54
|
+
isSameOrAfter(d) {
|
|
55
|
+
return this.cmp(d) >= 0;
|
|
56
|
+
}
|
|
57
|
+
includes(d, incl = '[)') {
|
|
58
|
+
d = LocalTime.parseToUnixTimestamp(d);
|
|
59
|
+
if (d < this.$start || (d === this.$start && incl[0] === '('))
|
|
60
|
+
return false;
|
|
61
|
+
if (d > this.$end || (d === this.$end && incl[1] === ')'))
|
|
62
|
+
return false;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* TimeIntervals compare by start date.
|
|
67
|
+
* If it's the same - then by end date.
|
|
68
|
+
*/
|
|
69
|
+
cmp(d) {
|
|
70
|
+
d = TimeInterval.parse(d);
|
|
71
|
+
if (this.$start > d.$start)
|
|
72
|
+
return 1;
|
|
73
|
+
if (this.$start < d.$start)
|
|
74
|
+
return -1;
|
|
75
|
+
if (this.$end > d.$end)
|
|
76
|
+
return 1;
|
|
77
|
+
if (this.$end < d.$end)
|
|
78
|
+
return -1;
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
toString() {
|
|
82
|
+
return [this.$start, this.$end].join('/');
|
|
83
|
+
}
|
|
84
|
+
toJSON() {
|
|
85
|
+
return this.toString();
|
|
86
|
+
}
|
|
87
|
+
}
|
package/dist-esm/index.js
CHANGED
|
@@ -59,4 +59,5 @@ export * from './string/leven';
|
|
|
59
59
|
export * from './datetime/localDate';
|
|
60
60
|
export * from './datetime/localTime';
|
|
61
61
|
export * from './datetime/dateInterval';
|
|
62
|
+
export * from './datetime/timeInterval';
|
|
62
63
|
export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pRetryFn, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
|
|
@@ -10,6 +10,12 @@ import { _sortNumbers } from '../number/number.util';
|
|
|
10
10
|
export function _average(values) {
|
|
11
11
|
return values.reduce((a, b) => a + b) / values.length;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Same as _average, but safely returns null if input array is empty or nullish.
|
|
15
|
+
*/
|
|
16
|
+
export function _averageOrNull(values) {
|
|
17
|
+
return (values === null || values === void 0 ? void 0 : values.length) ? values.reduce((a, b) => a + b) / values.length : null;
|
|
18
|
+
}
|
|
13
19
|
/**
|
|
14
20
|
* valuesArray and weightsArray length is expected to be the same.
|
|
15
21
|
*/
|
package/dist-esm/math/sma.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LocalDate, LocalDateConfig } from './localDate'
|
|
1
|
+
import { Inclusiveness, LocalDate, LocalDateConfig, LocalDateUnit } from './localDate'
|
|
2
2
|
|
|
3
|
-
export type DateIntervalConfig = DateInterval |
|
|
3
|
+
export type DateIntervalConfig = DateInterval | DateIntervalString
|
|
4
4
|
export type DateIntervalString = string
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -34,16 +34,18 @@ export class DateInterval {
|
|
|
34
34
|
return this.cmp(d) === 0
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
isBefore(d: DateIntervalConfig): boolean {
|
|
38
|
-
|
|
37
|
+
isBefore(d: DateIntervalConfig, inclusive = false): boolean {
|
|
38
|
+
const r = this.cmp(d)
|
|
39
|
+
return r === -1 || (r === 0 && inclusive)
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
isSameOrBefore(d: DateIntervalConfig): boolean {
|
|
42
43
|
return this.cmp(d) <= 0
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
isAfter(d: DateIntervalConfig): boolean {
|
|
46
|
-
|
|
46
|
+
isAfter(d: DateIntervalConfig, inclusive = false): boolean {
|
|
47
|
+
const r = this.cmp(d)
|
|
48
|
+
return r === 1 || (r === 0 && inclusive)
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
isSameOrAfter(d: DateIntervalConfig): boolean {
|
|
@@ -53,9 +55,15 @@ export class DateInterval {
|
|
|
53
55
|
/**
|
|
54
56
|
* Ranges of DateInterval (start, end) are INCLUSIVE.
|
|
55
57
|
*/
|
|
56
|
-
includes(d: LocalDateConfig): boolean {
|
|
58
|
+
includes(d: LocalDateConfig, incl: Inclusiveness = '[]'): boolean {
|
|
57
59
|
d = LocalDate.of(d)
|
|
58
|
-
return d.
|
|
60
|
+
return d.isAfter(this.start, incl[0] === '[') && d.isBefore(this.end, incl[1] === ']')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
intersects(int: DateIntervalConfig, inclusive = true): boolean {
|
|
64
|
+
const $int = DateInterval.parse(int)
|
|
65
|
+
const incl = inclusive ? '[]' : '()'
|
|
66
|
+
return this.includes($int.start, incl) || this.includes($int.end, incl)
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
/**
|
|
@@ -67,19 +75,15 @@ export class DateInterval {
|
|
|
67
75
|
return this.start.cmp(d.start) || this.end.cmp(d.end)
|
|
68
76
|
}
|
|
69
77
|
|
|
78
|
+
getDays(incl: Inclusiveness = '[]'): LocalDate[] {
|
|
79
|
+
return LocalDate.range(this.start, this.end, incl, 1, 'day')
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
/**
|
|
71
83
|
* Returns an array of LocalDates that are included in the interval.
|
|
72
|
-
* Ranges are INCLUSIVE.
|
|
73
84
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let current = this.start
|
|
77
|
-
do {
|
|
78
|
-
days.push(current)
|
|
79
|
-
current = current.add(1, 'day')
|
|
80
|
-
} while (current.isSameOrBefore(this.end))
|
|
81
|
-
|
|
82
|
-
return days
|
|
85
|
+
range(incl: Inclusiveness = '[]', step = 1, stepUnit: LocalDateUnit = 'day'): LocalDate[] {
|
|
86
|
+
return LocalDate.range(this.start, this.end, incl, step, stepUnit)
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
toString(): DateIntervalString {
|