@naturalcycles/js-lib 14.243.0 → 14.244.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.js +1 -1
- package/dist/datetime/localDate.d.ts +31 -26
- package/dist/datetime/localDate.js +180 -154
- package/dist/datetime/localTime.d.ts +43 -41
- package/dist/datetime/localTime.js +178 -118
- package/dist/datetime/timeInterval.js +2 -2
- package/dist/env/buildInfo.js +2 -2
- package/dist-esm/datetime/dateInterval.js +1 -1
- package/dist-esm/datetime/localDate.js +180 -154
- package/dist-esm/datetime/localTime.js +178 -118
- package/dist-esm/datetime/timeInterval.js +2 -2
- package/dist-esm/env/buildInfo.js +2 -2
- package/package.json +2 -1
- package/src/datetime/dateInterval.ts +1 -1
- package/src/datetime/localDate.ts +188 -168
- package/src/datetime/localTime.ts +191 -149
- package/src/datetime/timeInterval.ts +2 -5
- package/src/env/buildInfo.ts +2 -2
|
@@ -15,6 +15,7 @@ export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestam
|
|
|
15
15
|
export type LocalTimeInputNullable = LocalTimeInput | null | undefined;
|
|
16
16
|
export type LocalTimeFormatter = (ld: LocalTime) => string;
|
|
17
17
|
export type DateTimeObject = DateObject & TimeObject;
|
|
18
|
+
export type DateTimeObjectInput = DateObject & Partial<TimeObject>;
|
|
18
19
|
export interface DateObject {
|
|
19
20
|
year: number;
|
|
20
21
|
month: number;
|
|
@@ -32,12 +33,12 @@ export declare class LocalTime {
|
|
|
32
33
|
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
33
34
|
* Opposite of `.local()` method.
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
toUTC(): LocalTime;
|
|
36
37
|
/**
|
|
37
38
|
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
38
39
|
* Opposite of `.utc()` method.
|
|
39
40
|
*/
|
|
40
|
-
|
|
41
|
+
toLocal(): LocalTime;
|
|
41
42
|
/**
|
|
42
43
|
* Returns [cloned] fake LocalTime that has yyyy-mm-dd hh:mm:ss in the provided timezone.
|
|
43
44
|
* It is a fake LocalTime in a sense that it's timezone is not real.
|
|
@@ -85,25 +86,25 @@ export declare class LocalTime {
|
|
|
85
86
|
getUTCOffsetString(tz: string): string;
|
|
86
87
|
get(unit: LocalTimeUnit): number;
|
|
87
88
|
set(unit: LocalTimeUnit, v: number, mutate?: boolean): LocalTime;
|
|
88
|
-
year(): number;
|
|
89
|
-
|
|
90
|
-
month(): number;
|
|
91
|
-
|
|
92
|
-
week(): number;
|
|
93
|
-
|
|
94
|
-
day(): number;
|
|
95
|
-
|
|
89
|
+
get year(): number;
|
|
90
|
+
setYear(v: number): LocalTime;
|
|
91
|
+
get month(): number;
|
|
92
|
+
setMonth(v: number): LocalTime;
|
|
93
|
+
get week(): number;
|
|
94
|
+
setWeek(v: number): LocalTime;
|
|
95
|
+
get day(): number;
|
|
96
|
+
setDay(v: number): LocalTime;
|
|
97
|
+
get hour(): number;
|
|
98
|
+
setHour(v: number): LocalTime;
|
|
99
|
+
get minute(): number;
|
|
100
|
+
setMinute(v: number): LocalTime;
|
|
101
|
+
get second(): number;
|
|
102
|
+
setSecond(v: number): LocalTime;
|
|
96
103
|
/**
|
|
97
104
|
* Based on ISO: 1-7 is Mon-Sun.
|
|
98
105
|
*/
|
|
99
|
-
dayOfWeek(): ISODayOfWeek;
|
|
100
|
-
|
|
101
|
-
hour(): number;
|
|
102
|
-
hour(v: number): LocalTime;
|
|
103
|
-
minute(): number;
|
|
104
|
-
minute(v: number): LocalTime;
|
|
105
|
-
second(): number;
|
|
106
|
-
second(v: number): LocalTime;
|
|
106
|
+
get dayOfWeek(): ISODayOfWeek;
|
|
107
|
+
setDayOfWeek(v: ISODayOfWeek): LocalTime;
|
|
107
108
|
setComponents(c: Partial<DateTimeObject>, mutate?: boolean): LocalTime;
|
|
108
109
|
plusSeconds(num: number): LocalTime;
|
|
109
110
|
plusMinutes(num: number): LocalTime;
|
|
@@ -129,7 +130,7 @@ export declare class LocalTime {
|
|
|
129
130
|
* Returns how many days are in the current month.
|
|
130
131
|
* E.g 31 for January.
|
|
131
132
|
*/
|
|
132
|
-
daysInMonth(): number;
|
|
133
|
+
get daysInMonth(): number;
|
|
133
134
|
isSame(d: LocalTimeInput): boolean;
|
|
134
135
|
isBefore(d: LocalTimeInput, inclusive?: boolean): boolean;
|
|
135
136
|
isSameOrBefore(d: LocalTimeInput): boolean;
|
|
@@ -176,15 +177,15 @@ export declare class LocalTime {
|
|
|
176
177
|
* returns 0 if they are equal
|
|
177
178
|
* returns -1 if this < d
|
|
178
179
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
compare(d: LocalTimeInput): -1 | 0 | 1;
|
|
181
|
+
toDateTimeObject(): DateTimeObject;
|
|
182
|
+
toDateObject(): DateObject;
|
|
183
|
+
toTimeObject(): TimeObject;
|
|
184
|
+
toFromNowString(now?: LocalTimeInput): string;
|
|
185
|
+
toDate(): Date;
|
|
185
186
|
clone(): LocalTime;
|
|
186
|
-
unix(): UnixTimestampNumber;
|
|
187
|
-
unixMillis(): UnixTimestampMillisNumber;
|
|
187
|
+
get unix(): UnixTimestampNumber;
|
|
188
|
+
get unixMillis(): UnixTimestampMillisNumber;
|
|
188
189
|
valueOf(): UnixTimestampNumber;
|
|
189
190
|
toLocalDate(): LocalDate;
|
|
190
191
|
/**
|
|
@@ -216,21 +217,26 @@ export declare class LocalTime {
|
|
|
216
217
|
}
|
|
217
218
|
declare class LocalTimeFactory {
|
|
218
219
|
/**
|
|
219
|
-
* Parses input String into
|
|
220
|
-
* Input can already be a
|
|
220
|
+
* Parses input String into LocalTime.
|
|
221
|
+
* Input can already be a LocalTime - it is returned as-is in that case.
|
|
221
222
|
*/
|
|
222
|
-
|
|
223
|
+
from(input: LocalTimeInput): LocalTime;
|
|
224
|
+
fromDate(date: Date): LocalTime;
|
|
225
|
+
fromUnix(ts: UnixTimestampNumber): LocalTime;
|
|
223
226
|
/**
|
|
224
227
|
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
225
228
|
*/
|
|
226
|
-
|
|
229
|
+
fromMillis(millis: UnixTimestampMillisNumber): LocalTime;
|
|
227
230
|
/**
|
|
228
231
|
* Returns null if invalid
|
|
229
232
|
*/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
fromOrNull(d: LocalTimeInputNullable): LocalTime | null;
|
|
234
|
+
fromStringOrNull(s: string | undefined | null): LocalTime | null;
|
|
235
|
+
fromDateTimeObject(input: DateTimeObjectInput): LocalTime;
|
|
236
|
+
private parseStringToDateOrNull;
|
|
237
|
+
isValid(input: LocalTimeInputNullable): boolean;
|
|
238
|
+
isValidString(isoString: string | undefined | null): boolean;
|
|
239
|
+
private assertNotNull;
|
|
234
240
|
/**
|
|
235
241
|
* Returns the IANA timezone e.g `Europe/Stockholm`.
|
|
236
242
|
* https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
@@ -250,15 +256,11 @@ declare class LocalTimeFactory {
|
|
|
250
256
|
*
|
|
251
257
|
* `localTime` function will instead return LocalTime of `now` for falsy input.
|
|
252
258
|
*/
|
|
253
|
-
orUndefined(
|
|
259
|
+
orUndefined(input: LocalTimeInputNullable): LocalTime | undefined;
|
|
254
260
|
/**
|
|
255
261
|
* Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
|
|
256
262
|
*/
|
|
257
|
-
orNow(
|
|
258
|
-
fromComponents(c: {
|
|
259
|
-
year: number;
|
|
260
|
-
month: number;
|
|
261
|
-
} & Partial<DateTimeObject>): LocalTime;
|
|
263
|
+
orNow(input: LocalTimeInputNullable): LocalTime;
|
|
262
264
|
sort(items: LocalTime[], dir?: SortDirection, mutate?: boolean): LocalTime[];
|
|
263
265
|
minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined;
|
|
264
266
|
min(items: LocalTimeInputNullable[]): LocalTime;
|
|
@@ -23,6 +23,10 @@ const SECONDS_IN_DAY = 86400;
|
|
|
23
23
|
// const MILLISECONDS_IN_DAY = 86400000
|
|
24
24
|
// const MILLISECONDS_IN_MINUTE = 60000
|
|
25
25
|
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
|
|
26
|
+
// It supports 2 forms:
|
|
27
|
+
// 1. 2023-03-03
|
|
28
|
+
// 2. 2023-03-03T05:10:02
|
|
29
|
+
const DATE_TIME_REGEX = /^(\d{4})-(\d{2})-(\d{2})([T\s](\d{2}):(\d{2}):(\d{2}))?/;
|
|
26
30
|
class LocalTime {
|
|
27
31
|
constructor($date) {
|
|
28
32
|
this.$date = $date;
|
|
@@ -31,14 +35,14 @@ class LocalTime {
|
|
|
31
35
|
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in UTC timezone.
|
|
32
36
|
* Opposite of `.local()` method.
|
|
33
37
|
*/
|
|
34
|
-
|
|
38
|
+
toUTC() {
|
|
35
39
|
return new LocalTime(new Date(this.$date.toISOString()));
|
|
36
40
|
}
|
|
37
41
|
/**
|
|
38
42
|
* Returns [cloned] LocalTime that is based on the same unixtimestamp, but in local timezone.
|
|
39
43
|
* Opposite of `.utc()` method.
|
|
40
44
|
*/
|
|
41
|
-
|
|
45
|
+
toLocal() {
|
|
42
46
|
return new LocalTime(new Date(this.$date.getTime()));
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
@@ -160,34 +164,58 @@ class LocalTime {
|
|
|
160
164
|
}
|
|
161
165
|
return t;
|
|
162
166
|
}
|
|
163
|
-
year(
|
|
164
|
-
return
|
|
167
|
+
get year() {
|
|
168
|
+
return this.$date.getFullYear();
|
|
165
169
|
}
|
|
166
|
-
|
|
167
|
-
return
|
|
170
|
+
setYear(v) {
|
|
171
|
+
return this.set('year', v);
|
|
168
172
|
}
|
|
169
|
-
|
|
170
|
-
return
|
|
173
|
+
get month() {
|
|
174
|
+
return this.$date.getMonth() + 1;
|
|
171
175
|
}
|
|
172
|
-
|
|
173
|
-
return
|
|
176
|
+
setMonth(v) {
|
|
177
|
+
return this.set('month', v);
|
|
174
178
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
get week() {
|
|
180
|
+
return getWeek(this.$date);
|
|
181
|
+
}
|
|
182
|
+
setWeek(v) {
|
|
183
|
+
return this.set('week', v);
|
|
184
|
+
}
|
|
185
|
+
get day() {
|
|
186
|
+
return this.$date.getDate();
|
|
182
187
|
}
|
|
183
|
-
|
|
184
|
-
return
|
|
188
|
+
setDay(v) {
|
|
189
|
+
return this.set('day', v);
|
|
185
190
|
}
|
|
186
|
-
|
|
187
|
-
return
|
|
191
|
+
get hour() {
|
|
192
|
+
return this.$date.getHours();
|
|
193
|
+
}
|
|
194
|
+
setHour(v) {
|
|
195
|
+
return this.set('hour', v);
|
|
196
|
+
}
|
|
197
|
+
get minute() {
|
|
198
|
+
return this.$date.getMinutes();
|
|
199
|
+
}
|
|
200
|
+
setMinute(v) {
|
|
201
|
+
return this.set('minute', v);
|
|
202
|
+
}
|
|
203
|
+
get second() {
|
|
204
|
+
return this.$date.getSeconds();
|
|
188
205
|
}
|
|
189
|
-
|
|
190
|
-
return
|
|
206
|
+
setSecond(v) {
|
|
207
|
+
return this.set('second', v);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Based on ISO: 1-7 is Mon-Sun.
|
|
211
|
+
*/
|
|
212
|
+
get dayOfWeek() {
|
|
213
|
+
return (this.$date.getDay() || 7);
|
|
214
|
+
}
|
|
215
|
+
setDayOfWeek(v) {
|
|
216
|
+
(0, assert_1._assert)(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`);
|
|
217
|
+
const dow = this.$date.getDay() || 7;
|
|
218
|
+
return this.plus(v - dow, 'day');
|
|
191
219
|
}
|
|
192
220
|
setComponents(c, mutate = false) {
|
|
193
221
|
const d = mutate ? this.$date : new Date(this.$date);
|
|
@@ -255,7 +283,7 @@ class LocalTime {
|
|
|
255
283
|
}
|
|
256
284
|
if (unit === 'year' || unit === 'month') {
|
|
257
285
|
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
|
|
258
|
-
return mutate ? this : exports.localTime.
|
|
286
|
+
return mutate ? this : exports.localTime.from(d);
|
|
259
287
|
}
|
|
260
288
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
261
289
|
}
|
|
@@ -266,7 +294,7 @@ class LocalTime {
|
|
|
266
294
|
return Math.abs(this.diff(other, unit));
|
|
267
295
|
}
|
|
268
296
|
diff(other, unit) {
|
|
269
|
-
const date2 = exports.localTime.
|
|
297
|
+
const date2 = exports.localTime.from(other).$date;
|
|
270
298
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
271
299
|
if (!secDiff)
|
|
272
300
|
return 0;
|
|
@@ -354,32 +382,32 @@ class LocalTime {
|
|
|
354
382
|
* Returns how many days are in the current month.
|
|
355
383
|
* E.g 31 for January.
|
|
356
384
|
*/
|
|
357
|
-
daysInMonth() {
|
|
385
|
+
get daysInMonth() {
|
|
358
386
|
return localDate_1.localDate.getMonthLength(this.$date.getFullYear(), this.$date.getMonth() + 1);
|
|
359
387
|
}
|
|
360
388
|
isSame(d) {
|
|
361
|
-
return this.
|
|
389
|
+
return this.compare(d) === 0;
|
|
362
390
|
}
|
|
363
391
|
isBefore(d, inclusive = false) {
|
|
364
|
-
const r = this.
|
|
392
|
+
const r = this.compare(d);
|
|
365
393
|
return r === -1 || (r === 0 && inclusive);
|
|
366
394
|
}
|
|
367
395
|
isSameOrBefore(d) {
|
|
368
|
-
return this.
|
|
396
|
+
return this.compare(d) <= 0;
|
|
369
397
|
}
|
|
370
398
|
isAfter(d, inclusive = false) {
|
|
371
|
-
const r = this.
|
|
399
|
+
const r = this.compare(d);
|
|
372
400
|
return r === 1 || (r === 0 && inclusive);
|
|
373
401
|
}
|
|
374
402
|
isSameOrAfter(d) {
|
|
375
|
-
return this.
|
|
403
|
+
return this.compare(d) >= 0;
|
|
376
404
|
}
|
|
377
405
|
isBetween(min, max, incl = '[)') {
|
|
378
|
-
let r = this.
|
|
406
|
+
let r = this.compare(min);
|
|
379
407
|
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
380
408
|
if (r < 0 || (r === 0 && incl[0] === '('))
|
|
381
409
|
return false;
|
|
382
|
-
r = this.
|
|
410
|
+
r = this.compare(max);
|
|
383
411
|
if (r > 0 || (r === 0 && incl[1] === ')'))
|
|
384
412
|
return false;
|
|
385
413
|
return true;
|
|
@@ -394,13 +422,13 @@ class LocalTime {
|
|
|
394
422
|
* Third argument allows to override "now".
|
|
395
423
|
*/
|
|
396
424
|
isOlderThan(n, unit, now) {
|
|
397
|
-
return this.isBefore(exports.localTime.
|
|
425
|
+
return this.isBefore(exports.localTime.from(now ?? new Date()).plus(-n, unit));
|
|
398
426
|
}
|
|
399
427
|
/**
|
|
400
428
|
* Checks if this localTime is same or older (<=) than "now" by X units.
|
|
401
429
|
*/
|
|
402
430
|
isSameOrOlderThan(n, unit, now) {
|
|
403
|
-
return this.isSameOrBefore(exports.localTime.
|
|
431
|
+
return this.isSameOrBefore(exports.localTime.from(now ?? new Date()).plus(-n, unit));
|
|
404
432
|
}
|
|
405
433
|
/**
|
|
406
434
|
* Checks if this localTime is younger (>) than "now" by X units.
|
|
@@ -412,13 +440,13 @@ class LocalTime {
|
|
|
412
440
|
* Third argument allows to override "now".
|
|
413
441
|
*/
|
|
414
442
|
isYoungerThan(n, unit, now) {
|
|
415
|
-
return this.isAfter(exports.localTime.
|
|
443
|
+
return this.isAfter(exports.localTime.from(now ?? new Date()).plus(-n, unit));
|
|
416
444
|
}
|
|
417
445
|
/**
|
|
418
446
|
* Checks if this localTime is same or younger (>=) than "now" by X units.
|
|
419
447
|
*/
|
|
420
448
|
isSameOrYoungerThan(n, unit, now) {
|
|
421
|
-
return this.isSameOrAfter(exports.localTime.
|
|
449
|
+
return this.isSameOrAfter(exports.localTime.from(now ?? new Date()).plus(-n, unit));
|
|
422
450
|
}
|
|
423
451
|
getAgeInYears(now) {
|
|
424
452
|
return this.getAgeIn('year', now);
|
|
@@ -439,42 +467,42 @@ class LocalTime {
|
|
|
439
467
|
return this.getAgeIn('second', now);
|
|
440
468
|
}
|
|
441
469
|
getAgeIn(unit, now) {
|
|
442
|
-
return exports.localTime.
|
|
470
|
+
return exports.localTime.from(now ?? new Date()).diff(this, unit);
|
|
443
471
|
}
|
|
444
472
|
/**
|
|
445
473
|
* Returns 1 if this > d
|
|
446
474
|
* returns 0 if they are equal
|
|
447
475
|
* returns -1 if this < d
|
|
448
476
|
*/
|
|
449
|
-
|
|
477
|
+
compare(d) {
|
|
450
478
|
const t1 = this.$date.valueOf();
|
|
451
|
-
const t2 = exports.localTime.
|
|
479
|
+
const t2 = exports.localTime.from(d).$date.valueOf();
|
|
452
480
|
if (t1 === t2)
|
|
453
481
|
return 0;
|
|
454
482
|
return t1 < t2 ? -1 : 1;
|
|
455
483
|
}
|
|
456
|
-
|
|
484
|
+
toDateTimeObject() {
|
|
457
485
|
return {
|
|
458
|
-
...this.
|
|
459
|
-
...this.
|
|
486
|
+
...this.toDateObject(),
|
|
487
|
+
...this.toTimeObject(),
|
|
460
488
|
};
|
|
461
489
|
}
|
|
462
|
-
|
|
490
|
+
toDateObject() {
|
|
463
491
|
return {
|
|
464
492
|
year: this.$date.getFullYear(),
|
|
465
493
|
month: this.$date.getMonth() + 1,
|
|
466
494
|
day: this.$date.getDate(),
|
|
467
495
|
};
|
|
468
496
|
}
|
|
469
|
-
|
|
497
|
+
toTimeObject() {
|
|
470
498
|
return {
|
|
471
499
|
hour: this.$date.getHours(),
|
|
472
500
|
minute: this.$date.getMinutes(),
|
|
473
501
|
second: this.$date.getSeconds(),
|
|
474
502
|
};
|
|
475
503
|
}
|
|
476
|
-
|
|
477
|
-
const msDiff = exports.localTime.
|
|
504
|
+
toFromNowString(now = new Date()) {
|
|
505
|
+
const msDiff = exports.localTime.from(now).$date.valueOf() - this.$date.valueOf();
|
|
478
506
|
if (msDiff === 0)
|
|
479
507
|
return 'now';
|
|
480
508
|
if (msDiff >= 0) {
|
|
@@ -482,16 +510,16 @@ class LocalTime {
|
|
|
482
510
|
}
|
|
483
511
|
return `in ${(0, time_util_1._ms)(msDiff * -1)}`;
|
|
484
512
|
}
|
|
485
|
-
|
|
513
|
+
toDate() {
|
|
486
514
|
return this.$date;
|
|
487
515
|
}
|
|
488
516
|
clone() {
|
|
489
517
|
return new LocalTime(new Date(this.$date));
|
|
490
518
|
}
|
|
491
|
-
unix() {
|
|
519
|
+
get unix() {
|
|
492
520
|
return Math.floor(this.$date.valueOf() / 1000);
|
|
493
521
|
}
|
|
494
|
-
unixMillis() {
|
|
522
|
+
get unixMillis() {
|
|
495
523
|
return this.$date.valueOf();
|
|
496
524
|
}
|
|
497
525
|
valueOf() {
|
|
@@ -523,7 +551,7 @@ class LocalTime {
|
|
|
523
551
|
* Returns e.g: `1984-06-21`, only the date part of DateTime
|
|
524
552
|
*/
|
|
525
553
|
toISODate() {
|
|
526
|
-
const { year, month, day } = this.
|
|
554
|
+
const { year, month, day } = this.toDateObject();
|
|
527
555
|
return [
|
|
528
556
|
String(year).padStart(4, '0'),
|
|
529
557
|
String(month).padStart(2, '0'),
|
|
@@ -536,7 +564,7 @@ class LocalTime {
|
|
|
536
564
|
* Returns e.g: `17:03:15` (or `17:03` with seconds=false)
|
|
537
565
|
*/
|
|
538
566
|
toISOTime(seconds = true) {
|
|
539
|
-
const { hour, minute, second } = this.
|
|
567
|
+
const { hour, minute, second } = this.toTimeObject();
|
|
540
568
|
return [
|
|
541
569
|
String(hour).padStart(2, '0'),
|
|
542
570
|
String(minute).padStart(2, '0'),
|
|
@@ -551,7 +579,7 @@ class LocalTime {
|
|
|
551
579
|
* Returns e.g: `19840621_1705`
|
|
552
580
|
*/
|
|
553
581
|
toStringCompact(seconds = false) {
|
|
554
|
-
const { year, month, day, hour, minute, second } = this.
|
|
582
|
+
const { year, month, day, hour, minute, second } = this.toDateTimeObject();
|
|
555
583
|
return [
|
|
556
584
|
String(year).padStart(4, '0'),
|
|
557
585
|
String(month).padStart(2, '0'),
|
|
@@ -566,7 +594,7 @@ class LocalTime {
|
|
|
566
594
|
return this.toISODateTime();
|
|
567
595
|
}
|
|
568
596
|
toJSON() {
|
|
569
|
-
return this.unix
|
|
597
|
+
return this.unix;
|
|
570
598
|
}
|
|
571
599
|
toMonthId() {
|
|
572
600
|
return this.toISODate().slice(0, 7);
|
|
@@ -581,82 +609,117 @@ class LocalTime {
|
|
|
581
609
|
exports.LocalTime = LocalTime;
|
|
582
610
|
class LocalTimeFactory {
|
|
583
611
|
/**
|
|
584
|
-
* Parses input String into
|
|
585
|
-
* Input can already be a
|
|
612
|
+
* Parses input String into LocalTime.
|
|
613
|
+
* Input can already be a LocalTime - it is returned as-is in that case.
|
|
586
614
|
*/
|
|
587
|
-
|
|
588
|
-
const
|
|
589
|
-
(
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
615
|
+
from(input) {
|
|
616
|
+
const lt = this.fromOrNull(input);
|
|
617
|
+
this.assertNotNull(lt, input);
|
|
618
|
+
return lt;
|
|
619
|
+
}
|
|
620
|
+
fromDate(date) {
|
|
621
|
+
return new LocalTime(date);
|
|
622
|
+
}
|
|
623
|
+
fromUnix(ts) {
|
|
624
|
+
return new LocalTime(new Date(ts * 1000));
|
|
593
625
|
}
|
|
594
626
|
/**
|
|
595
627
|
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
596
628
|
*/
|
|
597
|
-
|
|
598
|
-
return
|
|
629
|
+
fromMillis(millis) {
|
|
630
|
+
return new LocalTime(new Date(millis));
|
|
599
631
|
}
|
|
600
632
|
/**
|
|
601
633
|
* Returns null if invalid
|
|
602
634
|
*/
|
|
603
|
-
|
|
635
|
+
fromOrNull(d) {
|
|
604
636
|
if (d instanceof LocalTime)
|
|
605
637
|
return d;
|
|
606
|
-
let date;
|
|
607
638
|
if (d instanceof Date) {
|
|
608
|
-
|
|
639
|
+
return new LocalTime(d);
|
|
609
640
|
}
|
|
610
|
-
|
|
611
|
-
|
|
641
|
+
if (typeof d === 'number') {
|
|
642
|
+
return new LocalTime(new Date(d * 1000));
|
|
612
643
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
return null;
|
|
644
|
+
if (typeof d === 'string') {
|
|
645
|
+
return this.fromStringOrNull(d);
|
|
616
646
|
}
|
|
617
|
-
|
|
618
|
-
|
|
647
|
+
// This check is after checking the number, to support `0`
|
|
648
|
+
// unexpected type, e.g Function or something
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
fromStringOrNull(s) {
|
|
652
|
+
const date = this.parseStringToDateOrNull(s);
|
|
653
|
+
return date ? new LocalTime(date) : null;
|
|
654
|
+
}
|
|
655
|
+
fromDateTimeObject(input) {
|
|
656
|
+
const { year, month, day = 1, hour = 0, minute = 0, second = 0 } = input;
|
|
657
|
+
return new LocalTime(new Date(year, month - 1, day, hour, minute, second));
|
|
658
|
+
}
|
|
659
|
+
parseStringToDateOrNull(s) {
|
|
660
|
+
if (!s)
|
|
661
|
+
return null;
|
|
662
|
+
// Slicing removes the "timezone component", and makes the date "local"
|
|
663
|
+
// e.g 2022-04-06T23:15:00+09:00
|
|
664
|
+
// becomes 2022-04-06T23:15:00
|
|
665
|
+
// date = new Date(d.slice(0, 19))
|
|
666
|
+
// Parsing is inspired by how Day.js does it
|
|
667
|
+
// Specifically, it ensures that `localTime('2023-03-03')` returns the expected Date, and not a day before
|
|
668
|
+
// Because `new Date('2023-03-03')` in NewYork gives you '2023-03-02 19:00:00 GMT-0500'
|
|
669
|
+
const m = s.match(DATE_TIME_REGEX);
|
|
670
|
+
// Validate in 3 ways:
|
|
671
|
+
// 1. Should match Regex.
|
|
672
|
+
// In some ways it's stricter than Date constructor, e.g it doesn't allow 2023/05/05
|
|
673
|
+
// In other ways it's looser, e.g it allows `2023-05-05T`, while Date constructor doesn't.
|
|
674
|
+
// 2. Date constructor (of Node/v8 implementation, which we know is different from e.g WebKit/Safari)
|
|
675
|
+
// should not return `Invalid Date`.
|
|
676
|
+
// 3. Year, month and day should be valid, e.g 2023-01-32 should not be allowed.
|
|
677
|
+
// UPD: Actually, 3 can be skipped, because 2 is catching it already
|
|
678
|
+
// UPD: 2 is skipped, 1 and 3 are kept
|
|
679
|
+
// if (!m || isNaN(new Date(s).getDate())) return null
|
|
680
|
+
if (!m)
|
|
681
|
+
return null;
|
|
682
|
+
const year = Number(m[1]);
|
|
683
|
+
const month = Number(m[2]);
|
|
684
|
+
const day = Number(m[3]);
|
|
685
|
+
const hour = Number(m[5]);
|
|
686
|
+
const minute = Number(m[6]);
|
|
687
|
+
const second = Number(m[7]);
|
|
688
|
+
// Validation for just the Date part
|
|
689
|
+
if (!year ||
|
|
690
|
+
!month ||
|
|
691
|
+
month < 1 ||
|
|
692
|
+
month > 12 ||
|
|
693
|
+
!day ||
|
|
694
|
+
day < 1 ||
|
|
695
|
+
day > localDate_1.localDate.getMonthLength(year, month)) {
|
|
619
696
|
return null;
|
|
620
697
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
698
|
+
// Validation for Date+Time string, since the string is longer than YYYY-MM-DD
|
|
699
|
+
if (s.length > 10 &&
|
|
700
|
+
(isNaN(hour) ||
|
|
701
|
+
isNaN(minute) ||
|
|
702
|
+
isNaN(second) ||
|
|
703
|
+
hour < 0 ||
|
|
704
|
+
hour > 23 ||
|
|
705
|
+
minute < 0 ||
|
|
706
|
+
minute > 59 ||
|
|
707
|
+
second < 0 ||
|
|
708
|
+
second > 59)) {
|
|
632
709
|
return null;
|
|
633
710
|
}
|
|
634
|
-
return new
|
|
711
|
+
return new Date(year, month - 1, day, hour || 0, minute || 0, second || 0, 0);
|
|
635
712
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
return d.$date;
|
|
639
|
-
if (d instanceof Date)
|
|
640
|
-
return d;
|
|
641
|
-
const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
|
|
642
|
-
(0, assert_1._assert)(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
|
|
643
|
-
input: d,
|
|
644
|
-
});
|
|
645
|
-
return date;
|
|
713
|
+
isValid(input) {
|
|
714
|
+
return this.fromOrNull(input) !== null;
|
|
646
715
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
return d;
|
|
650
|
-
if (d instanceof LocalTime)
|
|
651
|
-
return d.unix();
|
|
652
|
-
const date = d instanceof Date ? d : new Date(d);
|
|
653
|
-
(0, assert_1._assert)(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
|
|
654
|
-
input: d,
|
|
655
|
-
});
|
|
656
|
-
return date.valueOf() / 1000;
|
|
716
|
+
isValidString(isoString) {
|
|
717
|
+
return this.fromStringOrNull(isoString) !== null;
|
|
657
718
|
}
|
|
658
|
-
|
|
659
|
-
|
|
719
|
+
assertNotNull(lt, input) {
|
|
720
|
+
(0, assert_1._assert)(lt !== null, `Cannot parse "${input}" into LocalTime`, {
|
|
721
|
+
input,
|
|
722
|
+
});
|
|
660
723
|
}
|
|
661
724
|
/**
|
|
662
725
|
* Returns the IANA timezone e.g `Europe/Stockholm`.
|
|
@@ -683,17 +746,14 @@ class LocalTimeFactory {
|
|
|
683
746
|
*
|
|
684
747
|
* `localTime` function will instead return LocalTime of `now` for falsy input.
|
|
685
748
|
*/
|
|
686
|
-
orUndefined(
|
|
687
|
-
return
|
|
749
|
+
orUndefined(input) {
|
|
750
|
+
return input || input === 0 ? this.from(input) : undefined;
|
|
688
751
|
}
|
|
689
752
|
/**
|
|
690
753
|
* Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
|
|
691
754
|
*/
|
|
692
|
-
orNow(
|
|
693
|
-
return
|
|
694
|
-
}
|
|
695
|
-
fromComponents(c) {
|
|
696
|
-
return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
|
|
755
|
+
orNow(input) {
|
|
756
|
+
return input || input === 0 ? this.from(input) : this.now();
|
|
697
757
|
}
|
|
698
758
|
sort(items, dir = 'asc', mutate = false) {
|
|
699
759
|
const mod = dir === 'desc' ? -1 : 1;
|
|
@@ -712,7 +772,7 @@ class LocalTimeFactory {
|
|
|
712
772
|
const items2 = items.filter(is_util_1._isTruthy);
|
|
713
773
|
(0, assert_1._assert)(items2.length, 'localTime.min called on empty array');
|
|
714
774
|
return items2
|
|
715
|
-
.map(i => this.
|
|
775
|
+
.map(i => this.from(i))
|
|
716
776
|
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
|
|
717
777
|
}
|
|
718
778
|
maxOrUndefined(items) {
|
|
@@ -722,7 +782,7 @@ class LocalTimeFactory {
|
|
|
722
782
|
const items2 = items.filter(is_util_1._isTruthy);
|
|
723
783
|
(0, assert_1._assert)(items2.length, 'localTime.max called on empty array');
|
|
724
784
|
return items2
|
|
725
|
-
.map(i => this.
|
|
785
|
+
.map(i => this.from(i))
|
|
726
786
|
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
|
|
727
787
|
}
|
|
728
788
|
}
|
|
@@ -815,7 +875,7 @@ function differenceInMonths(a, b) {
|
|
|
815
875
|
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
|
|
816
876
|
}
|
|
817
877
|
const localTimeFactory = new LocalTimeFactory();
|
|
818
|
-
exports.localTime = localTimeFactory.
|
|
878
|
+
exports.localTime = localTimeFactory.from.bind(localTimeFactory);
|
|
819
879
|
// The line below is the blackest of black magic I have ever written in 2024.
|
|
820
880
|
// And probably 2023 as well.
|
|
821
881
|
Object.setPrototypeOf(exports.localTime, localTimeFactory);
|