@naturalcycles/js-lib 14.243.1 → 14.245.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.
Files changed (42) hide show
  1. package/dist/datetime/dateInterval.d.ts +1 -1
  2. package/dist/datetime/dateInterval.js +1 -1
  3. package/dist/datetime/localDate.d.ts +75 -51
  4. package/dist/datetime/localDate.js +256 -200
  5. package/dist/datetime/localTime.d.ts +88 -56
  6. package/dist/datetime/localTime.js +277 -176
  7. package/dist/datetime/timeInterval.d.ts +2 -2
  8. package/dist/datetime/timeInterval.js +2 -2
  9. package/dist/env/buildInfo.js +2 -2
  10. package/dist/error/error.util.d.ts +1 -1
  11. package/dist/index.d.ts +37 -37
  12. package/dist/index.js +37 -37
  13. package/dist/json-schema/from-data/generateJsonSchemaFromData.d.ts +1 -1
  14. package/dist/json-schema/jsonSchemaBuilder.d.ts +1 -1
  15. package/dist/object/object.util.d.ts +1 -1
  16. package/dist/time/time.util.js +4 -2
  17. package/dist/zod/zod.util.d.ts +1 -1
  18. package/dist-esm/datetime/dateInterval.js +1 -1
  19. package/dist-esm/datetime/localDate.js +256 -199
  20. package/dist-esm/datetime/localTime.js +277 -175
  21. package/dist-esm/datetime/timeInterval.js +2 -2
  22. package/dist-esm/decorators/logMethod.decorator.js +1 -1
  23. package/dist-esm/env/buildInfo.js +2 -2
  24. package/dist-esm/index.js +37 -37
  25. package/dist-esm/json-schema/jsonSchemaBuilder.js +1 -1
  26. package/dist-esm/time/time.util.js +4 -2
  27. package/package.json +1 -1
  28. package/src/datetime/dateInterval.ts +2 -2
  29. package/src/datetime/localDate.ts +259 -215
  30. package/src/datetime/localTime.ts +277 -209
  31. package/src/datetime/timeInterval.ts +4 -4
  32. package/src/decorators/logMethod.decorator.ts +1 -1
  33. package/src/define.ts +1 -1
  34. package/src/env/buildInfo.ts +2 -2
  35. package/src/error/error.util.ts +3 -3
  36. package/src/http/fetcher.ts +1 -1
  37. package/src/index.ts +37 -37
  38. package/src/json-schema/from-data/generateJsonSchemaFromData.ts +1 -1
  39. package/src/json-schema/jsonSchemaBuilder.ts +2 -2
  40. package/src/object/object.util.ts +1 -1
  41. package/src/time/time.util.ts +4 -1
  42. package/src/zod/zod.util.ts +1 -1
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.localTime = exports.LocalTime = exports.ISODayOfWeek = void 0;
4
- exports.nowUnix = nowUnix;
5
4
  const assert_1 = require("../error/assert");
6
5
  const is_util_1 = require("../is.util");
7
6
  const time_util_1 = require("../time/time.util");
@@ -23,10 +22,22 @@ const SECONDS_IN_DAY = 86400;
23
22
  // const MILLISECONDS_IN_DAY = 86400000
24
23
  // const MILLISECONDS_IN_MINUTE = 60000
25
24
  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}))?/;
