@naturalcycles/js-lib 14.230.1 → 14.232.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/localDate.d.ts +9 -0
- package/dist/datetime/localDate.js +16 -6
- package/dist/datetime/localTime.d.ts +22 -1
- package/dist/datetime/localTime.js +64 -9
- package/dist-esm/datetime/localDate.js +16 -6
- package/dist-esm/datetime/localTime.js +64 -9
- package/package.json +3 -1
- package/src/datetime/localDate.ts +18 -7
- package/src/datetime/localTime.ts +78 -11
|
@@ -113,12 +113,21 @@ export declare class LocalDate {
|
|
|
113
113
|
* Timezone will match local timezone.
|
|
114
114
|
*/
|
|
115
115
|
toDate(): Date;
|
|
116
|
+
/**
|
|
117
|
+
* Converts LocalDate to Date in UTC timezone.
|
|
118
|
+
* Unlike normal `.toDate` that uses browser's timezone by default.
|
|
119
|
+
*/
|
|
120
|
+
toDateInUTC(): Date;
|
|
116
121
|
toLocalTime(): LocalTime;
|
|
117
122
|
toISODate(): IsoDateString;
|
|
118
123
|
/**
|
|
119
124
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
120
125
|
*/
|
|
121
126
|
toISODateTime(): IsoDateTimeString;
|
|
127
|
+
/**
|
|
128
|
+
* Returns e.g: `1984-06-21T17:56:21Z` (notice the Z at the end, which indicates UTC)
|
|
129
|
+
*/
|
|
130
|
+
toISODateTimeUTC(): IsoDateTimeString;
|
|
122
131
|
toString(): IsoDateString;
|
|
123
132
|
toStringCompact(): string;
|
|
124
133
|
toMonthId(): MonthId;
|
|
@@ -51,7 +51,6 @@ class LocalDate {
|
|
|
51
51
|
if (d instanceof Date) {
|
|
52
52
|
return this.fromDate(d);
|
|
53
53
|
}
|
|
54
|
-
// const [year, month, day] = d.slice(0, 10).split('-').map(Number)
|
|
55
54
|
const matches = typeof d === 'string' && DATE_REGEX.exec(d.slice(0, 10));
|
|
56
55
|
if (!matches)
|
|
57
56
|
return null;
|
|
@@ -69,10 +68,6 @@ class LocalDate {
|
|
|
69
68
|
}
|
|
70
69
|
return new LocalDate(year, month, day);
|
|
71
70
|
}
|
|
72
|
-
// Can use just .toString()
|
|
73
|
-
// static parseToString(d: LocalDateConfig): IsoDateString {
|
|
74
|
-
// return typeof d === 'string' ? d : d.toString()
|
|
75
|
-
// }
|
|
76
71
|
static isValid(iso) {
|
|
77
72
|
return this.parseOrNull(iso) !== null;
|
|
78
73
|
}
|
|
@@ -391,6 +386,13 @@ class LocalDate {
|
|
|
391
386
|
toDate() {
|
|
392
387
|
return new Date(this.$year, this.$month - 1, this.$day);
|
|
393
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Converts LocalDate to Date in UTC timezone.
|
|
391
|
+
* Unlike normal `.toDate` that uses browser's timezone by default.
|
|
392
|
+
*/
|
|
393
|
+
toDateInUTC() {
|
|
394
|
+
return new Date(this.toISODateTimeUTC());
|
|
395
|
+
}
|
|
394
396
|
toLocalTime() {
|
|
395
397
|
return localTime_1.LocalTime.of(this.toDate());
|
|
396
398
|
}
|
|
@@ -403,6 +405,12 @@ class LocalDate {
|
|
|
403
405
|
toISODateTime() {
|
|
404
406
|
return this.toString() + 'T00:00:00';
|
|
405
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Returns e.g: `1984-06-21T17:56:21Z` (notice the Z at the end, which indicates UTC)
|
|
410
|
+
*/
|
|
411
|
+
toISODateTimeUTC() {
|
|
412
|
+
return this.toISODateTime() + 'Z';
|
|
413
|
+
}
|
|
406
414
|
toString() {
|
|
407
415
|
return [
|
|
408
416
|
String(this.$year).padStart(4, '0'),
|
|
@@ -508,6 +516,8 @@ exports.localDateOrToday = localDateOrToday;
|
|
|
508
516
|
*/
|
|
509
517
|
function todayString() {
|
|
510
518
|
// It was benchmarked to be faster than by concatenating individual Date components
|
|
511
|
-
return new Date().toISOString().slice(0, 10)
|
|
519
|
+
// return new Date().toISOString().slice(0, 10)
|
|
520
|
+
// But, toISOString always returns the date in UTC, so in the Browser it would give unexpected result!
|
|
521
|
+
return LocalDate.fromDate(new Date()).toString();
|
|
512
522
|
}
|
|
513
523
|
exports.todayString = todayString;
|
|
@@ -12,10 +12,13 @@ export declare enum ISODayOfWeek {
|
|
|
12
12
|
}
|
|
13
13
|
export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber;
|
|
14
14
|
export type LocalTimeFormatter = (ld: LocalTime) => string;
|
|
15
|
-
export
|
|
15
|
+
export type LocalTimeComponents = DateComponents & TimeComponents;
|
|
16
|
+
interface DateComponents {
|
|
16
17
|
year: number;
|
|
17
18
|
month: number;
|
|
18
19
|
day: number;
|
|
20
|
+
}
|
|
21
|
+
interface TimeComponents {
|
|
19
22
|
hour: number;
|
|
20
23
|
minute: number;
|
|
21
24
|
second: number;
|
|
@@ -47,6 +50,16 @@ export declare class LocalTime {
|
|
|
47
50
|
year: number;
|
|
48
51
|
month: number;
|
|
49
52
|
} & Partial<LocalTimeComponents>): LocalTime;
|
|
53
|
+
/**
|
|
54
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
55
|
+
* Opposite of `.local()` method.
|
|
56
|
+
*/
|
|
57
|
+
utc(): LocalTime;
|
|
58
|
+
/**
|
|
59
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
60
|
+
* Opposite of `.utc()` method.
|
|
61
|
+
*/
|
|
62
|
+
local(): LocalTime;
|
|
50
63
|
get(unit: LocalTimeUnit): number;
|
|
51
64
|
set(unit: LocalTimeUnit, v: number, mutate?: boolean): LocalTime;
|
|
52
65
|
year(): number;
|
|
@@ -126,6 +139,8 @@ export declare class LocalTime {
|
|
|
126
139
|
*/
|
|
127
140
|
cmp(d: LocalTimeInput): -1 | 0 | 1;
|
|
128
141
|
components(): LocalTimeComponents;
|
|
142
|
+
private dateComponents;
|
|
143
|
+
private timeComponents;
|
|
129
144
|
fromNow(now?: LocalTimeInput): string;
|
|
130
145
|
getDate(): Date;
|
|
131
146
|
clone(): LocalTime;
|
|
@@ -133,6 +148,11 @@ export declare class LocalTime {
|
|
|
133
148
|
unixMillis(): UnixTimestampMillisNumber;
|
|
134
149
|
valueOf(): UnixTimestampNumber;
|
|
135
150
|
toLocalDate(): LocalDate;
|
|
151
|
+
/**
|
|
152
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
153
|
+
* or (if seconds=false):
|
|
154
|
+
* `1984-06-21 17:56`
|
|
155
|
+
*/
|
|
136
156
|
toPretty(seconds?: boolean): IsoDateTimeString;
|
|
137
157
|
/**
|
|
138
158
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
@@ -196,3 +216,4 @@ export declare function getUTCOffsetMinutes(): NumberOfMinutes;
|
|
|
196
216
|
* Instead of -0 it returns 0, for the peace of mind and less weird test/snapshot differences.
|
|
197
217
|
*/
|
|
198
218
|
export declare function getUTCOffsetHours(): NumberOfHours;
|
|
219
|
+
export {};
|
|
@@ -64,16 +64,18 @@ class LocalTime {
|
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
67
|
+
// Slicing removes the "timezone component", and makes the date "local"
|
|
68
|
+
// e.g 2022-04-06T23:15:00+09:00
|
|
69
|
+
// becomes 2022-04-06T23:15:00
|
|
67
70
|
date = new Date(d.slice(0, 19));
|
|
71
|
+
// We used to slice to remove the timezone information, now we don't
|
|
72
|
+
// date = new Date(d)
|
|
68
73
|
}
|
|
69
74
|
// validation
|
|
70
75
|
if (isNaN(date.getDate())) {
|
|
71
76
|
// throw new TypeError(`Cannot parse "${d}" into LocalTime`)
|
|
72
77
|
return null;
|
|
73
78
|
}
|
|
74
|
-
// if (utc) {
|
|
75
|
-
// date.setMinutes(date.getMinutes() + date.getTimezoneOffset())
|
|
76
|
-
// }
|
|
77
79
|
return new LocalTime(date);
|
|
78
80
|
}
|
|
79
81
|
static parseToDate(d) {
|
|
@@ -107,6 +109,20 @@ class LocalTime {
|
|
|
107
109
|
static fromComponents(c) {
|
|
108
110
|
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
109
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
114
|
+
* Opposite of `.local()` method.
|
|
115
|
+
*/
|
|
116
|
+
utc() {
|
|
117
|
+
return new LocalTime(new Date(this.$date.toISOString()));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
121
|
+
* Opposite of `.utc()` method.
|
|
122
|
+
*/
|
|
123
|
+
local() {
|
|
124
|
+
return new LocalTime(new Date(this.$date.getTime()));
|
|
125
|
+
}
|
|
110
126
|
get(unit) {
|
|
111
127
|
if (unit === 'year') {
|
|
112
128
|
return this.$date.getFullYear();
|
|
@@ -422,6 +438,20 @@ class LocalTime {
|
|
|
422
438
|
second: this.$date.getSeconds(),
|
|
423
439
|
};
|
|
424
440
|
}
|
|
441
|
+
dateComponents() {
|
|
442
|
+
return {
|
|
443
|
+
year: this.$date.getFullYear(),
|
|
444
|
+
month: this.$date.getMonth() + 1,
|
|
445
|
+
day: this.$date.getDate(),
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
timeComponents() {
|
|
449
|
+
return {
|
|
450
|
+
hour: this.$date.getHours(),
|
|
451
|
+
minute: this.$date.getMinutes(),
|
|
452
|
+
second: this.$date.getSeconds(),
|
|
453
|
+
};
|
|
454
|
+
}
|
|
425
455
|
fromNow(now = new Date()) {
|
|
426
456
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
427
457
|
if (msDiff === 0)
|
|
@@ -449,27 +479,52 @@ class LocalTime {
|
|
|
449
479
|
toLocalDate() {
|
|
450
480
|
return localDate_1.LocalDate.fromDate(this.$date);
|
|
451
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
484
|
+
* or (if seconds=false):
|
|
485
|
+
* `1984-06-21 17:56`
|
|
486
|
+
*/
|
|
452
487
|
toPretty(seconds = true) {
|
|
453
|
-
|
|
454
|
-
|
|
488
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds);
|
|
489
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
490
|
+
// const s = this.$date.toISOString()
|
|
491
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
455
492
|
}
|
|
456
493
|
/**
|
|
457
494
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
458
495
|
*/
|
|
459
496
|
toISODateTime() {
|
|
460
|
-
return this
|
|
497
|
+
return this.toISODate() + 'T' + this.toISOTime();
|
|
498
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
499
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
461
500
|
}
|
|
462
501
|
/**
|
|
463
502
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
464
503
|
*/
|
|
465
504
|
toISODate() {
|
|
466
|
-
|
|
505
|
+
const { year, month, day } = this.dateComponents();
|
|
506
|
+
return [
|
|
507
|
+
String(year).padStart(4, '0'),
|
|
508
|
+
String(month).padStart(2, '0'),
|
|
509
|
+
String(day).padStart(2, '0'),
|
|
510
|
+
].join('-');
|
|
511
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
512
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
467
513
|
}
|
|
468
514
|
/**
|
|
469
515
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
470
516
|
*/
|
|
471
517
|
toISOTime(seconds = true) {
|
|
472
|
-
|
|
518
|
+
const { hour, minute, second } = this.timeComponents();
|
|
519
|
+
return [
|
|
520
|
+
String(hour).padStart(2, '0'),
|
|
521
|
+
String(minute).padStart(2, '0'),
|
|
522
|
+
seconds && String(second).padStart(2, '0'),
|
|
523
|
+
]
|
|
524
|
+
.filter(Boolean)
|
|
525
|
+
.join(':');
|
|
526
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
527
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
473
528
|
}
|
|
474
529
|
/**
|
|
475
530
|
* Returns e.g: `19840621_1705`
|
|
@@ -493,7 +548,7 @@ class LocalTime {
|
|
|
493
548
|
return this.unix();
|
|
494
549
|
}
|
|
495
550
|
toMonthId() {
|
|
496
|
-
return this
|
|
551
|
+
return this.toISODate().slice(0, 7);
|
|
497
552
|
}
|
|
498
553
|
format(fmt) {
|
|
499
554
|
if (fmt instanceof Intl.DateTimeFormat) {
|
|
@@ -48,7 +48,6 @@ export class LocalDate {
|
|
|
48
48
|
if (d instanceof Date) {
|
|
49
49
|
return this.fromDate(d);
|
|
50
50
|
}
|
|
51
|
-
// const [year, month, day] = d.slice(0, 10).split('-').map(Number)
|
|
52
51
|
const matches = typeof d === 'string' && DATE_REGEX.exec(d.slice(0, 10));
|
|
53
52
|
if (!matches)
|
|
54
53
|
return null;
|
|
@@ -66,10 +65,6 @@ export class LocalDate {
|
|
|
66
65
|
}
|
|
67
66
|
return new LocalDate(year, month, day);
|
|
68
67
|
}
|
|
69
|
-
// Can use just .toString()
|
|
70
|
-
// static parseToString(d: LocalDateConfig): IsoDateString {
|
|
71
|
-
// return typeof d === 'string' ? d : d.toString()
|
|
72
|
-
// }
|
|
73
68
|
static isValid(iso) {
|
|
74
69
|
return this.parseOrNull(iso) !== null;
|
|
75
70
|
}
|
|
@@ -388,6 +383,13 @@ export class LocalDate {
|
|
|
388
383
|
toDate() {
|
|
389
384
|
return new Date(this.$year, this.$month - 1, this.$day);
|
|
390
385
|
}
|
|
386
|
+
/**
|
|
387
|
+
* Converts LocalDate to Date in UTC timezone.
|
|
388
|
+
* Unlike normal `.toDate` that uses browser's timezone by default.
|
|
389
|
+
*/
|
|
390
|
+
toDateInUTC() {
|
|
391
|
+
return new Date(this.toISODateTimeUTC());
|
|
392
|
+
}
|
|
391
393
|
toLocalTime() {
|
|
392
394
|
return LocalTime.of(this.toDate());
|
|
393
395
|
}
|
|
@@ -400,6 +402,12 @@ export class LocalDate {
|
|
|
400
402
|
toISODateTime() {
|
|
401
403
|
return this.toString() + 'T00:00:00';
|
|
402
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Returns e.g: `1984-06-21T17:56:21Z` (notice the Z at the end, which indicates UTC)
|
|
407
|
+
*/
|
|
408
|
+
toISODateTimeUTC() {
|
|
409
|
+
return this.toISODateTime() + 'Z';
|
|
410
|
+
}
|
|
403
411
|
toString() {
|
|
404
412
|
return [
|
|
405
413
|
String(this.$year).padStart(4, '0'),
|
|
@@ -498,5 +506,7 @@ export function localDateOrToday(d) {
|
|
|
498
506
|
*/
|
|
499
507
|
export function todayString() {
|
|
500
508
|
// It was benchmarked to be faster than by concatenating individual Date components
|
|
501
|
-
return new Date().toISOString().slice(0, 10)
|
|
509
|
+
// return new Date().toISOString().slice(0, 10)
|
|
510
|
+
// But, toISOString always returns the date in UTC, so in the Browser it would give unexpected result!
|
|
511
|
+
return LocalDate.fromDate(new Date()).toString();
|
|
502
512
|
}
|
|
@@ -61,16 +61,18 @@ export class LocalTime {
|
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
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
|
|
64
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)
|
|
65
70
|
}
|
|
66
71
|
// validation
|
|
67
72
|
if (isNaN(date.getDate())) {
|
|
68
73
|
// throw new TypeError(`Cannot parse "${d}" into LocalTime`)
|
|
69
74
|
return null;
|
|
70
75
|
}
|
|
71
|
-
// if (utc) {
|
|
72
|
-
// date.setMinutes(date.getMinutes() + date.getTimezoneOffset())
|
|
73
|
-
// }
|
|
74
76
|
return new LocalTime(date);
|
|
75
77
|
}
|
|
76
78
|
static parseToDate(d) {
|
|
@@ -104,6 +106,20 @@ export class LocalTime {
|
|
|
104
106
|
static fromComponents(c) {
|
|
105
107
|
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
106
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
111
|
+
* Opposite of `.local()` method.
|
|
112
|
+
*/
|
|
113
|
+
utc() {
|
|
114
|
+
return new LocalTime(new Date(this.$date.toISOString()));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
118
|
+
* Opposite of `.utc()` method.
|
|
119
|
+
*/
|
|
120
|
+
local() {
|
|
121
|
+
return new LocalTime(new Date(this.$date.getTime()));
|
|
122
|
+
}
|
|
107
123
|
get(unit) {
|
|
108
124
|
if (unit === 'year') {
|
|
109
125
|
return this.$date.getFullYear();
|
|
@@ -420,6 +436,20 @@ export class LocalTime {
|
|
|
420
436
|
second: this.$date.getSeconds(),
|
|
421
437
|
};
|
|
422
438
|
}
|
|
439
|
+
dateComponents() {
|
|
440
|
+
return {
|
|
441
|
+
year: this.$date.getFullYear(),
|
|
442
|
+
month: this.$date.getMonth() + 1,
|
|
443
|
+
day: this.$date.getDate(),
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
timeComponents() {
|
|
447
|
+
return {
|
|
448
|
+
hour: this.$date.getHours(),
|
|
449
|
+
minute: this.$date.getMinutes(),
|
|
450
|
+
second: this.$date.getSeconds(),
|
|
451
|
+
};
|
|
452
|
+
}
|
|
423
453
|
fromNow(now = new Date()) {
|
|
424
454
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
425
455
|
if (msDiff === 0)
|
|
@@ -447,27 +477,52 @@ export class LocalTime {
|
|
|
447
477
|
toLocalDate() {
|
|
448
478
|
return LocalDate.fromDate(this.$date);
|
|
449
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
482
|
+
* or (if seconds=false):
|
|
483
|
+
* `1984-06-21 17:56`
|
|
484
|
+
*/
|
|
450
485
|
toPretty(seconds = true) {
|
|
451
|
-
|
|
452
|
-
|
|
486
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds);
|
|
487
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
488
|
+
// const s = this.$date.toISOString()
|
|
489
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
453
490
|
}
|
|
454
491
|
/**
|
|
455
492
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
456
493
|
*/
|
|
457
494
|
toISODateTime() {
|
|
458
|
-
return this
|
|
495
|
+
return this.toISODate() + 'T' + this.toISOTime();
|
|
496
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
497
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
459
498
|
}
|
|
460
499
|
/**
|
|
461
500
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
462
501
|
*/
|
|
463
502
|
toISODate() {
|
|
464
|
-
|
|
503
|
+
const { year, month, day } = this.dateComponents();
|
|
504
|
+
return [
|
|
505
|
+
String(year).padStart(4, '0'),
|
|
506
|
+
String(month).padStart(2, '0'),
|
|
507
|
+
String(day).padStart(2, '0'),
|
|
508
|
+
].join('-');
|
|
509
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
510
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
465
511
|
}
|
|
466
512
|
/**
|
|
467
513
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
468
514
|
*/
|
|
469
515
|
toISOTime(seconds = true) {
|
|
470
|
-
|
|
516
|
+
const { hour, minute, second } = this.timeComponents();
|
|
517
|
+
return [
|
|
518
|
+
String(hour).padStart(2, '0'),
|
|
519
|
+
String(minute).padStart(2, '0'),
|
|
520
|
+
seconds && String(second).padStart(2, '0'),
|
|
521
|
+
]
|
|
522
|
+
.filter(Boolean)
|
|
523
|
+
.join(':');
|
|
524
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
525
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
471
526
|
}
|
|
472
527
|
/**
|
|
473
528
|
* Returns e.g: `19840621_1705`
|
|
@@ -491,7 +546,7 @@ export class LocalTime {
|
|
|
491
546
|
return this.unix();
|
|
492
547
|
}
|
|
493
548
|
toMonthId() {
|
|
494
|
-
return this
|
|
549
|
+
return this.toISODate().slice(0, 7);
|
|
495
550
|
}
|
|
496
551
|
format(fmt) {
|
|
497
552
|
if (fmt instanceof Intl.DateTimeFormat) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.232.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
7
|
+
"test-tz1": "TZ=Europe/Stockholm yarn test local",
|
|
8
|
+
"test-tz2": "TZ=JST-9 yarn test local",
|
|
7
9
|
"docs-dev": "vitepress dev docs --open",
|
|
8
10
|
"docs-build": "vitepress build docs",
|
|
9
11
|
"docs-preview": "vitepress preview docs"
|
|
@@ -74,7 +74,6 @@ export class LocalDate {
|
|
|
74
74
|
return this.fromDate(d)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// const [year, month, day] = d.slice(0, 10).split('-').map(Number)
|
|
78
77
|
const matches = typeof (d as any) === 'string' && DATE_REGEX.exec(d.slice(0, 10))
|
|
79
78
|
if (!matches) return null
|
|
80
79
|
|
|
@@ -97,11 +96,6 @@ export class LocalDate {
|
|
|
97
96
|
return new LocalDate(year, month, day)
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
// Can use just .toString()
|
|
101
|
-
// static parseToString(d: LocalDateConfig): IsoDateString {
|
|
102
|
-
// return typeof d === 'string' ? d : d.toString()
|
|
103
|
-
// }
|
|
104
|
-
|
|
105
99
|
static isValid(iso: string | undefined | null): boolean {
|
|
106
100
|
return this.parseOrNull(iso) !== null
|
|
107
101
|
}
|
|
@@ -473,6 +467,14 @@ export class LocalDate {
|
|
|
473
467
|
return new Date(this.$year, this.$month - 1, this.$day)
|
|
474
468
|
}
|
|
475
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Converts LocalDate to Date in UTC timezone.
|
|
472
|
+
* Unlike normal `.toDate` that uses browser's timezone by default.
|
|
473
|
+
*/
|
|
474
|
+
toDateInUTC(): Date {
|
|
475
|
+
return new Date(this.toISODateTimeUTC())
|
|
476
|
+
}
|
|
477
|
+
|
|
476
478
|
toLocalTime(): LocalTime {
|
|
477
479
|
return LocalTime.of(this.toDate())
|
|
478
480
|
}
|
|
@@ -488,6 +490,13 @@ export class LocalDate {
|
|
|
488
490
|
return this.toString() + 'T00:00:00'
|
|
489
491
|
}
|
|
490
492
|
|
|
493
|
+
/**
|
|
494
|
+
* Returns e.g: `1984-06-21T17:56:21Z` (notice the Z at the end, which indicates UTC)
|
|
495
|
+
*/
|
|
496
|
+
toISODateTimeUTC(): IsoDateTimeString {
|
|
497
|
+
return this.toISODateTime() + 'Z'
|
|
498
|
+
}
|
|
499
|
+
|
|
491
500
|
toString(): IsoDateString {
|
|
492
501
|
return [
|
|
493
502
|
String(this.$year).padStart(4, '0'),
|
|
@@ -616,5 +625,7 @@ export function localDateOrToday(d?: LocalDateInput | null): LocalDate {
|
|
|
616
625
|
*/
|
|
617
626
|
export function todayString(): IsoDateString {
|
|
618
627
|
// It was benchmarked to be faster than by concatenating individual Date components
|
|
619
|
-
return new Date().toISOString().slice(0, 10)
|
|
628
|
+
// return new Date().toISOString().slice(0, 10)
|
|
629
|
+
// But, toISOString always returns the date in UTC, so in the Browser it would give unexpected result!
|
|
630
|
+
return LocalDate.fromDate(new Date()).toString()
|
|
620
631
|
}
|
|
@@ -28,10 +28,15 @@ export enum ISODayOfWeek {
|
|
|
28
28
|
export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber
|
|
29
29
|
export type LocalTimeFormatter = (ld: LocalTime) => string
|
|
30
30
|
|
|
31
|
-
export
|
|
31
|
+
export type LocalTimeComponents = DateComponents & TimeComponents
|
|
32
|
+
|
|
33
|
+
interface DateComponents {
|
|
32
34
|
year: number
|
|
33
35
|
month: number
|
|
34
36
|
day: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface TimeComponents {
|
|
35
40
|
hour: number
|
|
36
41
|
minute: number
|
|
37
42
|
second: number
|
|
@@ -88,7 +93,12 @@ export class LocalTime {
|
|
|
88
93
|
// unexpected type, e.g Function or something
|
|
89
94
|
return null
|
|
90
95
|
} else {
|
|
96
|
+
// Slicing removes the "timezone component", and makes the date "local"
|
|
97
|
+
// e.g 2022-04-06T23:15:00+09:00
|
|
98
|
+
// becomes 2022-04-06T23:15:00
|
|
91
99
|
date = new Date(d.slice(0, 19))
|
|
100
|
+
// We used to slice to remove the timezone information, now we don't
|
|
101
|
+
// date = new Date(d)
|
|
92
102
|
}
|
|
93
103
|
|
|
94
104
|
// validation
|
|
@@ -97,10 +107,6 @@ export class LocalTime {
|
|
|
97
107
|
return null
|
|
98
108
|
}
|
|
99
109
|
|
|
100
|
-
// if (utc) {
|
|
101
|
-
// date.setMinutes(date.getMinutes() + date.getTimezoneOffset())
|
|
102
|
-
// }
|
|
103
|
-
|
|
104
110
|
return new LocalTime(date)
|
|
105
111
|
}
|
|
106
112
|
|
|
@@ -146,6 +152,22 @@ export class LocalTime {
|
|
|
146
152
|
)
|
|
147
153
|
}
|
|
148
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
157
|
+
* Opposite of `.local()` method.
|
|
158
|
+
*/
|
|
159
|
+
utc(): LocalTime {
|
|
160
|
+
return new LocalTime(new Date(this.$date.toISOString()))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Returns LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
165
|
+
* Opposite of `.utc()` method.
|
|
166
|
+
*/
|
|
167
|
+
local(): LocalTime {
|
|
168
|
+
return new LocalTime(new Date(this.$date.getTime()))
|
|
169
|
+
}
|
|
170
|
+
|
|
149
171
|
get(unit: LocalTimeUnit): number {
|
|
150
172
|
if (unit === 'year') {
|
|
151
173
|
return this.$date.getFullYear()
|
|
@@ -514,6 +536,22 @@ export class LocalTime {
|
|
|
514
536
|
}
|
|
515
537
|
}
|
|
516
538
|
|
|
539
|
+
private dateComponents(): DateComponents {
|
|
540
|
+
return {
|
|
541
|
+
year: this.$date.getFullYear(),
|
|
542
|
+
month: this.$date.getMonth() + 1,
|
|
543
|
+
day: this.$date.getDate(),
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
private timeComponents(): TimeComponents {
|
|
548
|
+
return {
|
|
549
|
+
hour: this.$date.getHours(),
|
|
550
|
+
minute: this.$date.getMinutes(),
|
|
551
|
+
second: this.$date.getSeconds(),
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
517
555
|
fromNow(now: LocalTimeInput = new Date()): string {
|
|
518
556
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf()
|
|
519
557
|
|
|
@@ -550,30 +588,59 @@ export class LocalTime {
|
|
|
550
588
|
return LocalDate.fromDate(this.$date)
|
|
551
589
|
}
|
|
552
590
|
|
|
591
|
+
/**
|
|
592
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
593
|
+
* or (if seconds=false):
|
|
594
|
+
* `1984-06-21 17:56`
|
|
595
|
+
*/
|
|
553
596
|
toPretty(seconds = true): IsoDateTimeString {
|
|
554
|
-
|
|
555
|
-
|
|
597
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds)
|
|
598
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
599
|
+
// const s = this.$date.toISOString()
|
|
600
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
556
601
|
}
|
|
557
602
|
|
|
558
603
|
/**
|
|
559
604
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
560
605
|
*/
|
|
561
606
|
toISODateTime(): IsoDateTimeString {
|
|
562
|
-
return this
|
|
607
|
+
return this.toISODate() + 'T' + this.toISOTime()
|
|
608
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
609
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
563
610
|
}
|
|
564
611
|
|
|
565
612
|
/**
|
|
566
613
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
567
614
|
*/
|
|
568
615
|
toISODate(): IsoDateString {
|
|
569
|
-
|
|
616
|
+
const { year, month, day } = this.dateComponents()
|
|
617
|
+
|
|
618
|
+
return [
|
|
619
|
+
String(year).padStart(4, '0'),
|
|
620
|
+
String(month).padStart(2, '0'),
|
|
621
|
+
String(day).padStart(2, '0'),
|
|
622
|
+
].join('-')
|
|
623
|
+
|
|
624
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
625
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
570
626
|
}
|
|
571
627
|
|
|
572
628
|
/**
|
|
573
629
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
574
630
|
*/
|
|
575
631
|
toISOTime(seconds = true): string {
|
|
576
|
-
|
|
632
|
+
const { hour, minute, second } = this.timeComponents()
|
|
633
|
+
|
|
634
|
+
return [
|
|
635
|
+
String(hour).padStart(2, '0'),
|
|
636
|
+
String(minute).padStart(2, '0'),
|
|
637
|
+
seconds && String(second).padStart(2, '0'),
|
|
638
|
+
]
|
|
639
|
+
.filter(Boolean)
|
|
640
|
+
.join(':')
|
|
641
|
+
|
|
642
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
643
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
577
644
|
}
|
|
578
645
|
|
|
579
646
|
/**
|
|
@@ -602,7 +669,7 @@ export class LocalTime {
|
|
|
602
669
|
}
|
|
603
670
|
|
|
604
671
|
toMonthId(): MonthId {
|
|
605
|
-
return this
|
|
672
|
+
return this.toISODate().slice(0, 7)
|
|
606
673
|
}
|
|
607
674
|
|
|
608
675
|
format(fmt: Intl.DateTimeFormat | LocalTimeFormatter): string {
|