@naturalcycles/js-lib 14.232.0 → 14.233.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 +1 -2
- package/dist/datetime/dateInterval.js +5 -5
- package/dist/datetime/localDate.d.ts +125 -52
- package/dist/datetime/localDate.js +259 -201
- package/dist/datetime/localTime.d.ts +46 -51
- package/dist/datetime/localTime.js +181 -197
- package/dist/datetime/timeInterval.d.ts +1 -2
- package/dist/datetime/timeInterval.js +4 -4
- package/dist/env/buildInfo.js +1 -1
- package/dist-esm/datetime/dateInterval.js +6 -6
- package/dist-esm/datetime/localDate.js +259 -195
- package/dist-esm/datetime/localTime.js +177 -192
- package/dist-esm/datetime/timeInterval.js +5 -5
- package/dist-esm/env/buildInfo.js +2 -2
- package/package.json +2 -2
- package/src/datetime/dateInterval.ts +6 -7
- package/src/datetime/localDate.ts +307 -237
- package/src/datetime/localTime.ts +203 -212
- package/src/datetime/timeInterval.ts +6 -7
- package/src/env/buildInfo.ts +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _assert } from '../error/assert';
|
|
2
2
|
import { _ms } from '../time/time.util';
|
|
3
|
-
import {
|
|
3
|
+
import { localDate } from './localDate';
|
|
4
4
|
export var ISODayOfWeek;
|
|
5
5
|
(function (ISODayOfWeek) {
|
|
6
6
|
ISODayOfWeek[ISODayOfWeek["MONDAY"] = 1] = "MONDAY";
|
|
@@ -17,104 +17,19 @@ const SECONDS_IN_DAY = 86400;
|
|
|
17
17
|
// const MILLISECONDS_IN_DAY = 86400000
|
|
18
18
|
// const MILLISECONDS_IN_MINUTE = 60000
|
|
19
19
|
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
|
|
20
|
-
/**
|
|
21
|
-
* @experimental
|
|
22
|
-
*/
|
|
23
20
|
export class LocalTime {
|
|
24
21
|
constructor($date) {
|
|
25
22
|
this.$date = $date;
|
|
26
23
|
}
|
|
27
24
|
/**
|
|
28
|
-
*
|
|
29
|
-
* Input can already be a LocalDate - it is returned as-is in that case.
|
|
30
|
-
*/
|
|
31
|
-
static of(d) {
|
|
32
|
-
const t = this.parseOrNull(d);
|
|
33
|
-
_assert(t !== null, `Cannot parse "${d}" into LocalTime`, {
|
|
34
|
-
input: d,
|
|
35
|
-
});
|
|
36
|
-
return t;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
40
|
-
*/
|
|
41
|
-
static ofMillis(millis) {
|
|
42
|
-
return LocalTime.of(new Date(millis));
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Returns null if invalid
|
|
46
|
-
*/
|
|
47
|
-
static parseOrNull(d) {
|
|
48
|
-
if (!d)
|
|
49
|
-
return null;
|
|
50
|
-
if (d instanceof LocalTime)
|
|
51
|
-
return d;
|
|
52
|
-
let date;
|
|
53
|
-
if (d instanceof Date) {
|
|
54
|
-
date = d;
|
|
55
|
-
}
|
|
56
|
-
else if (typeof d === 'number') {
|
|
57
|
-
date = new Date(d * 1000);
|
|
58
|
-
}
|
|
59
|
-
else if (typeof d !== 'string') {
|
|
60
|
-
// unexpected type, e.g Function or something
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
// Slicing removes the "timezone component", and makes the date "local"
|
|
65
|
-
// e.g 2022-04-06T23:15:00+09:00
|
|
66
|
-
// becomes 2022-04-06T23:15:00
|
|
67
|
-
date = new Date(d.slice(0, 19));
|
|
68
|
-
// We used to slice to remove the timezone information, now we don't
|
|
69
|
-
// date = new Date(d)
|
|
70
|
-
}
|
|
71
|
-
// validation
|
|
72
|
-
if (isNaN(date.getDate())) {
|
|
73
|
-
// throw new TypeError(`Cannot parse "${d}" into LocalTime`)
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
return new LocalTime(date);
|
|
77
|
-
}
|
|
78
|
-
static parseToDate(d) {
|
|
79
|
-
if (d instanceof LocalTime)
|
|
80
|
-
return d.$date;
|
|
81
|
-
if (d instanceof Date)
|
|
82
|
-
return d;
|
|
83
|
-
const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
|
|
84
|
-
_assert(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
|
|
85
|
-
input: d,
|
|
86
|
-
});
|
|
87
|
-
return date;
|
|
88
|
-
}
|
|
89
|
-
static parseToUnixTimestamp(d) {
|
|
90
|
-
if (typeof d === 'number')
|
|
91
|
-
return d;
|
|
92
|
-
if (d instanceof LocalTime)
|
|
93
|
-
return d.unix();
|
|
94
|
-
const date = d instanceof Date ? d : new Date(d);
|
|
95
|
-
_assert(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
|
|
96
|
-
input: d,
|
|
97
|
-
});
|
|
98
|
-
return date.valueOf() / 1000;
|
|
99
|
-
}
|
|
100
|
-
static isValid(d) {
|
|
101
|
-
return this.parseOrNull(d) !== null;
|
|
102
|
-
}
|
|
103
|
-
static now() {
|
|
104
|
-
return new LocalTime(new Date());
|
|
105
|
-
}
|
|
106
|
-
static fromComponents(c) {
|
|
107
|
-
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Returns LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
25
|
+
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
111
26
|
* Opposite of `.local()` method.
|
|
112
27
|
*/
|
|
113
28
|
utc() {
|
|
114
29
|
return new LocalTime(new Date(this.$date.toISOString()));
|
|
115
30
|
}
|
|
116
31
|
/**
|
|
117
|
-
* Returns LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
32
|
+
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
118
33
|
* Opposite of `.utc()` method.
|
|
119
34
|
*/
|
|
120
35
|
local() {
|
|
@@ -221,7 +136,7 @@ export class LocalTime {
|
|
|
221
136
|
}
|
|
222
137
|
if (unit === 'year' || unit === 'month') {
|
|
223
138
|
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
|
|
224
|
-
return mutate ? this :
|
|
139
|
+
return mutate ? this : localTime.of(d);
|
|
225
140
|
}
|
|
226
141
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
227
142
|
}
|
|
@@ -232,16 +147,16 @@ export class LocalTime {
|
|
|
232
147
|
return Math.abs(this.diff(other, unit));
|
|
233
148
|
}
|
|
234
149
|
diff(other, unit) {
|
|
235
|
-
const date2 =
|
|
150
|
+
const date2 = localTime.parseToDate(other);
|
|
236
151
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
237
152
|
if (!secDiff)
|
|
238
153
|
return 0;
|
|
239
154
|
let r;
|
|
240
155
|
if (unit === 'year') {
|
|
241
|
-
r = differenceInMonths(this
|
|
156
|
+
r = differenceInMonths(this.$date, date2) / 12;
|
|
242
157
|
}
|
|
243
158
|
else if (unit === 'month') {
|
|
244
|
-
r = differenceInMonths(this
|
|
159
|
+
r = differenceInMonths(this.$date, date2);
|
|
245
160
|
}
|
|
246
161
|
else if (unit === 'day') {
|
|
247
162
|
r = secDiff / SECONDS_IN_DAY;
|
|
@@ -308,7 +223,7 @@ export class LocalTime {
|
|
|
308
223
|
}
|
|
309
224
|
else {
|
|
310
225
|
// year or month
|
|
311
|
-
const lastDay =
|
|
226
|
+
const lastDay = localDate.getMonthLength(d.getFullYear(), d.getMonth() + 1);
|
|
312
227
|
d.setDate(lastDay);
|
|
313
228
|
}
|
|
314
229
|
}
|
|
@@ -321,35 +236,7 @@ export class LocalTime {
|
|
|
321
236
|
* E.g 31 for January.
|
|
322
237
|
*/
|
|
323
238
|
daysInMonth() {
|
|
324
|
-
return
|
|
325
|
-
}
|
|
326
|
-
static sort(items, mutate = false, dir = 'asc') {
|
|
327
|
-
const mod = dir === 'desc' ? -1 : 1;
|
|
328
|
-
return (mutate ? items : [...items]).sort((a, b) => {
|
|
329
|
-
const v1 = a.$date.valueOf();
|
|
330
|
-
const v2 = b.$date.valueOf();
|
|
331
|
-
if (v1 === v2)
|
|
332
|
-
return 0;
|
|
333
|
-
return (v1 < v2 ? -1 : 1) * mod;
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
static earliestOrUndefined(items) {
|
|
337
|
-
return items.length ? LocalTime.earliest(items) : undefined;
|
|
338
|
-
}
|
|
339
|
-
static earliest(items) {
|
|
340
|
-
_assert(items.length, 'LocalTime.earliest called on empty array');
|
|
341
|
-
return items
|
|
342
|
-
.map(i => LocalTime.of(i))
|
|
343
|
-
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
|
|
344
|
-
}
|
|
345
|
-
static latestOrUndefined(items) {
|
|
346
|
-
return items.length ? LocalTime.latest(items) : undefined;
|
|
347
|
-
}
|
|
348
|
-
static latest(items) {
|
|
349
|
-
_assert(items.length, 'LocalTime.latest called on empty array');
|
|
350
|
-
return items
|
|
351
|
-
.map(i => LocalTime.of(i))
|
|
352
|
-
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
|
|
239
|
+
return localDate.getMonthLength(this.$date.getFullYear(), this.$date.getMonth() + 1);
|
|
353
240
|
}
|
|
354
241
|
isSame(d) {
|
|
355
242
|
return this.cmp(d) === 0;
|
|
@@ -388,13 +275,13 @@ export class LocalTime {
|
|
|
388
275
|
* Third argument allows to override "now".
|
|
389
276
|
*/
|
|
390
277
|
isOlderThan(n, unit, now) {
|
|
391
|
-
return this.isBefore(
|
|
278
|
+
return this.isBefore(localTime.of(now !== null && now !== void 0 ? now : new Date()).plus(-n, unit));
|
|
392
279
|
}
|
|
393
280
|
/**
|
|
394
281
|
* Checks if this localTime is same or older (<=) than "now" by X units.
|
|
395
282
|
*/
|
|
396
283
|
isSameOrOlderThan(n, unit, now) {
|
|
397
|
-
return this.isSameOrBefore(
|
|
284
|
+
return this.isSameOrBefore(localTime.of(now !== null && now !== void 0 ? now : new Date()).plus(-n, unit));
|
|
398
285
|
}
|
|
399
286
|
/**
|
|
400
287
|
* Checks if this localTime is younger (>) than "now" by X units.
|
|
@@ -406,13 +293,13 @@ export class LocalTime {
|
|
|
406
293
|
* Third argument allows to override "now".
|
|
407
294
|
*/
|
|
408
295
|
isYoungerThan(n, unit, now) {
|
|
409
|
-
return this.isAfter(
|
|
296
|
+
return this.isAfter(localTime.of(now !== null && now !== void 0 ? now : new Date()).plus(-n, unit));
|
|
410
297
|
}
|
|
411
298
|
/**
|
|
412
299
|
* Checks if this localTime is same or younger (>=) than "now" by X units.
|
|
413
300
|
*/
|
|
414
301
|
isSameOrYoungerThan(n, unit, now) {
|
|
415
|
-
return this.isSameOrAfter(
|
|
302
|
+
return this.isSameOrAfter(localTime.of(now !== null && now !== void 0 ? now : new Date()).plus(-n, unit));
|
|
416
303
|
}
|
|
417
304
|
/**
|
|
418
305
|
* Returns 1 if this > d
|
|
@@ -421,20 +308,13 @@ export class LocalTime {
|
|
|
421
308
|
*/
|
|
422
309
|
cmp(d) {
|
|
423
310
|
const t1 = this.$date.valueOf();
|
|
424
|
-
const t2 =
|
|
311
|
+
const t2 = localTime.parseToDate(d).valueOf();
|
|
425
312
|
if (t1 === t2)
|
|
426
313
|
return 0;
|
|
427
314
|
return t1 < t2 ? -1 : 1;
|
|
428
315
|
}
|
|
429
316
|
components() {
|
|
430
|
-
return {
|
|
431
|
-
year: this.$date.getFullYear(),
|
|
432
|
-
month: this.$date.getMonth() + 1,
|
|
433
|
-
day: this.$date.getDate(),
|
|
434
|
-
hour: this.$date.getHours(),
|
|
435
|
-
minute: this.$date.getMinutes(),
|
|
436
|
-
second: this.$date.getSeconds(),
|
|
437
|
-
};
|
|
317
|
+
return Object.assign(Object.assign({}, this.dateComponents()), this.timeComponents());
|
|
438
318
|
}
|
|
439
319
|
dateComponents() {
|
|
440
320
|
return {
|
|
@@ -451,7 +331,7 @@ export class LocalTime {
|
|
|
451
331
|
};
|
|
452
332
|
}
|
|
453
333
|
fromNow(now = new Date()) {
|
|
454
|
-
const msDiff =
|
|
334
|
+
const msDiff = localTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
455
335
|
if (msDiff === 0)
|
|
456
336
|
return 'now';
|
|
457
337
|
if (msDiff >= 0) {
|
|
@@ -475,7 +355,7 @@ export class LocalTime {
|
|
|
475
355
|
return Math.floor(this.$date.valueOf() / 1000);
|
|
476
356
|
}
|
|
477
357
|
toLocalDate() {
|
|
478
|
-
return
|
|
358
|
+
return localDate.fromDate(this.$date);
|
|
479
359
|
}
|
|
480
360
|
/**
|
|
481
361
|
* Returns e.g: `1984-06-21 17:56:21`
|
|
@@ -555,60 +435,131 @@ export class LocalTime {
|
|
|
555
435
|
return fmt(this);
|
|
556
436
|
}
|
|
557
437
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
438
|
+
class LocalTimeFactory {
|
|
439
|
+
/**
|
|
440
|
+
* Parses input String into LocalDate.
|
|
441
|
+
* Input can already be a LocalDate - it is returned as-is in that case.
|
|
442
|
+
*/
|
|
443
|
+
of(d) {
|
|
444
|
+
const t = this.parseOrNull(d);
|
|
445
|
+
_assert(t !== null, `Cannot parse "${d}" into LocalTime`, {
|
|
446
|
+
input: d,
|
|
447
|
+
});
|
|
448
|
+
return t;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
452
|
+
*/
|
|
453
|
+
ofMillis(millis) {
|
|
454
|
+
return this.of(new Date(millis));
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Returns null if invalid
|
|
458
|
+
*/
|
|
459
|
+
parseOrNull(d) {
|
|
460
|
+
if (!d)
|
|
461
|
+
return null;
|
|
462
|
+
if (d instanceof LocalTime)
|
|
463
|
+
return d;
|
|
464
|
+
let date;
|
|
465
|
+
if (d instanceof Date) {
|
|
466
|
+
date = d;
|
|
467
|
+
}
|
|
468
|
+
else if (typeof d === 'number') {
|
|
469
|
+
date = new Date(d * 1000);
|
|
470
|
+
}
|
|
471
|
+
else if (typeof d !== 'string') {
|
|
472
|
+
// unexpected type, e.g Function or something
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
// Slicing removes the "timezone component", and makes the date "local"
|
|
477
|
+
// e.g 2022-04-06T23:15:00+09:00
|
|
478
|
+
// becomes 2022-04-06T23:15:00
|
|
479
|
+
date = new Date(d.slice(0, 19));
|
|
480
|
+
// We used to slice to remove the timezone information, now we don't
|
|
481
|
+
// date = new Date(d)
|
|
482
|
+
}
|
|
483
|
+
// validation
|
|
484
|
+
if (isNaN(date.getDate())) {
|
|
485
|
+
// throw new TypeError(`Cannot parse "${d}" into LocalTime`)
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
return new LocalTime(date);
|
|
489
|
+
}
|
|
490
|
+
parseToDate(d) {
|
|
491
|
+
if (d instanceof LocalTime)
|
|
492
|
+
return d.$date;
|
|
493
|
+
if (d instanceof Date)
|
|
494
|
+
return d;
|
|
495
|
+
const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
|
|
496
|
+
_assert(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
|
|
497
|
+
input: d,
|
|
498
|
+
});
|
|
499
|
+
return date;
|
|
500
|
+
}
|
|
501
|
+
parseToUnixTimestamp(d) {
|
|
502
|
+
if (typeof d === 'number')
|
|
503
|
+
return d;
|
|
504
|
+
if (d instanceof LocalTime)
|
|
505
|
+
return d.unix();
|
|
506
|
+
const date = d instanceof Date ? d : new Date(d);
|
|
507
|
+
_assert(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
|
|
508
|
+
input: d,
|
|
509
|
+
});
|
|
510
|
+
return date.valueOf() / 1000;
|
|
511
|
+
}
|
|
512
|
+
isValid(d) {
|
|
513
|
+
return this.parseOrNull(d) !== null;
|
|
514
|
+
}
|
|
515
|
+
now() {
|
|
516
|
+
return new LocalTime(new Date());
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Creates a LocalTime from the input, unless it's falsy - then returns undefined.
|
|
520
|
+
*
|
|
521
|
+
* `localTime` function will instead return LocalTime of `now` for falsy input.
|
|
522
|
+
*/
|
|
523
|
+
orUndefined(d) {
|
|
524
|
+
return d ? this.of(d) : undefined;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
|
|
528
|
+
*/
|
|
529
|
+
orNow(d) {
|
|
530
|
+
return d ? this.of(d) : this.now();
|
|
531
|
+
}
|
|
532
|
+
fromComponents(c) {
|
|
533
|
+
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
534
|
+
}
|
|
535
|
+
sort(items, dir = 'asc', mutate = false) {
|
|
536
|
+
const mod = dir === 'desc' ? -1 : 1;
|
|
537
|
+
return (mutate ? items : [...items]).sort((a, b) => {
|
|
538
|
+
const v1 = a.$date.valueOf();
|
|
539
|
+
const v2 = b.$date.valueOf();
|
|
540
|
+
if (v1 === v2)
|
|
541
|
+
return 0;
|
|
542
|
+
return (v1 < v2 ? -1 : 1) * mod;
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
minOrUndefined(items) {
|
|
546
|
+
return items.length ? this.min(items) : undefined;
|
|
547
|
+
}
|
|
548
|
+
min(items) {
|
|
549
|
+
_assert(items.length, 'localTime.min called on empty array');
|
|
550
|
+
return items
|
|
551
|
+
.map(i => this.of(i))
|
|
552
|
+
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
|
|
553
|
+
}
|
|
554
|
+
maxOrUndefined(items) {
|
|
555
|
+
return items.length ? this.max(items) : undefined;
|
|
556
|
+
}
|
|
557
|
+
max(items) {
|
|
558
|
+
_assert(items.length, 'localTime.max called on empty array');
|
|
559
|
+
return items
|
|
560
|
+
.map(i => this.of(i))
|
|
561
|
+
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
|
|
562
|
+
}
|
|
612
563
|
}
|
|
613
564
|
// based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
|
|
614
565
|
function getWeek(date) {
|
|
@@ -683,7 +634,7 @@ function addMonths(d, num, mutate = false) {
|
|
|
683
634
|
year--;
|
|
684
635
|
month += 12;
|
|
685
636
|
}
|
|
686
|
-
const monthLen =
|
|
637
|
+
const monthLen = localDate.getMonthLength(year, month);
|
|
687
638
|
if (day > monthLen)
|
|
688
639
|
day = monthLen;
|
|
689
640
|
d.setFullYear(year, month - 1, day);
|
|
@@ -698,3 +649,37 @@ function differenceInMonths(a, b) {
|
|
|
698
649
|
const anchor2 = addMonths(a, wholeMonthDiff + sign).getTime();
|
|
699
650
|
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
|
|
700
651
|
}
|
|
652
|
+
const localTimeFactory = new LocalTimeFactory();
|
|
653
|
+
export const localTime = localTimeFactory.of.bind(localTimeFactory);
|
|
654
|
+
// The line below is the blackest of black magic I have ever written in 2024.
|
|
655
|
+
// And probably 2023 as well.
|
|
656
|
+
Object.setPrototypeOf(localTime, localTimeFactory);
|
|
657
|
+
/**
|
|
658
|
+
Convenience function to return current Unix timestamp in seconds.
|
|
659
|
+
Like Date.now(), but in seconds.
|
|
660
|
+
*/
|
|
661
|
+
export function nowUnix() {
|
|
662
|
+
return Math.floor(Date.now() / 1000);
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* UTC offset is the opposite of "timezone offset" - it's the number of minutes to add
|
|
666
|
+
* to the local time to get UTC time.
|
|
667
|
+
*
|
|
668
|
+
* E.g utcOffset for CEST is -120,
|
|
669
|
+
* which means that you need to add -120 minutes to the local time to get UTC time.
|
|
670
|
+
*
|
|
671
|
+
* Instead of -0 it returns 0, for the peace of mind and less weird test/snapshot differences.
|
|
672
|
+
*/
|
|
673
|
+
export function getUTCOffsetMinutes() {
|
|
674
|
+
return -new Date().getTimezoneOffset() || 0;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Same as getUTCOffsetMinutes, but rounded to hours.
|
|
678
|
+
*
|
|
679
|
+
* E.g for CEST it is -2.
|
|
680
|
+
*
|
|
681
|
+
* Instead of -0 it returns 0, for the peace of mind and less weird test/snapshot differences.
|
|
682
|
+
*/
|
|
683
|
+
export function getUTCOffsetHours() {
|
|
684
|
+
return Math.round(getUTCOffsetMinutes() / 60);
|
|
685
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { localTime } from './localTime';
|
|
2
2
|
/**
|
|
3
3
|
* Class that supports an "interval of time" between 2 timestamps - start and end.
|
|
4
4
|
* Example: `1649267185/1649267187`.
|
|
@@ -11,7 +11,7 @@ export class TimeInterval {
|
|
|
11
11
|
this.$end = $end;
|
|
12
12
|
}
|
|
13
13
|
static of(start, end) {
|
|
14
|
-
return new TimeInterval(
|
|
14
|
+
return new TimeInterval(localTime.parseToUnixTimestamp(start), localTime.parseToUnixTimestamp(end));
|
|
15
15
|
}
|
|
16
16
|
get start() {
|
|
17
17
|
return this.$start;
|
|
@@ -20,10 +20,10 @@ export class TimeInterval {
|
|
|
20
20
|
return this.$end;
|
|
21
21
|
}
|
|
22
22
|
get startTime() {
|
|
23
|
-
return
|
|
23
|
+
return localTime(this.$start);
|
|
24
24
|
}
|
|
25
25
|
get endTime() {
|
|
26
|
-
return
|
|
26
|
+
return localTime(this.$end);
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Parses string like `1649267185/1649267187` into a TimeInterval.
|
|
@@ -55,7 +55,7 @@ export class TimeInterval {
|
|
|
55
55
|
return this.cmp(d) >= 0;
|
|
56
56
|
}
|
|
57
57
|
includes(d, incl = '[)') {
|
|
58
|
-
d =
|
|
58
|
+
d = localTime.parseToUnixTimestamp(d);
|
|
59
59
|
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
60
60
|
if (d < this.$start || (d === this.$start && incl[0] === '('))
|
|
61
61
|
return false;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { localTime } from '../datetime/localTime';
|
|
2
2
|
export function generateBuildInfoDev() {
|
|
3
|
-
const now =
|
|
3
|
+
const now = localTime.now();
|
|
4
4
|
const ts = now.unix();
|
|
5
5
|
const rev = 'devRev';
|
|
6
6
|
const branchName = 'devBranch';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.233.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"zod": "^3.20.2"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@naturalcycles/bench-lib": "^
|
|
18
|
+
"@naturalcycles/bench-lib": "^3.0.0",
|
|
19
19
|
"@naturalcycles/dev-lib": "^13.0.1",
|
|
20
20
|
"@naturalcycles/nodejs-lib": "^13.0.1",
|
|
21
21
|
"@naturalcycles/time-lib": "^3.5.1",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Inclusiveness } from '../types'
|
|
2
|
-
import
|
|
3
|
-
import { LocalDate, localDateRange } from './localDate'
|
|
2
|
+
import { localDate, LocalDateInput, LocalDateUnit, LocalDate } from './localDate'
|
|
4
3
|
|
|
5
4
|
export type DateIntervalConfig = DateInterval | DateIntervalString
|
|
6
5
|
export type DateIntervalString = string
|
|
@@ -17,7 +16,7 @@ export class DateInterval {
|
|
|
17
16
|
) {}
|
|
18
17
|
|
|
19
18
|
static of(start: LocalDateInput, end: LocalDateInput): DateInterval {
|
|
20
|
-
return new DateInterval(
|
|
19
|
+
return new DateInterval(localDate(start), localDate(end))
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
/**
|
|
@@ -32,7 +31,7 @@ export class DateInterval {
|
|
|
32
31
|
throw new Error(`Cannot parse "${d}" into DateInterval`)
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
return new DateInterval(
|
|
34
|
+
return new DateInterval(localDate(start), localDate(end))
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
isSame(d: DateIntervalConfig): boolean {
|
|
@@ -61,7 +60,7 @@ export class DateInterval {
|
|
|
61
60
|
* Ranges of DateInterval (start, end) are INCLUSIVE.
|
|
62
61
|
*/
|
|
63
62
|
includes(d: LocalDateInput, incl: Inclusiveness = '[]'): boolean {
|
|
64
|
-
d =
|
|
63
|
+
d = localDate(d)
|
|
65
64
|
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
66
65
|
return d.isAfter(this.start, incl[0] === '[') && d.isBefore(this.end, incl[1] === ']')
|
|
67
66
|
}
|
|
@@ -82,14 +81,14 @@ export class DateInterval {
|
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
getDays(incl: Inclusiveness = '[]'): LocalDate[] {
|
|
85
|
-
return
|
|
84
|
+
return localDate.range(this.start, this.end, incl, 1, 'day')
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
/**
|
|
89
88
|
* Returns an array of LocalDates that are included in the interval.
|
|
90
89
|
*/
|
|
91
90
|
range(incl: Inclusiveness = '[]', step = 1, stepUnit: LocalDateUnit = 'day'): LocalDate[] {
|
|
92
|
-
return
|
|
91
|
+
return localDate.range(this.start, this.end, incl, step, stepUnit)
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
toString(): DateIntervalString {
|