25
+ /**
26
+ * It supports 2 forms:
27
+ * 1. 2023-03-03
28
+ * 2. 2023-03-03T05:10:02
29
+ * // todo: make it even looser, like Day.js
30
+ */
31
+ const DATE_TIME_REGEX_LOOSE = /^(\d{4})-(\d{2})-(\d{2})([Tt\s](\d{2}):?(\d{2})?:?(\d{2})?)?/;
32
+ /**
33
+ * Supports 2 forms:
34
+ * 1. 2023-03-03
35
+ * 2. 2023-03-03T05:10:02
36
+ * Ok, now it allows arbitrary stuff after `:ss`, to allow millis/timezone info,
37
+ * but it will not take it into account.
38
+ */
39
+ const DATE_TIME_REGEX_STRICT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/;
40
+ const DATE_REGEX_STRICT = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
30
41
  class LocalTime {
31
42
  constructor($date) {
32
43
  this.$date = $date;
@@ -35,14 +46,14 @@ class LocalTime {
35
46
  * Returns [cloned] LocalTime that is based on the same unixtimestamp, but in UTC timezone.
36
47
  * Opposite of `.local()` method.
37
48
  */
38
- utc() {
49
+ toUTC() {
39
50
  return new LocalTime(new Date(this.$date.toISOString()));
40
51
  }
41
52
  /**
42
53
  * Returns [cloned] LocalTime that is based on the same unixtimestamp, but in local timezone.
43
54
  * Opposite of `.utc()` method.
44
55
  */
45
- local() {
56
+ toLocal() {
46
57
  return new LocalTime(new Date(this.$date.getTime()));
47
58
  }
48
59
  /**
@@ -164,34 +175,58 @@ class LocalTime {
164
175
  }
165
176
  return t;
166
177
  }
167
- year(v) {
168
- return v === undefined ? this.get('year') : this.set('year', v);
178
+ get year() {
179
+ return this.$date.getFullYear();
169
180
  }
170
- month(v) {
171
- return v === undefined ? this.get('month') : this.set('month', v);
181
+ setYear(v) {
182
+ return this.set('year', v);
172
183
  }
173
- week(v) {
174
- return v === undefined ? getWeek(this.$date) : this.set('week', v);
184
+ get month() {
185
+ return this.$date.getMonth() + 1;
175
186
  }
176
- day(v) {
177
- return v === undefined ? this.get('day') : this.set('day', v);
187
+ setMonth(v) {
188
+ return this.set('month', v);
178
189
  }
179
- dayOfWeek(v) {
180
- const dow = (this.$date.getDay() || 7);
181
- if (v === undefined) {
182
- return dow;
183
- }
184
- (0, assert_1._assert)(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`);
185
- return this.plus(v - dow, 'day');
190
+ get week() {
191
+ return getWeek(this.$date);
192
+ }
193
+ setWeek(v) {
194
+ return this.set('week', v);
195
+ }
196
+ get day() {
197
+ return this.$date.getDate();
198
+ }
199
+ setDay(v) {
200
+ return this.set('day', v);
201
+ }
202
+ get hour() {
203
+ return this.$date.getHours();
186
204
  }
187
- hour(v) {
188
- return v === undefined ? this.get('hour') : this.set('hour', v);
205
+ setHour(v) {
206
+ return this.set('hour', v);
189
207
  }
190
- minute(v) {
191
- return v === undefined ? this.get('minute') : this.set('minute', v);
208
+ get minute() {
209
+ return this.$date.getMinutes();
192
210
  }
193
- second(v) {
194
- return v === undefined ? this.get('second') : this.set('second', v);
211
+ setMinute(v) {
212
+ return this.set('minute', v);
213
+ }
214
+ get second() {
215
+ return this.$date.getSeconds();
216
+ }
217
+ setSecond(v) {
218
+ return this.set('second', v);
219
+ }
220
+ /**
221
+ * Based on ISO: 1-7 is Mon-Sun.
222
+ */
223
+ get dayOfWeek() {
224
+ return (this.$date.getDay() || 7);
225
+ }
226
+ setDayOfWeek(v) {
227
+ (0, assert_1._assert)(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`);
228
+ const dow = this.$date.getDay() || 7;
229
+ return this.plus(v - dow, 'day');
195
230
  }
196
231
  setComponents(c, mutate = false) {
197
232
  const d = mutate ? this.$date : new Date(this.$date);
@@ -259,7 +294,7 @@ class LocalTime {
259
294
  }
260
295
  if (unit === 'year' || unit === 'month') {
261
296
  const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
262
- return mutate ? this : exports.localTime.of(d);
297
+ return mutate ? this : exports.localTime.fromInput(d);
263
298
  }
264
299
  return this.set(unit, this.get(unit) + num, mutate);
265
300
  }
@@ -270,7 +305,7 @@ class LocalTime {
270
305
  return Math.abs(this.diff(other, unit));
271
306
  }
272
307
  diff(other, unit) {
273
- const date2 = exports.localTime.of(other).$date;
308
+ const date2 = exports.localTime.fromInput(other).$date;
274
309
  const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
275
310
  if (!secDiff)
276
311
  return 0;
@@ -358,32 +393,32 @@ class LocalTime {
358
393
  * Returns how many days are in the current month.
359
394
  * E.g 31 for January.
360
395
  */
361
- daysInMonth() {
396
+ get daysInMonth() {
362
397
  return localDate_1.localDate.getMonthLength(this.$date.getFullYear(), this.$date.getMonth() + 1);
363
398
  }
364
399
  isSame(d) {
365
- return this.cmp(d) === 0;
400
+ return this.compare(d) === 0;
366
401
  }
367
402
  isBefore(d, inclusive = false) {
368
- const r = this.cmp(d);
403
+ const r = this.compare(d);
369
404
  return r === -1 || (r === 0 && inclusive);
370
405
  }
371
406
  isSameOrBefore(d) {
372
- return this.cmp(d) <= 0;
407
+ return this.compare(d) <= 0;
373
408
  }
374
409
  isAfter(d, inclusive = false) {
375
- const r = this.cmp(d);
410
+ const r = this.compare(d);
376
411
  return r === 1 || (r === 0 && inclusive);
377
412
  }
378
413
  isSameOrAfter(d) {
379
- return this.cmp(d) >= 0;
414
+ return this.compare(d) >= 0;
380
415
  }
381
416
  isBetween(min, max, incl = '[)') {
382
- let r = this.cmp(min);
417
+ let r = this.compare(min);
383
418
  // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
384
419
  if (r < 0 || (r === 0 && incl[0] === '('))
385
420
  return false;
386
- r = this.cmp(max);
421
+ r = this.compare(max);
387
422
  if (r > 0 || (r === 0 && incl[1] === ')'))
388
423
  return false;
389
424
  return true;
@@ -398,13 +433,13 @@ class LocalTime {
398
433
  * Third argument allows to override "now".
399
434
  */
400
435
  isOlderThan(n, unit, now) {
401
- return this.isBefore(exports.localTime.of(now ?? new Date()).plus(-n, unit));
436
+ return this.isBefore(exports.localTime.fromInput(now ?? new Date()).plus(-n, unit));
402
437
  }
403
438
  /**
404
439
  * Checks if this localTime is same or older (<=) than "now" by X units.
405
440
  */
406
441
  isSameOrOlderThan(n, unit, now) {
407
- return this.isSameOrBefore(exports.localTime.of(now ?? new Date()).plus(-n, unit));
442
+ return this.isSameOrBefore(exports.localTime.fromInput(now ?? new Date()).plus(-n, unit));
408
443
  }
409
444
  /**
410
445
  * Checks if this localTime is younger (>) than "now" by X units.
@@ -416,13 +451,13 @@ class LocalTime {
416
451
  * Third argument allows to override "now".
417
452
  */
418
453
  isYoungerThan(n, unit, now) {
419
- return this.isAfter(exports.localTime.of(now ?? new Date()).plus(-n, unit));
454
+ return this.isAfter(exports.localTime.fromInput(now ?? new Date()).plus(-n, unit));
420
455
  }
421
456
  /**
422
457
  * Checks if this localTime is same or younger (>=) than "now" by X units.
423
458
  */
424
459
  isSameOrYoungerThan(n, unit, now) {
425
- return this.isSameOrAfter(exports.localTime.of(now ?? new Date()).plus(-n, unit));
460
+ return this.isSameOrAfter(exports.localTime.fromInput(now ?? new Date()).plus(-n, unit));
426
461
  }
427
462
  getAgeInYears(now) {
428
463
  return this.getAgeIn('year', now);
@@ -443,42 +478,42 @@ class LocalTime {
443
478
  return this.getAgeIn('second', now);
444
479
  }
445
480
  getAgeIn(unit, now) {
446
- return exports.localTime.of(now ?? new Date()).diff(this, unit);
481
+ return exports.localTime.fromInput(now ?? new Date()).diff(this, unit);
447
482
  }
448
483
  /**
449
484
  * Returns 1 if this > d
450
485
  * returns 0 if they are equal
451
486
  * returns -1 if this < d
452
487
  */
453
- cmp(d) {
488
+ compare(d) {
454
489
  const t1 = this.$date.valueOf();
455
- const t2 = exports.localTime.of(d).$date.valueOf();
490
+ const t2 = exports.localTime.fromInput(d).$date.valueOf();
456
491
  if (t1 === t2)
457
492
  return 0;
458
493
  return t1 < t2 ? -1 : 1;
459
494
  }
460
- getDateTimeObject() {
495
+ toDateTimeObject() {
461
496
  return {
462
- ...this.getDateObject(),
463
- ...this.getTimeObject(),
497
+ ...this.toDateObject(),
498
+ ...this.toTimeObject(),
464
499
  };
465
500
  }
466
- getDateObject() {
501
+ toDateObject() {
467
502
  return {
468
503
  year: this.$date.getFullYear(),
469
504
  month: this.$date.getMonth() + 1,
470
505
  day: this.$date.getDate(),
471
506
  };
472
507
  }
473
- getTimeObject() {
508
+ toTimeObject() {
474
509
  return {
475
510
  hour: this.$date.getHours(),
476
511
  minute: this.$date.getMinutes(),
477
512
  second: this.$date.getSeconds(),
478
513
  };
479
514
  }
480
- fromNow(now = new Date()) {
481
- const msDiff = exports.localTime.of(now).$date.valueOf() - this.$date.valueOf();
515
+ toFromNowString(now = new Date()) {
516
+ const msDiff = exports.localTime.fromInput(now).$date.valueOf() - this.$date.valueOf();
482
517
  if (msDiff === 0)
483
518
  return 'now';
484
519
  if (msDiff >= 0) {
@@ -486,16 +521,16 @@ class LocalTime {
486
521
  }
487
522
  return `in ${(0, time_util_1._ms)(msDiff * -1)}`;
488
523
  }
489
- getDate() {
524
+ toDate() {
490
525
  return this.$date;
491
526
  }
492
527
  clone() {
493
528
  return new LocalTime(new Date(this.$date));
494
529
  }
495
- unix() {
530
+ get unix() {
496
531
  return Math.floor(this.$date.valueOf() / 1000);
497
532
  }
498
- unixMillis() {
533
+ get unixMillis() {
499
534
  return this.$date.valueOf();
500
535
  }
501
536
  valueOf() {
@@ -527,7 +562,7 @@ class LocalTime {
527
562
  * Returns e.g: `1984-06-21`, only the date part of DateTime
528
563
  */
529
564
  toISODate() {
530
- const { year, month, day } = this.getDateObject();
565
+ const { year, month, day } = this.toDateObject();
531
566
  return [
532
567
  String(year).padStart(4, '0'),
533
568
  String(month).padStart(2, '0'),
@@ -540,7 +575,7 @@ class LocalTime {
540
575
  * Returns e.g: `17:03:15` (or `17:03` with seconds=false)
541
576
  */
542
577
  toISOTime(seconds = true) {
543
- const { hour, minute, second } = this.getTimeObject();
578
+ const { hour, minute, second } = this.toTimeObject();
544
579
  return [
545
580
  String(hour).padStart(2, '0'),
546
581
  String(minute).padStart(2, '0'),
@@ -555,7 +590,7 @@ class LocalTime {
555
590
  * Returns e.g: `19840621_1705`
556
591
  */
557
592
  toStringCompact(seconds = false) {
558
- const { year, month, day, hour, minute, second } = this.getDateTimeObject();
593
+ const { year, month, day, hour, minute, second } = this.toDateTimeObject();
559
594
  return [
560
595
  String(year).padStart(4, '0'),
561
596
  String(month).padStart(2, '0'),
@@ -570,7 +605,7 @@ class LocalTime {
570
605
  return this.toISODateTime();
571
606
  }
572
607
  toJSON() {
573
- return this.unix();
608
+ return this.unix;
574
609
  }
575
610
  toMonthId() {
576
611
  return this.toISODate().slice(0, 7);
@@ -585,105 +620,198 @@ class LocalTime {
585
620
  exports.LocalTime = LocalTime;
586
621
  class LocalTimeFactory {
587
622
  /**
588
- * Parses input String into LocalDate.
589
- * Input can already be a LocalDate - it is returned as-is in that case.
623
+ * Creates a LocalTime from the input, unless it's falsy - then returns undefined.
624
+ *
625
+ * `localTime` function will instead return LocalTime of `now` for falsy input.
590
626
  */
591
- of(d) {
592
- const t = this.parseOrNull(d);
593
- (0, assert_1._assert)(t !== null, `Cannot parse "${d}" into LocalTime`, {
594
- input: d,
595
- });
596
- return t;
627
+ orUndefined(input) {
628
+ return input || input === 0 ? this.fromInput(input) : undefined;
597
629
  }
598
630
  /**
599
- * Create LocalTime from unixTimestamp in milliseconds (not in seconds).
631
+ * Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
600
632
  */
601
- ofMillis(millis) {
602
- return this.of(new Date(millis));
633
+ orNow(input) {
634
+ return input || input === 0 ? this.fromInput(input) : this.now();
635
+ }
636
+ now() {
637
+ return new LocalTime(new Date());
603
638
  }
604
639
  /**
605
- * Returns null if invalid
640
+ Convenience function to return current Unix timestamp in seconds.
641
+ Like Date.now(), but in seconds.
606
642
  */
607
- parseOrNull(d) {
608
- if (d instanceof LocalTime)
609
- return d;
610
- let date;
611
- if (d instanceof Date) {
612
- date = d;
613
- }
614
- else if (typeof d === 'number') {
615
- date = new Date(d * 1000);
616
- }
617
- else if (!d) {
618
- // This check is after checking the number, to support `0`
619
- return null;
620
- }
621
- else if (typeof d !== 'string') {
622
- // unexpected type, e.g Function or something
623
- return null;
643
+ nowUnix() {
644
+ return Math.floor(Date.now() / 1000);
645
+ }
646
+ /**
647
+ * Create LocalTime from LocalTimeInput.
648
+ * Input can already be a LocalTime - it is returned as-is in that case.
649
+ * Date - will be used as-is.
650
+ * String - will be parsed as strict `yyyy-mm-ddThh:mm:ss`.
651
+ * Number - will be treated as unix timestamp in seconds.
652
+ */
653
+ fromInput(input) {
654
+ if (input instanceof LocalTime)
655
+ return input;
656
+ if (input instanceof Date) {
657
+ return this.fromDate(input);
624
658
  }
625
- else {
626
- date = this.parseStringToDateOrNull(d);
627
- if (date === null)
628
- return null;
659
+ if (typeof input === 'number') {
660
+ return this.fromUnix(input);
629
661
  }
662
+ // It means it's a string
663
+ // Will parse it STRICTLY
664
+ return this.fromIsoDateTimeString(input);
665
+ }
666
+ /**
667
+ * Returns true if input is valid to create LocalTime.
668
+ */
669
+ isValid(input) {
670
+ if (!input)
671
+ return false;
672
+ if (input instanceof LocalTime)
673
+ return true;
674
+ if (input instanceof Date)
675
+ return !isNaN(input.getDate());
676
+ // We currently don't validate Unixtimestamp input, treat it as always valid
677
+ if (typeof input === 'number')
678
+ return true;
679
+ return this.isValidString(input);
680
+ }
681
+ /**
682
+ * Returns true if isoString is a valid iso8601 string like `yyyy-mm-ddThh:mm:dd`.
683
+ */
684
+ isValidString(isoString) {
685
+ return !!this.parseStrictlyOrUndefined(isoString);
686
+ }
687
+ /**
688
+ * Tries to convert/parse the input into LocalTime.
689
+ * Uses LOOSE parsing.
690
+ * If invalid - doesn't throw, but returns undefined instead.
691
+ */
692
+ try(input) {
693
+ if (input instanceof LocalTime)
694
+ return input;
695
+ if (input instanceof Date) {
696
+ if (isNaN(input.getDate()))
697
+ return;
698
+ return new LocalTime(input);
699
+ }
700
+ if (typeof input === 'number') {
701
+ return this.fromUnix(input);
702
+ }
703
+ if (!input)
704
+ return;
705
+ const date = this.parseLooselyOrUndefined(input);
706
+ return date ? new LocalTime(date) : undefined;
707
+ }
708
+ /**
709
+ * Performs STRICT parsing.
710
+ * Only allows IsoDateTimeString or IsoDateString input, nothing else.
711
+ */
712
+ // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
713
+ fromIsoDateTimeString(s) {
714
+ const d = this.parseStrictlyOrUndefined(s);
715
+ (0, assert_1._assert)(d, `Cannot parse "${s}" into LocalTime`);
716
+ return new LocalTime(d);
717
+ }
718
+ /**
719
+ * Performs LOOSE parsing.
720
+ * Tries to coerce imprefect/incorrect string input into IsoDateTimeString.
721
+ * Use with caution.
722
+ * Allows to input IsoDateString, will set h:m:s to zeros.
723
+ */
724
+ parse(s) {
725
+ const d = this.parseLooselyOrUndefined(String(s));
726
+ (0, assert_1._assert)(d, `Cannot parse "${s}" into LocalTime`);
727
+ return new LocalTime(d);
728
+ }
729
+ parseStrictlyOrUndefined(s) {
730
+ if (!s || typeof s !== 'string')
731
+ return;
732
+ let m = DATE_TIME_REGEX_STRICT.exec(s);
733
+ if (!m) {
734
+ // DateTime regex didn't match, try just-Date regex
735
+ m = DATE_REGEX_STRICT.exec(s);
736
+ if (!m)
737
+ return;
738
+ }
739
+ const o = {
740
+ year: Number(m[1]),
741
+ month: Number(m[2]),
742
+ day: Number(m[3]),
743
+ hour: Number(m[4]) || 0,
744
+ minute: Number(m[5]) || 0,
745
+ second: Number(m[6]) || 0,
746
+ };
747
+ if (!this.isDateTimeObjectValid(o))
748
+ return;
749
+ return this.createDateFromDateTimeObject(o);
750
+ }
751
+ parseLooselyOrUndefined(s) {
752
+ if (!s || typeof s !== 'string')
753
+ return;
754
+ const m = DATE_TIME_REGEX_LOOSE.exec(s);
755
+ if (!m) {
756
+ if (s.length < 8)
757
+ return;
758
+ // Attempt to parse with Date constructor
759
+ const d = new Date(s);
760
+ return isNaN(d.getDate()) ? undefined : d;
761
+ }
762
+ const o = {
763
+ year: Number(m[1]),
764
+ month: Number(m[2]),
765
+ day: Number(m[3]) || 1,
766
+ // [4] is skipped due to extra regex parentheses group
767
+ hour: Number(m[5]) || 0,
768
+ minute: Number(m[6]) || 0,
769
+ second: Number(m[7]) || 0,
770
+ };
771
+ if (!this.isDateTimeObjectValid(o))
772
+ return;
773
+ return this.createDateFromDateTimeObject(o);
774
+ }
775
+ /**
776
+ * Throws on invalid value.
777
+ */
778
+ validateDateTimeObject(o) {
779
+ (0, assert_1._assert)(this.isDateTimeObjectValid(o), `Cannot construct LocalTime from: ${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`);
780
+ }
781
+ isDateTimeObjectValid(o) {
782
+ return localDate_1.localDate.isDateObjectValid(o) && this.isTimeObjectValid(o);
783
+ }
784
+ isTimeObjectValid({ hour, minute, second }) {
785
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
786
+ }
787
+ fromDate(date) {
788
+ (0, assert_1._assert)(!isNaN(date.getDate()), `localTime.fromDate is called on Date object that is invalid`);
630
789
  return new LocalTime(date);
631
790
  }
632
- parseStringToDateOrNull(s) {
633
- // Slicing removes the "timezone component", and makes the date "local"
634
- // e.g 2022-04-06T23:15:00+09:00
635
- // becomes 2022-04-06T23:15:00
636
- // date = new Date(d.slice(0, 19))
637
- // Parsing is inspired by how Day.js does it
638
- // Specifically, it ensures that `localTime('2023-03-03')` returns the expected Date, and not a day before
639
- // Because `new Date('2023-03-03')` in NewYork gives you '2023-03-02 19:00:00 GMT-0500'
640
- const m = s.match(DATE_TIME_REGEX);
641
- // Validate in 3 ways:
642
- // 1. Should match Regex.
643
- // In some ways it's stricter than Date constructor, e.g it doesn't allow 2023/05/05
644
- // In other ways it's looser, e.g it allows `2023-05-05T`, while Date constructor doesn't.
645
- // 2. Date constructor (of Node/v8 implementation, which we know is different from e.g WebKit/Safari)
646
- // should not return `Invalid Date`.
647
- // 3. Year, month and day should be valid, e.g 2023-01-32 should not be allowed.
648
- // UPD: Actually, 3 can be skipped, because 2 is catching it already
649
- // UPD: 2 is skipped, 1 and 3 are kept
650
- // if (!m || isNaN(new Date(s).getDate())) return null
651
- if (!m)
652
- return null;
653
- const year = Number(m[1]);
654
- const month = Number(m[2]);
655
- const day = Number(m[3]);
656
- const hour = Number(m[5]);
657
- const minute = Number(m[6]);
658
- const second = Number(m[7]);
659
- // Validation for just the Date part
660
- if (!year ||
661
- !month ||
662
- month < 1 ||
663
- month > 12 ||
664
- !day ||
665
- day < 1 ||
666
- day > localDate_1.localDate.getMonthLength(year, month)) {
667
- return null;
668
- }
669
- // Validation for Date+Time string, since the string is longer than YYYY-MM-DD
670
- if (s.length > 10 &&
671
- (isNaN(hour) ||
672
- isNaN(minute) ||
673
- isNaN(second) ||
674
- hour < 0 ||
675
- hour > 23 ||
676
- minute < 0 ||
677
- minute > 59 ||
678
- second < 0 ||
679
- second > 59)) {
680
- return null;
681
- }
682
- return new Date(year, month - 1, day, hour || 0, minute || 0, second || 0, 0);
683
- }
684
- isValid(d) {
685
- return this.parseOrNull(d) !== null;
791
+ fromUnix(ts) {
792
+ return new LocalTime(new Date(ts * 1000));
686
793
  }
794
+ /**
795
+ * Create LocalTime from unixTimestamp in milliseconds (not in seconds).
796
+ */
797
+ fromMillis(millis) {
798
+ return new LocalTime(new Date(millis));
799
+ }
800
+ fromDateTimeObject(o) {
801
+ // todo: validate?
802
+ return new LocalTime(this.createDateFromDateTimeObject(o));
803
+ }
804
+ createDateFromDateTimeObject(o) {
805
+ return new Date(o.year, o.month - 1, o.day || 1, o.hour || 0, o.minute || 0, o.second || 0);
806
+ }
807
+ // private assertNotNull(
808
+ // lt: LocalTime | null,
809
+ // input: LocalTimeInputNullable,
810
+ // ): asserts lt is LocalTime {
811
+ // _assert(lt !== null, `Cannot parse "${input}" into LocalTime`, {
812
+ // input,
813
+ // })
814
+ // }
687
815
  /**
688
816
  * Returns the IANA timezone e.g `Europe/Stockholm`.
689
817
  * https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
@@ -701,26 +829,6 @@ class LocalTimeFactory {
701
829
  isTimezoneValid(tz) {
702
830
  return Intl.supportedValuesOf('timeZone').includes(tz);
703
831
  }
704
- now() {
705
- return new LocalTime(new Date());
706
- }
707
- /**
708
- * Creates a LocalTime from the input, unless it's falsy - then returns undefined.
709
- *
710
- * `localTime` function will instead return LocalTime of `now` for falsy input.
711
- */
712
- orUndefined(d) {
713
- return d ? this.of(d) : undefined;
714
- }
715
- /**
716
- * Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
717
- */
718
- orNow(d) {
719
- return d ? this.of(d) : this.now();
720
- }
721
- fromComponents(c) {
722
- return new LocalTime(new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0));
723
- }
724
832
  sort(items, dir = 'asc', mutate = false) {
725
833
  const mod = dir === 'desc' ? -1 : 1;
726
834
  return (mutate ? items : [...items]).sort((a, b) => {
@@ -738,7 +846,7 @@ class LocalTimeFactory {
738
846
  const items2 = items.filter(is_util_1._isTruthy);
739
847
  (0, assert_1._assert)(items2.length, 'localTime.min called on empty array');
740
848
  return items2
741
- .map(i => this.of(i))
849
+ .map(i => this.fromInput(i))
742
850
  .reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
743
851
  }
744
852
  maxOrUndefined(items) {
@@ -748,7 +856,7 @@ class LocalTimeFactory {
748
856
  const items2 = items.filter(is_util_1._isTruthy);
749
857
  (0, assert_1._assert)(items2.length, 'localTime.max called on empty array');
750
858
  return items2
751
- .map(i => this.of(i))
859
+ .map(i => this.fromInput(i))
752
860
  .reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
753
861
  }
754
862
  }
@@ -841,14 +949,7 @@ function differenceInMonths(a, b) {
841
949
  return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
842
950
  }
843
951
  const localTimeFactory = new LocalTimeFactory();
844
- exports.localTime = localTimeFactory.of.bind(localTimeFactory);
952
+ exports.localTime = localTimeFactory.fromInput.bind(localTimeFactory);
845
953
  // The line below is the blackest of black magic I have ever written in 2024.
846
954
  // And probably 2023 as well.
847
955
  Object.setPrototypeOf(exports.localTime, localTimeFactory);
848
- /**
849
- Convenience function to return current Unix timestamp in seconds.
850
- Like Date.now(), but in seconds.
851
- */
852
- function nowUnix() {
853
- return Math.floor(Date.now() / 1000);
854
- }
@@ -1,5 +1,5 @@
1
- import type { UnixTimestampNumber, Inclusiveness } from '../types';
2
- import { LocalTimeInput, LocalTime } from './localTime';
1
+ import type { Inclusiveness, UnixTimestampNumber } from '../types';
2
+ import { LocalTime, LocalTimeInput } from './localTime';
3
3
  export type TimeIntervalConfig = TimeInterval | TimeIntervalString;
4
4
  export type TimeIntervalString = string;
5
5
  /**