@naturalcycles/js-lib 14.244.0 → 14.245.1
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 -1
- package/dist/datetime/localDate.d.ts +62 -43
- package/dist/datetime/localDate.js +153 -123
- package/dist/datetime/localTime.d.ts +57 -28
- package/dist/datetime/localTime.js +205 -138
- package/dist/datetime/timeInterval.d.ts +2 -2
- package/dist/datetime/timeInterval.js +2 -2
- package/dist/error/error.util.d.ts +1 -1
- package/dist/index.d.ts +37 -37
- package/dist/index.js +37 -37
- package/dist/json-schema/from-data/generateJsonSchemaFromData.d.ts +1 -1
- package/dist/json-schema/jsonSchemaBuilder.d.ts +1 -1
- package/dist/log/commonLogger.js +10 -9
- package/dist/object/object.util.d.ts +1 -1
- package/dist/time/time.util.js +4 -2
- package/dist/zod/zod.util.d.ts +1 -1
- package/dist-esm/datetime/localDate.js +153 -122
- package/dist-esm/datetime/localTime.js +205 -137
- package/dist-esm/datetime/timeInterval.js +2 -2
- package/dist-esm/decorators/logMethod.decorator.js +1 -1
- package/dist-esm/index.js +37 -37
- package/dist-esm/json-schema/jsonSchemaBuilder.js +1 -1
- package/dist-esm/log/commonLogger.js +2 -1
- package/dist-esm/time/time.util.js +4 -2
- package/package.json +1 -1
- package/src/datetime/dateInterval.ts +1 -1
- package/src/datetime/localDate.ts +157 -133
- package/src/datetime/localTime.ts +204 -149
- package/src/datetime/timeInterval.ts +4 -4
- package/src/decorators/logMethod.decorator.ts +1 -1
- package/src/define.ts +1 -1
- package/src/error/error.util.ts +3 -3
- package/src/http/fetcher.ts +1 -1
- package/src/index.ts +37 -37
- package/src/json-schema/from-data/generateJsonSchemaFromData.ts +1 -1
- package/src/json-schema/jsonSchemaBuilder.ts +2 -2
- package/src/log/commonLogger.ts +2 -1
- package/src/object/object.util.ts +1 -1
- package/src/time/time.util.ts +4 -1
- package/src/zod/zod.util.ts +1 -1
|
@@ -19,10 +19,22 @@ const SECONDS_IN_DAY = 86400;
|
|
|
19
19
|
// const MILLISECONDS_IN_DAY = 86400000
|
|
20
20
|
// const MILLISECONDS_IN_MINUTE = 60000
|
|
21
21
|
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* It supports 2 forms:
|
|
24
|
+
* 1. 2023-03-03
|
|
25
|
+
* 2. 2023-03-03T05:10:02
|
|
26
|
+
* // todo: make it even looser, like Day.js
|
|
27
|
+
*/
|
|
28
|
+
const DATE_TIME_REGEX_LOOSE = /^(\d{4})-(\d{2})-(\d{2})([Tt\s](\d{2}):?(\d{2})?:?(\d{2})?)?/;
|
|
29
|
+
/**
|
|
30
|
+
* Supports 2 forms:
|
|
31
|
+
* 1. 2023-03-03
|
|
32
|
+
* 2. 2023-03-03T05:10:02
|
|
33
|
+
* Ok, now it allows arbitrary stuff after `:ss`, to allow millis/timezone info,
|
|
34
|
+
* but it will not take it into account.
|
|
35
|
+
*/
|
|
36
|
+
const DATE_TIME_REGEX_STRICT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/;
|
|
37
|
+
const DATE_REGEX_STRICT = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
26
38
|
export class LocalTime {
|
|
27
39
|
constructor($date) {
|
|
28
40
|
this.$date = $date;
|
|
@@ -279,7 +291,7 @@ export class LocalTime {
|
|
|
279
291
|
}
|
|
280
292
|
if (unit === 'year' || unit === 'month') {
|
|
281
293
|
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
|
|
282
|
-
return mutate ? this : localTime.
|
|
294
|
+
return mutate ? this : localTime.fromInput(d);
|
|
283
295
|
}
|
|
284
296
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
285
297
|
}
|
|
@@ -290,7 +302,7 @@ export class LocalTime {
|
|
|
290
302
|
return Math.abs(this.diff(other, unit));
|
|
291
303
|
}
|
|
292
304
|
diff(other, unit) {
|
|
293
|
-
const date2 = localTime.
|
|
305
|
+
const date2 = localTime.fromInput(other).$date;
|
|
294
306
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
295
307
|
if (!secDiff)
|
|
296
308
|
return 0;
|
|
@@ -418,13 +430,13 @@ export class LocalTime {
|
|
|
418
430
|
* Third argument allows to override "now".
|
|
419
431
|
*/
|
|
420
432
|
isOlderThan(n, unit, now) {
|
|
421
|
-
return this.isBefore(localTime.
|
|
433
|
+
return this.isBefore(localTime.fromInput(now ?? new Date()).plus(-n, unit));
|
|
422
434
|
}
|
|
423
435
|
/**
|
|
424
436
|
* Checks if this localTime is same or older (<=) than "now" by X units.
|
|
425
437
|
*/
|
|
426
438
|
isSameOrOlderThan(n, unit, now) {
|
|
427
|
-
return this.isSameOrBefore(localTime.
|
|
439
|
+
return this.isSameOrBefore(localTime.fromInput(now ?? new Date()).plus(-n, unit));
|
|
428
440
|
}
|
|
429
441
|
/**
|
|
430
442
|
* Checks if this localTime is younger (>) than "now" by X units.
|
|
@@ -436,13 +448,13 @@ export class LocalTime {
|
|
|
436
448
|
* Third argument allows to override "now".
|
|
437
449
|
*/
|
|
438
450
|
isYoungerThan(n, unit, now) {
|
|
439
|
-
return this.isAfter(localTime.
|
|
451
|
+
return this.isAfter(localTime.fromInput(now ?? new Date()).plus(-n, unit));
|
|
440
452
|
}
|
|
441
453
|
/**
|
|
442
454
|
* Checks if this localTime is same or younger (>=) than "now" by X units.
|
|
443
455
|
*/
|
|
444
456
|
isSameOrYoungerThan(n, unit, now) {
|
|
445
|
-
return this.isSameOrAfter(localTime.
|
|
457
|
+
return this.isSameOrAfter(localTime.fromInput(now ?? new Date()).plus(-n, unit));
|
|
446
458
|
}
|
|
447
459
|
getAgeInYears(now) {
|
|
448
460
|
return this.getAgeIn('year', now);
|
|
@@ -463,7 +475,7 @@ export class LocalTime {
|
|
|
463
475
|
return this.getAgeIn('second', now);
|
|
464
476
|
}
|
|
465
477
|
getAgeIn(unit, now) {
|
|
466
|
-
return localTime.
|
|
478
|
+
return localTime.fromInput(now ?? new Date()).diff(this, unit);
|
|
467
479
|
}
|
|
468
480
|
/**
|
|
469
481
|
* Returns 1 if this > d
|
|
@@ -472,7 +484,7 @@ export class LocalTime {
|
|
|
472
484
|
*/
|
|
473
485
|
compare(d) {
|
|
474
486
|
const t1 = this.$date.valueOf();
|
|
475
|
-
const t2 = localTime.
|
|
487
|
+
const t2 = localTime.fromInput(d).$date.valueOf();
|
|
476
488
|
if (t1 === t2)
|
|
477
489
|
return 0;
|
|
478
490
|
return t1 < t2 ? -1 : 1;
|
|
@@ -498,7 +510,7 @@ export class LocalTime {
|
|
|
498
510
|
};
|
|
499
511
|
}
|
|
500
512
|
toFromNowString(now = new Date()) {
|
|
501
|
-
const msDiff = localTime.
|
|
513
|
+
const msDiff = localTime.fromInput(now).$date.valueOf() - this.$date.valueOf();
|
|
502
514
|
if (msDiff === 0)
|
|
503
515
|
return 'now';
|
|
504
516
|
if (msDiff >= 0) {
|
|
@@ -604,118 +616,198 @@ export class LocalTime {
|
|
|
604
616
|
}
|
|
605
617
|
class LocalTimeFactory {
|
|
606
618
|
/**
|
|
607
|
-
*
|
|
608
|
-
*
|
|
619
|
+
* Creates a LocalTime from the input, unless it's falsy - then returns undefined.
|
|
620
|
+
*
|
|
621
|
+
* `localTime` function will instead return LocalTime of `now` for falsy input.
|
|
609
622
|
*/
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
this.assertNotNull(lt, input);
|
|
613
|
-
return lt;
|
|
623
|
+
orUndefined(input) {
|
|
624
|
+
return input || input === 0 ? this.fromInput(input) : undefined;
|
|
614
625
|
}
|
|
615
|
-
|
|
616
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
|
|
628
|
+
*/
|
|
629
|
+
orNow(input) {
|
|
630
|
+
return input || input === 0 ? this.fromInput(input) : this.now();
|
|
617
631
|
}
|
|
618
|
-
|
|
619
|
-
return new LocalTime(new Date(
|
|
632
|
+
now() {
|
|
633
|
+
return new LocalTime(new Date());
|
|
620
634
|
}
|
|
621
635
|
/**
|
|
622
|
-
|
|
636
|
+
Convenience function to return current Unix timestamp in seconds.
|
|
637
|
+
Like Date.now(), but in seconds.
|
|
623
638
|
*/
|
|
624
|
-
|
|
625
|
-
return
|
|
639
|
+
nowUnix() {
|
|
640
|
+
return Math.floor(Date.now() / 1000);
|
|
626
641
|
}
|
|
627
642
|
/**
|
|
628
|
-
*
|
|
643
|
+
* Create LocalTime from LocalTimeInput.
|
|
644
|
+
* Input can already be a LocalTime - it is returned as-is in that case.
|
|
645
|
+
* Date - will be used as-is.
|
|
646
|
+
* String - will be parsed as strict `yyyy-mm-ddThh:mm:ss`.
|
|
647
|
+
* Number - will be treated as unix timestamp in seconds.
|
|
629
648
|
*/
|
|
630
|
-
|
|
631
|
-
if (
|
|
632
|
-
return
|
|
633
|
-
if (
|
|
634
|
-
return
|
|
635
|
-
}
|
|
636
|
-
if (typeof
|
|
637
|
-
return
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
// This check is after checking the number, to support `0`
|
|
643
|
-
// unexpected type, e.g Function or something
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
fromStringOrNull(s) {
|
|
647
|
-
const date = this.parseStringToDateOrNull(s);
|
|
648
|
-
return date ? new LocalTime(date) : null;
|
|
649
|
-
}
|
|
650
|
-
fromDateTimeObject(input) {
|
|
651
|
-
const { year, month, day = 1, hour = 0, minute = 0, second = 0 } = input;
|
|
652
|
-
return new LocalTime(new Date(year, month - 1, day, hour, minute, second));
|
|
653
|
-
}
|
|
654
|
-
parseStringToDateOrNull(s) {
|
|
655
|
-
if (!s)
|
|
656
|
-
return null;
|
|
657
|
-
// Slicing removes the "timezone component", and makes the date "local"
|
|
658
|
-
// e.g 2022-04-06T23:15:00+09:00
|
|
659
|
-
// becomes 2022-04-06T23:15:00
|
|
660
|
-
// date = new Date(d.slice(0, 19))
|
|
661
|
-
// Parsing is inspired by how Day.js does it
|
|
662
|
-
// Specifically, it ensures that `localTime('2023-03-03')` returns the expected Date, and not a day before
|
|
663
|
-
// Because `new Date('2023-03-03')` in NewYork gives you '2023-03-02 19:00:00 GMT-0500'
|
|
664
|
-
const m = s.match(DATE_TIME_REGEX);
|
|
665
|
-
// Validate in 3 ways:
|
|
666
|
-
// 1. Should match Regex.
|
|
667
|
-
// In some ways it's stricter than Date constructor, e.g it doesn't allow 2023/05/05
|
|
668
|
-
// In other ways it's looser, e.g it allows `2023-05-05T`, while Date constructor doesn't.
|
|
669
|
-
// 2. Date constructor (of Node/v8 implementation, which we know is different from e.g WebKit/Safari)
|
|
670
|
-
// should not return `Invalid Date`.
|
|
671
|
-
// 3. Year, month and day should be valid, e.g 2023-01-32 should not be allowed.
|
|
672
|
-
// UPD: Actually, 3 can be skipped, because 2 is catching it already
|
|
673
|
-
// UPD: 2 is skipped, 1 and 3 are kept
|
|
674
|
-
// if (!m || isNaN(new Date(s).getDate())) return null
|
|
675
|
-
if (!m)
|
|
676
|
-
return null;
|
|
677
|
-
const year = Number(m[1]);
|
|
678
|
-
const month = Number(m[2]);
|
|
679
|
-
const day = Number(m[3]);
|
|
680
|
-
const hour = Number(m[5]);
|
|
681
|
-
const minute = Number(m[6]);
|
|
682
|
-
const second = Number(m[7]);
|
|
683
|
-
// Validation for just the Date part
|
|
684
|
-
if (!year ||
|
|
685
|
-
!month ||
|
|
686
|
-
month < 1 ||
|
|
687
|
-
month > 12 ||
|
|
688
|
-
!day ||
|
|
689
|
-
day < 1 ||
|
|
690
|
-
day > localDate.getMonthLength(year, month)) {
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
// Validation for Date+Time string, since the string is longer than YYYY-MM-DD
|
|
694
|
-
if (s.length > 10 &&
|
|
695
|
-
(isNaN(hour) ||
|
|
696
|
-
isNaN(minute) ||
|
|
697
|
-
isNaN(second) ||
|
|
698
|
-
hour < 0 ||
|
|
699
|
-
hour > 23 ||
|
|
700
|
-
minute < 0 ||
|
|
701
|
-
minute > 59 ||
|
|
702
|
-
second < 0 ||
|
|
703
|
-
second > 59)) {
|
|
704
|
-
return null;
|
|
705
|
-
}
|
|
706
|
-
return new Date(year, month - 1, day, hour || 0, minute || 0, second || 0, 0);
|
|
649
|
+
fromInput(input) {
|
|
650
|
+
if (input instanceof LocalTime)
|
|
651
|
+
return input;
|
|
652
|
+
if (input instanceof Date) {
|
|
653
|
+
return this.fromDate(input);
|
|
654
|
+
}
|
|
655
|
+
if (typeof input === 'number') {
|
|
656
|
+
return this.fromUnix(input);
|
|
657
|
+
}
|
|
658
|
+
// It means it's a string
|
|
659
|
+
// Will parse it STRICTLY
|
|
660
|
+
return this.fromIsoDateTimeString(input);
|
|
707
661
|
}
|
|
662
|
+
/**
|
|
663
|
+
* Returns true if input is valid to create LocalTime.
|
|
664
|
+
*/
|
|
708
665
|
isValid(input) {
|
|
709
|
-
|
|
666
|
+
if (!input)
|
|
667
|
+
return false;
|
|
668
|
+
if (input instanceof LocalTime)
|
|
669
|
+
return true;
|
|
670
|
+
if (input instanceof Date)
|
|
671
|
+
return !isNaN(input.getDate());
|
|
672
|
+
// We currently don't validate Unixtimestamp input, treat it as always valid
|
|
673
|
+
if (typeof input === 'number')
|
|
674
|
+
return true;
|
|
675
|
+
return this.isValidString(input);
|
|
710
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* Returns true if isoString is a valid iso8601 string like `yyyy-mm-ddThh:mm:dd`.
|
|
679
|
+
*/
|
|
711
680
|
isValidString(isoString) {
|
|
712
|
-
return this.
|
|
681
|
+
return !!this.parseStrictlyOrUndefined(isoString);
|
|
713
682
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
683
|
+
/**
|
|
684
|
+
* Tries to convert/parse the input into LocalTime.
|
|
685
|
+
* Uses LOOSE parsing.
|
|
686
|
+
* If invalid - doesn't throw, but returns undefined instead.
|
|
687
|
+
*/
|
|
688
|
+
try(input) {
|
|
689
|
+
if (input instanceof LocalTime)
|
|
690
|
+
return input;
|
|
691
|
+
if (input instanceof Date) {
|
|
692
|
+
if (isNaN(input.getDate()))
|
|
693
|
+
return;
|
|
694
|
+
return new LocalTime(input);
|
|
695
|
+
}
|
|
696
|
+
if (typeof input === 'number') {
|
|
697
|
+
return this.fromUnix(input);
|
|
698
|
+
}
|
|
699
|
+
if (!input)
|
|
700
|
+
return;
|
|
701
|
+
const date = this.parseLooselyOrUndefined(input);
|
|
702
|
+
return date ? new LocalTime(date) : undefined;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Performs STRICT parsing.
|
|
706
|
+
* Only allows IsoDateTimeString or IsoDateString input, nothing else.
|
|
707
|
+
*/
|
|
708
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
|
|
709
|
+
fromIsoDateTimeString(s) {
|
|
710
|
+
const d = this.parseStrictlyOrUndefined(s);
|
|
711
|
+
_assert(d, `Cannot parse "${s}" into LocalTime`);
|
|
712
|
+
return new LocalTime(d);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Performs LOOSE parsing.
|
|
716
|
+
* Tries to coerce imprefect/incorrect string input into IsoDateTimeString.
|
|
717
|
+
* Use with caution.
|
|
718
|
+
* Allows to input IsoDateString, will set h:m:s to zeros.
|
|
719
|
+
*/
|
|
720
|
+
parse(s) {
|
|
721
|
+
const d = this.parseLooselyOrUndefined(String(s));
|
|
722
|
+
_assert(d, `Cannot parse "${s}" into LocalTime`);
|
|
723
|
+
return new LocalTime(d);
|
|
724
|
+
}
|
|
725
|
+
parseStrictlyOrUndefined(s) {
|
|
726
|
+
if (!s || typeof s !== 'string')
|
|
727
|
+
return;
|
|
728
|
+
let m = DATE_TIME_REGEX_STRICT.exec(s);
|
|
729
|
+
if (!m) {
|
|
730
|
+
// DateTime regex didn't match, try just-Date regex
|
|
731
|
+
m = DATE_REGEX_STRICT.exec(s);
|
|
732
|
+
if (!m)
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const o = {
|
|
736
|
+
year: Number(m[1]),
|
|
737
|
+
month: Number(m[2]),
|
|
738
|
+
day: Number(m[3]),
|
|
739
|
+
hour: Number(m[4]) || 0,
|
|
740
|
+
minute: Number(m[5]) || 0,
|
|
741
|
+
second: Number(m[6]) || 0,
|
|
742
|
+
};
|
|
743
|
+
if (!this.isDateTimeObjectValid(o))
|
|
744
|
+
return;
|
|
745
|
+
return this.createDateFromDateTimeObject(o);
|
|
746
|
+
}
|
|
747
|
+
parseLooselyOrUndefined(s) {
|
|
748
|
+
if (!s || typeof s !== 'string')
|
|
749
|
+
return;
|
|
750
|
+
const m = DATE_TIME_REGEX_LOOSE.exec(s);
|
|
751
|
+
if (!m) {
|
|
752
|
+
if (s.length < 8)
|
|
753
|
+
return;
|
|
754
|
+
// Attempt to parse with Date constructor
|
|
755
|
+
const d = new Date(s);
|
|
756
|
+
return isNaN(d.getDate()) ? undefined : d;
|
|
757
|
+
}
|
|
758
|
+
const o = {
|
|
759
|
+
year: Number(m[1]),
|
|
760
|
+
month: Number(m[2]),
|
|
761
|
+
day: Number(m[3]) || 1,
|
|
762
|
+
// [4] is skipped due to extra regex parentheses group
|
|
763
|
+
hour: Number(m[5]) || 0,
|
|
764
|
+
minute: Number(m[6]) || 0,
|
|
765
|
+
second: Number(m[7]) || 0,
|
|
766
|
+
};
|
|
767
|
+
if (!this.isDateTimeObjectValid(o))
|
|
768
|
+
return;
|
|
769
|
+
return this.createDateFromDateTimeObject(o);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Throws on invalid value.
|
|
773
|
+
*/
|
|
774
|
+
validateDateTimeObject(o) {
|
|
775
|
+
_assert(this.isDateTimeObjectValid(o), `Cannot construct LocalTime from: ${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`);
|
|
776
|
+
}
|
|
777
|
+
isDateTimeObjectValid(o) {
|
|
778
|
+
return localDate.isDateObjectValid(o) && this.isTimeObjectValid(o);
|
|
779
|
+
}
|
|
780
|
+
isTimeObjectValid({ hour, minute, second }) {
|
|
781
|
+
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
|
|
782
|
+
}
|
|
783
|
+
fromDate(date) {
|
|
784
|
+
_assert(!isNaN(date.getDate()), `localTime.fromDate is called on Date object that is invalid`);
|
|
785
|
+
return new LocalTime(date);
|
|
786
|
+
}
|
|
787
|
+
fromUnix(ts) {
|
|
788
|
+
return new LocalTime(new Date(ts * 1000));
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
792
|
+
*/
|
|
793
|
+
fromMillis(millis) {
|
|
794
|
+
return new LocalTime(new Date(millis));
|
|
718
795
|
}
|
|
796
|
+
fromDateTimeObject(o) {
|
|
797
|
+
// todo: validate?
|
|
798
|
+
return new LocalTime(this.createDateFromDateTimeObject(o));
|
|
799
|
+
}
|
|
800
|
+
createDateFromDateTimeObject(o) {
|
|
801
|
+
return new Date(o.year, o.month - 1, o.day || 1, o.hour || 0, o.minute || 0, o.second || 0);
|
|
802
|
+
}
|
|
803
|
+
// private assertNotNull(
|
|
804
|
+
// lt: LocalTime | null,
|
|
805
|
+
// input: LocalTimeInputNullable,
|
|
806
|
+
// ): asserts lt is LocalTime {
|
|
807
|
+
// _assert(lt !== null, `Cannot parse "${input}" into LocalTime`, {
|
|
808
|
+
// input,
|
|
809
|
+
// })
|
|
810
|
+
// }
|
|
719
811
|
/**
|
|
720
812
|
* Returns the IANA timezone e.g `Europe/Stockholm`.
|
|
721
813
|
* https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
@@ -733,23 +825,6 @@ class LocalTimeFactory {
|
|
|
733
825
|
isTimezoneValid(tz) {
|
|
734
826
|
return Intl.supportedValuesOf('timeZone').includes(tz);
|
|
735
827
|
}
|
|
736
|
-
now() {
|
|
737
|
-
return new LocalTime(new Date());
|
|
738
|
-
}
|
|
739
|
-
/**
|
|
740
|
-
* Creates a LocalTime from the input, unless it's falsy - then returns undefined.
|
|
741
|
-
*
|
|
742
|
-
* `localTime` function will instead return LocalTime of `now` for falsy input.
|
|
743
|
-
*/
|
|
744
|
-
orUndefined(input) {
|
|
745
|
-
return input || input === 0 ? this.from(input) : undefined;
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
|
|
749
|
-
*/
|
|
750
|
-
orNow(input) {
|
|
751
|
-
return input || input === 0 ? this.from(input) : this.now();
|
|
752
|
-
}
|
|
753
828
|
sort(items, dir = 'asc', mutate = false) {
|
|
754
829
|
const mod = dir === 'desc' ? -1 : 1;
|
|
755
830
|
return (mutate ? items : [...items]).sort((a, b) => {
|
|
@@ -767,7 +842,7 @@ class LocalTimeFactory {
|
|
|
767
842
|
const items2 = items.filter(_isTruthy);
|
|
768
843
|
_assert(items2.length, 'localTime.min called on empty array');
|
|
769
844
|
return items2
|
|
770
|
-
.map(i => this.
|
|
845
|
+
.map(i => this.fromInput(i))
|
|
771
846
|
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
|
|
772
847
|
}
|
|
773
848
|
maxOrUndefined(items) {
|
|
@@ -777,7 +852,7 @@ class LocalTimeFactory {
|
|
|
777
852
|
const items2 = items.filter(_isTruthy);
|
|
778
853
|
_assert(items2.length, 'localTime.max called on empty array');
|
|
779
854
|
return items2
|
|
780
|
-
.map(i => this.
|
|
855
|
+
.map(i => this.fromInput(i))
|
|
781
856
|
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
|
|
782
857
|
}
|
|
783
858
|
}
|
|
@@ -870,14 +945,7 @@ function differenceInMonths(a, b) {
|
|
|
870
945
|
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
|
|
871
946
|
}
|
|
872
947
|
const localTimeFactory = new LocalTimeFactory();
|
|
873
|
-
export const localTime = localTimeFactory.
|
|
948
|
+
export const localTime = localTimeFactory.fromInput.bind(localTimeFactory);
|
|
874
949
|
// The line below is the blackest of black magic I have ever written in 2024.
|
|
875
950
|
// And probably 2023 as well.
|
|
876
951
|
Object.setPrototypeOf(localTime, localTimeFactory);
|
|
877
|
-
/**
|
|
878
|
-
Convenience function to return current Unix timestamp in seconds.
|
|
879
|
-
Like Date.now(), but in seconds.
|
|
880
|
-
*/
|
|
881
|
-
export function nowUnix() {
|
|
882
|
-
return Math.floor(Date.now() / 1000);
|
|
883
|
-
}
|
|
@@ -11,7 +11,7 @@ export class TimeInterval {
|
|
|
11
11
|
this.$end = $end;
|
|
12
12
|
}
|
|
13
13
|
static of(start, end) {
|
|
14
|
-
return new TimeInterval(localTime.
|
|
14
|
+
return new TimeInterval(localTime.fromInput(start).unix, localTime.fromInput(end).unix);
|
|
15
15
|
}
|
|
16
16
|
get start() {
|
|
17
17
|
return this.$start;
|
|
@@ -55,7 +55,7 @@ export class TimeInterval {
|
|
|
55
55
|
return this.cmp(d) >= 0;
|
|
56
56
|
}
|
|
57
57
|
includes(d, incl = '[)') {
|
|
58
|
-
d = localTime.
|
|
58
|
+
d = localTime.fromInput(d).unix;
|
|
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;
|
package/dist-esm/index.js
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
+
export * from './abort';
|
|
1
2
|
export * from './array/array.util';
|
|
2
|
-
export * from './define';
|
|
3
|
-
export * from './string/url.util';
|
|
4
3
|
export * from './array/range';
|
|
4
|
+
export * from './datetime/dateInterval';
|
|
5
|
+
export * from './datetime/localDate';
|
|
6
|
+
export * from './datetime/localTime';
|
|
7
|
+
export * from './datetime/timeInterval';
|
|
8
|
+
export * from './datetime/wallTime';
|
|
9
|
+
export * from './decorators/asyncMemo.decorator';
|
|
5
10
|
export * from './decorators/createPromiseDecorator';
|
|
6
11
|
export * from './decorators/debounce';
|
|
7
12
|
export * from './decorators/debounce.decorator';
|
|
8
13
|
export * from './decorators/decorator.util';
|
|
9
14
|
export * from './decorators/logMethod.decorator';
|
|
10
15
|
export * from './decorators/memo.decorator';
|
|
11
|
-
export * from './decorators/asyncMemo.decorator';
|
|
12
16
|
export * from './decorators/memo.util';
|
|
13
17
|
export * from './decorators/memoFn';
|
|
14
18
|
export * from './decorators/memoFnAsync';
|
|
15
19
|
export * from './decorators/retry.decorator';
|
|
16
20
|
export * from './decorators/timeout.decorator';
|
|
17
|
-
export * from './
|
|
21
|
+
export * from './define';
|
|
18
22
|
export * from './enum.util';
|
|
23
|
+
export * from './env';
|
|
24
|
+
export * from './env/buildInfo';
|
|
25
|
+
export * from './error/assert';
|
|
19
26
|
export * from './error/error.model';
|
|
20
27
|
export * from './error/error.util';
|
|
21
28
|
export * from './error/errorMode';
|
|
22
29
|
export * from './error/try';
|
|
23
30
|
export * from './error/tryCatch';
|
|
31
|
+
export * from './form.util';
|
|
32
|
+
export * from './http/fetcher';
|
|
33
|
+
export * from './http/fetcher.model';
|
|
34
|
+
export * from './http/http.model';
|
|
35
|
+
export * from './is.util';
|
|
36
|
+
export * from './iter/asyncIterable2';
|
|
37
|
+
export * from './iter/iterable2';
|
|
24
38
|
export * from './json-schema/from-data/generateJsonSchemaFromData';
|
|
25
39
|
export * from './json-schema/jsonSchema.cnst';
|
|
26
40
|
export * from './json-schema/jsonSchema.model';
|
|
27
41
|
export * from './json-schema/jsonSchema.util';
|
|
28
42
|
export * from './json-schema/jsonSchemaBuilder';
|
|
43
|
+
export * from './log/commonLogger';
|
|
29
44
|
export * from './math/math.util';
|
|
30
45
|
export * from './math/sma';
|
|
46
|
+
export * from './math/stack.util';
|
|
31
47
|
export * from './number/createDeterministicRandom';
|
|
32
48
|
export * from './number/number.util';
|
|
33
49
|
export * from './object/deepEquals';
|
|
50
|
+
export * from './object/map2';
|
|
34
51
|
export * from './object/object.util';
|
|
52
|
+
export * from './object/set2';
|
|
35
53
|
export * from './object/sortObject';
|
|
36
54
|
export * from './object/sortObjectDeep';
|
|
37
|
-
export * from './
|
|
38
|
-
export * from './
|
|
55
|
+
export * from './polyfill';
|
|
56
|
+
export * from './promise/abortable';
|
|
39
57
|
export * from './promise/pDefer';
|
|
40
58
|
export * from './promise/pDelay';
|
|
41
59
|
export * from './promise/pFilter';
|
|
42
60
|
export * from './promise/pHang';
|
|
43
61
|
export * from './promise/pMap';
|
|
44
62
|
export * from './promise/pProps';
|
|
63
|
+
export * from './promise/pQueue';
|
|
45
64
|
export * from './promise/pRetry';
|
|
46
65
|
export * from './promise/pState';
|
|
47
66
|
export * from './promise/pTimeout';
|
|
67
|
+
export * from './semver';
|
|
48
68
|
export * from './string/case';
|
|
49
|
-
export * from './string/json.util';
|
|
50
|
-
export * from './string/string.util';
|
|
51
|
-
export * from './string/readingTime';
|
|
52
69
|
export * from './string/escape';
|
|
70
|
+
export * from './string/hash.util';
|
|
71
|
+
export * from './string/json.util';
|
|
72
|
+
export * from './string/leven';
|
|
53
73
|
export * from './string/pupa';
|
|
74
|
+
export * from './string/readingTime';
|
|
75
|
+
export * from './string/regex';
|
|
76
|
+
export * from './string/safeJsonStringify';
|
|
77
|
+
export * from './string/string.util';
|
|
54
78
|
export * from './string/stringify';
|
|
79
|
+
export * from './string/url.util';
|
|
55
80
|
export * from './time/time.util';
|
|
56
|
-
export * from './is.util';
|
|
57
81
|
export * from './typeFest';
|
|
58
82
|
export * from './types';
|
|
59
83
|
export * from './unit/size.util';
|
|
60
|
-
export * from './log/commonLogger';
|
|
61
|
-
export * from './string/safeJsonStringify';
|
|
62
|
-
export * from './promise/pQueue';
|
|
63
|
-
export * from './promise/abortable';
|
|
64
|
-
export * from './iter/iterable2';
|
|
65
|
-
export * from './iter/asyncIterable2';
|
|
66
|
-
export * from './math/stack.util';
|
|
67
|
-
export * from './string/leven';
|
|
68
|
-
export * from './datetime/localDate';
|
|
69
|
-
export * from './datetime/localTime';
|
|
70
|
-
export * from './datetime/wallTime';
|
|
71
|
-
export * from './datetime/dateInterval';
|
|
72
|
-
export * from './datetime/timeInterval';
|
|
73
|
-
export * from './env';
|
|
74
|
-
export * from './http/http.model';
|
|
75
|
-
export * from './http/fetcher';
|
|
76
|
-
export * from './http/fetcher.model';
|
|
77
|
-
export * from './string/hash.util';
|
|
78
|
-
export * from './env/buildInfo';
|
|
79
|
-
export * from './form.util';
|
|
80
|
-
export * from './semver';
|
|
81
84
|
export * from './web';
|
|
82
|
-
export * from './abort';
|
|
83
|
-
export * from './polyfill';
|
|
84
|
-
export * from './string/regex';
|
|
85
|
-
export * from './zod/zod.util';
|
|
86
85
|
export * from './zod/zod.shared.schemas';
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
export * from './zod/zod.util';
|
|
87
|
+
import { z, ZodError, ZodSchema } from 'zod';
|
|
88
|
+
export { z, ZodError, ZodSchema };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _uniq } from '../array/array.util';
|
|
2
|
-
import {
|
|
2
|
+
import { _deepCopy, _sortObject, mergeJsonSchemaObjects } from '../index';
|
|
3
3
|
import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst';
|
|
4
4
|
/**
|
|
5
5
|
* Fluent (chainable) API to manually create Json Schemas.
|
|
@@ -35,8 +35,10 @@ export function _ms(millis) {
|
|
|
35
35
|
if (millis < 1000)
|
|
36
36
|
return `${Math.round(millis)} ms`;
|
|
37
37
|
// < 5 sec
|
|
38
|
-
if (millis < 5000)
|
|
39
|
-
|
|
38
|
+
if (millis < 5000) {
|
|
39
|
+
const s = millis / 1000;
|
|
40
|
+
return `${Math.trunc(s) === s ? s : s.toFixed(3)} sec`;
|
|
41
|
+
}
|
|
40
42
|
const sec = Math.floor(millis / 1000) % 60;
|
|
41
43
|
const min = Math.floor(millis / (60 * 1000)) % 60;
|
|
42
44
|
const hrs = Math.floor(millis / (3600 * 1000));
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Inclusiveness } from '../types'
|
|
2
|
-
import { localDate, LocalDateInput, LocalDateUnit
|
|
2
|
+
import { LocalDate, localDate, LocalDateInput, LocalDateUnit } from './localDate'
|
|
3
3
|
|
|
4
4
|
export type DateIntervalConfig = DateInterval | DateIntervalString
|
|
5
5
|
export type DateIntervalString = string
|