@naturalcycles/js-lib 14.230.1 → 14.231.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 +13 -1
- package/dist/datetime/localTime.js +53 -6
- package/dist-esm/datetime/localDate.js +16 -6
- package/dist-esm/datetime/localTime.js +53 -6
- package/package.json +3 -1
- package/src/datetime/localDate.ts +18 -7
- package/src/datetime/localTime.ts +66 -7
|
@@ -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,7 @@ export declare class LocalTime {
|
|
|
47
50
|
year: number;
|
|
48
51
|
month: number;
|
|
49
52
|
} & Partial<LocalTimeComponents>): LocalTime;
|
|
53
|
+
static fromDateUTC(d: Date): LocalTime;
|
|
50
54
|
get(unit: LocalTimeUnit): number;
|
|
51
55
|
set(unit: LocalTimeUnit, v: number, mutate?: boolean): LocalTime;
|
|
52
56
|
year(): number;
|
|
@@ -126,6 +130,8 @@ export declare class LocalTime {
|
|
|
126
130
|
*/
|
|
127
131
|
cmp(d: LocalTimeInput): -1 | 0 | 1;
|
|
128
132
|
components(): LocalTimeComponents;
|
|
133
|
+
private dateComponents;
|
|
134
|
+
private timeComponents;
|
|
129
135
|
fromNow(now?: LocalTimeInput): string;
|
|
130
136
|
getDate(): Date;
|
|
131
137
|
clone(): LocalTime;
|
|
@@ -133,6 +139,11 @@ export declare class LocalTime {
|
|
|
133
139
|
unixMillis(): UnixTimestampMillisNumber;
|
|
134
140
|
valueOf(): UnixTimestampNumber;
|
|
135
141
|
toLocalDate(): LocalDate;
|
|
142
|
+
/**
|
|
143
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
144
|
+
* or (if seconds=false):
|
|
145
|
+
* `1984-06-21 17:56`
|
|
146
|
+
*/
|
|
136
147
|
toPretty(seconds?: boolean): IsoDateTimeString;
|
|
137
148
|
/**
|
|
138
149
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
@@ -196,3 +207,4 @@ export declare function getUTCOffsetMinutes(): NumberOfMinutes;
|
|
|
196
207
|
* Instead of -0 it returns 0, for the peace of mind and less weird test/snapshot differences.
|
|
197
208
|
*/
|
|
198
209
|
export declare function getUTCOffsetHours(): NumberOfHours;
|
|
210
|
+
export {};
|
|
@@ -64,7 +64,12 @@ 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())) {
|
|
@@ -107,6 +112,9 @@ class LocalTime {
|
|
|
107
112
|
static fromComponents(c) {
|
|
108
113
|
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
109
114
|
}
|
|
115
|
+
static fromDateUTC(d) {
|
|
116
|
+
return new LocalTime(new Date(d.toISOString()));
|
|
117
|
+
}
|
|
110
118
|
get(unit) {
|
|
111
119
|
if (unit === 'year') {
|
|
112
120
|
return this.$date.getFullYear();
|
|
@@ -422,6 +430,20 @@ class LocalTime {
|
|
|
422
430
|
second: this.$date.getSeconds(),
|
|
423
431
|
};
|
|
424
432
|
}
|
|
433
|
+
dateComponents() {
|
|
434
|
+
return {
|
|
435
|
+
year: this.$date.getFullYear(),
|
|
436
|
+
month: this.$date.getMonth() + 1,
|
|
437
|
+
day: this.$date.getDate(),
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
timeComponents() {
|
|
441
|
+
return {
|
|
442
|
+
hour: this.$date.getHours(),
|
|
443
|
+
minute: this.$date.getMinutes(),
|
|
444
|
+
second: this.$date.getSeconds(),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
425
447
|
fromNow(now = new Date()) {
|
|
426
448
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
427
449
|
if (msDiff === 0)
|
|
@@ -449,27 +471,52 @@ class LocalTime {
|
|
|
449
471
|
toLocalDate() {
|
|
450
472
|
return localDate_1.LocalDate.fromDate(this.$date);
|
|
451
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
476
|
+
* or (if seconds=false):
|
|
477
|
+
* `1984-06-21 17:56`
|
|
478
|
+
*/
|
|
452
479
|
toPretty(seconds = true) {
|
|
453
|
-
|
|
454
|
-
|
|
480
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds);
|
|
481
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
482
|
+
// const s = this.$date.toISOString()
|
|
483
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
455
484
|
}
|
|
456
485
|
/**
|
|
457
486
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
458
487
|
*/
|
|
459
488
|
toISODateTime() {
|
|
460
|
-
return this
|
|
489
|
+
return this.toISODate() + 'T' + this.toISOTime();
|
|
490
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
491
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
461
492
|
}
|
|
462
493
|
/**
|
|
463
494
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
464
495
|
*/
|
|
465
496
|
toISODate() {
|
|
466
|
-
|
|
497
|
+
const { year, month, day } = this.dateComponents();
|
|
498
|
+
return [
|
|
499
|
+
String(year).padStart(4, '0'),
|
|
500
|
+
String(month).padStart(2, '0'),
|
|
501
|
+
String(day).padStart(2, '0'),
|
|
502
|
+
].join('-');
|
|
503
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
504
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
467
505
|
}
|
|
468
506
|
/**
|
|
469
507
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
470
508
|
*/
|
|
471
509
|
toISOTime(seconds = true) {
|
|
472
|
-
|
|
510
|
+
const { hour, minute, second } = this.timeComponents();
|
|
511
|
+
return [
|
|
512
|
+
String(hour).padStart(2, '0'),
|
|
513
|
+
String(minute).padStart(2, '0'),
|
|
514
|
+
seconds && String(second).padStart(2, '0'),
|
|
515
|
+
]
|
|
516
|
+
.filter(Boolean)
|
|
517
|
+
.join(':');
|
|
518
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
519
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
473
520
|
}
|
|
474
521
|
/**
|
|
475
522
|
* Returns e.g: `19840621_1705`
|
|
@@ -493,7 +540,7 @@ class LocalTime {
|
|
|
493
540
|
return this.unix();
|
|
494
541
|
}
|
|
495
542
|
toMonthId() {
|
|
496
|
-
return this
|
|
543
|
+
return this.toISODate().slice(0, 7);
|
|
497
544
|
}
|
|
498
545
|
format(fmt) {
|
|
499
546
|
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,7 +61,12 @@ 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())) {
|
|
@@ -104,6 +109,9 @@ export class LocalTime {
|
|
|
104
109
|
static fromComponents(c) {
|
|
105
110
|
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
106
111
|
}
|
|
112
|
+
static fromDateUTC(d) {
|
|
113
|
+
return new LocalTime(new Date(d.toISOString()));
|
|
114
|
+
}
|
|
107
115
|
get(unit) {
|
|
108
116
|
if (unit === 'year') {
|
|
109
117
|
return this.$date.getFullYear();
|
|
@@ -420,6 +428,20 @@ export class LocalTime {
|
|
|
420
428
|
second: this.$date.getSeconds(),
|
|
421
429
|
};
|
|
422
430
|
}
|
|
431
|
+
dateComponents() {
|
|
432
|
+
return {
|
|
433
|
+
year: this.$date.getFullYear(),
|
|
434
|
+
month: this.$date.getMonth() + 1,
|
|
435
|
+
day: this.$date.getDate(),
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
timeComponents() {
|
|
439
|
+
return {
|
|
440
|
+
hour: this.$date.getHours(),
|
|
441
|
+
minute: this.$date.getMinutes(),
|
|
442
|
+
second: this.$date.getSeconds(),
|
|
443
|
+
};
|
|
444
|
+
}
|
|
423
445
|
fromNow(now = new Date()) {
|
|
424
446
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
|
|
425
447
|
if (msDiff === 0)
|
|
@@ -447,27 +469,52 @@ export class LocalTime {
|
|
|
447
469
|
toLocalDate() {
|
|
448
470
|
return LocalDate.fromDate(this.$date);
|
|
449
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
474
|
+
* or (if seconds=false):
|
|
475
|
+
* `1984-06-21 17:56`
|
|
476
|
+
*/
|
|
450
477
|
toPretty(seconds = true) {
|
|
451
|
-
|
|
452
|
-
|
|
478
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds);
|
|
479
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
480
|
+
// const s = this.$date.toISOString()
|
|
481
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
453
482
|
}
|
|
454
483
|
/**
|
|
455
484
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
456
485
|
*/
|
|
457
486
|
toISODateTime() {
|
|
458
|
-
return this
|
|
487
|
+
return this.toISODate() + 'T' + this.toISOTime();
|
|
488
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
489
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
459
490
|
}
|
|
460
491
|
/**
|
|
461
492
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
462
493
|
*/
|
|
463
494
|
toISODate() {
|
|
464
|
-
|
|
495
|
+
const { year, month, day } = this.dateComponents();
|
|
496
|
+
return [
|
|
497
|
+
String(year).padStart(4, '0'),
|
|
498
|
+
String(month).padStart(2, '0'),
|
|
499
|
+
String(day).padStart(2, '0'),
|
|
500
|
+
].join('-');
|
|
501
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
502
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
465
503
|
}
|
|
466
504
|
/**
|
|
467
505
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
468
506
|
*/
|
|
469
507
|
toISOTime(seconds = true) {
|
|
470
|
-
|
|
508
|
+
const { hour, minute, second } = this.timeComponents();
|
|
509
|
+
return [
|
|
510
|
+
String(hour).padStart(2, '0'),
|
|
511
|
+
String(minute).padStart(2, '0'),
|
|
512
|
+
seconds && String(second).padStart(2, '0'),
|
|
513
|
+
]
|
|
514
|
+
.filter(Boolean)
|
|
515
|
+
.join(':');
|
|
516
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
517
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
471
518
|
}
|
|
472
519
|
/**
|
|
473
520
|
* Returns e.g: `19840621_1705`
|
|
@@ -491,7 +538,7 @@ export class LocalTime {
|
|
|
491
538
|
return this.unix();
|
|
492
539
|
}
|
|
493
540
|
toMonthId() {
|
|
494
|
-
return this
|
|
541
|
+
return this.toISODate().slice(0, 7);
|
|
495
542
|
}
|
|
496
543
|
format(fmt) {
|
|
497
544
|
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.231.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
7
|
+
"test-tz1": "TZ=Europe/Stockholm test local",
|
|
8
|
+
"test-tz2": "TZ=JST-9 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
|
|
@@ -146,6 +156,10 @@ export class LocalTime {
|
|
|
146
156
|
)
|
|
147
157
|
}
|
|
148
158
|
|
|
159
|
+
static fromDateUTC(d: Date): LocalTime {
|
|
160
|
+
return new LocalTime(new Date(d.toISOString()))
|
|
161
|
+
}
|
|
162
|
+
|
|
149
163
|
get(unit: LocalTimeUnit): number {
|
|
150
164
|
if (unit === 'year') {
|
|
151
165
|
return this.$date.getFullYear()
|
|
@@ -514,6 +528,22 @@ export class LocalTime {
|
|
|
514
528
|
}
|
|
515
529
|
}
|
|
516
530
|
|
|
531
|
+
private dateComponents(): DateComponents {
|
|
532
|
+
return {
|
|
533
|
+
year: this.$date.getFullYear(),
|
|
534
|
+
month: this.$date.getMonth() + 1,
|
|
535
|
+
day: this.$date.getDate(),
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private timeComponents(): TimeComponents {
|
|
540
|
+
return {
|
|
541
|
+
hour: this.$date.getHours(),
|
|
542
|
+
minute: this.$date.getMinutes(),
|
|
543
|
+
second: this.$date.getSeconds(),
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
517
547
|
fromNow(now: LocalTimeInput = new Date()): string {
|
|
518
548
|
const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf()
|
|
519
549
|
|
|
@@ -550,30 +580,59 @@ export class LocalTime {
|
|
|
550
580
|
return LocalDate.fromDate(this.$date)
|
|
551
581
|
}
|
|
552
582
|
|
|
583
|
+
/**
|
|
584
|
+
* Returns e.g: `1984-06-21 17:56:21`
|
|
585
|
+
* or (if seconds=false):
|
|
586
|
+
* `1984-06-21 17:56`
|
|
587
|
+
*/
|
|
553
588
|
toPretty(seconds = true): IsoDateTimeString {
|
|
554
|
-
|
|
555
|
-
|
|
589
|
+
return this.toISODate() + ' ' + this.toISOTime(seconds)
|
|
590
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
591
|
+
// const s = this.$date.toISOString()
|
|
592
|
+
// return s.slice(0, 10) + ' ' + s.slice(11, seconds ? 19 : 16)
|
|
556
593
|
}
|
|
557
594
|
|
|
558
595
|
/**
|
|
559
596
|
* Returns e.g: `1984-06-21T17:56:21`
|
|
560
597
|
*/
|
|
561
598
|
toISODateTime(): IsoDateTimeString {
|
|
562
|
-
return this
|
|
599
|
+
return this.toISODate() + 'T' + this.toISOTime()
|
|
600
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
601
|
+
// return this.$date.toISOString().slice(0, 19)
|
|
563
602
|
}
|
|
564
603
|
|
|
565
604
|
/**
|
|
566
605
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
567
606
|
*/
|
|
568
607
|
toISODate(): IsoDateString {
|
|
569
|
-
|
|
608
|
+
const { year, month, day } = this.dateComponents()
|
|
609
|
+
|
|
610
|
+
return [
|
|
611
|
+
String(year).padStart(4, '0'),
|
|
612
|
+
String(month).padStart(2, '0'),
|
|
613
|
+
String(day).padStart(2, '0'),
|
|
614
|
+
].join('-')
|
|
615
|
+
|
|
616
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
617
|
+
// return this.$date.toISOString().slice(0, 10)
|
|
570
618
|
}
|
|
571
619
|
|
|
572
620
|
/**
|
|
573
621
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
574
622
|
*/
|
|
575
623
|
toISOTime(seconds = true): string {
|
|
576
|
-
|
|
624
|
+
const { hour, minute, second } = this.timeComponents()
|
|
625
|
+
|
|
626
|
+
return [
|
|
627
|
+
String(hour).padStart(2, '0'),
|
|
628
|
+
String(minute).padStart(2, '0'),
|
|
629
|
+
seconds && String(second).padStart(2, '0'),
|
|
630
|
+
]
|
|
631
|
+
.filter(Boolean)
|
|
632
|
+
.join(':')
|
|
633
|
+
|
|
634
|
+
// !! Not using toISOString(), as it returns time in UTC, not in local timezone (unexpected!)
|
|
635
|
+
// return this.$date.toISOString().slice(11, seconds ? 19 : 16)
|
|
577
636
|
}
|
|
578
637
|
|
|
579
638
|
/**
|
|
@@ -602,7 +661,7 @@ export class LocalTime {
|
|
|
602
661
|
}
|
|
603
662
|
|
|
604
663
|
toMonthId(): MonthId {
|
|
605
|
-
return this
|
|
664
|
+
return this.toISODate().slice(0, 7)
|
|
606
665
|
}
|
|
607
666
|
|
|
608
667
|
format(fmt: Intl.DateTimeFormat | LocalTimeFormatter): string {
|