@naturalcycles/js-lib 14.243.1 → 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.
@@ -32,6 +32,7 @@ export type LocalTimeInputNullable = LocalTimeInput | null | undefined
32
32
  export type LocalTimeFormatter = (ld: LocalTime) => string
33
33
 
34
34
  export type DateTimeObject = DateObject & TimeObject
35
+ export type DateTimeObjectInput = DateObject & Partial<TimeObject>
35
36
 
36
37
  export interface DateObject {
37
38
  year: number
@@ -63,7 +64,7 @@ export class LocalTime {
63
64
  * Returns [cloned] LocalTime that is based on the same unixtimestamp, but in UTC timezone.
64
65
  * Opposite of `.local()` method.
65
66
  */
66
- utc(): LocalTime {
67
+ toUTC(): LocalTime {
67
68
  return new LocalTime(new Date(this.$date.toISOString()))
68
69
  }
69
70
 
@@ -71,7 +72,7 @@ export class LocalTime {
71
72
  * Returns [cloned] LocalTime that is based on the same unixtimestamp, but in local timezone.
72
73
  * Opposite of `.utc()` method.
73
74
  */
74
- local(): LocalTime {
75
+ toLocal(): LocalTime {
75
76
  return new LocalTime(new Date(this.$date.getTime()))
76
77
  }
77
78
 
@@ -197,58 +198,60 @@ export class LocalTime {
197
198
  return t
198
199
  }
199
200
 
200
- year(): number
201
- year(v: number): LocalTime
202
- year(v?: number): number | LocalTime {
203
- return v === undefined ? this.get('year') : this.set('year', v)
201
+ get year(): number {
202
+ return this.$date.getFullYear()
204
203
  }
205
- month(): number
206
- month(v: number): LocalTime
207
- month(v?: number): number | LocalTime {
208
- return v === undefined ? this.get('month') : this.set('month', v)
204
+ setYear(v: number): LocalTime {
205
+ return this.set('year', v)
209
206
  }
210
- week(): number
211
- week(v: number): LocalTime
212
- week(v?: number): number | LocalTime {
213
- return v === undefined ? getWeek(this.$date) : this.set('week', v)
207
+ get month(): number {
208
+ return this.$date.getMonth() + 1
214
209
  }
215
- day(): number
216
- day(v: number): LocalTime
217
- day(v?: number): number | LocalTime {
218
- return v === undefined ? this.get('day') : this.set('day', v)
210
+ setMonth(v: number): LocalTime {
211
+ return this.set('month', v)
212
+ }
213
+ get week(): number {
214
+ return getWeek(this.$date)
215
+ }
216
+ setWeek(v: number): LocalTime {
217
+ return this.set('week', v)
218
+ }
219
+ get day(): number {
220
+ return this.$date.getDate()
221
+ }
222
+ setDay(v: number): LocalTime {
223
+ return this.set('day', v)
224
+ }
225
+ get hour(): number {
226
+ return this.$date.getHours()
227
+ }
228
+ setHour(v: number): LocalTime {
229
+ return this.set('hour', v)
230
+ }
231
+ get minute(): number {
232
+ return this.$date.getMinutes()
233
+ }
234
+ setMinute(v: number): LocalTime {
235
+ return this.set('minute', v)
236
+ }
237
+ get second(): number {
238
+ return this.$date.getSeconds()
239
+ }
240
+ setSecond(v: number): LocalTime {
241
+ return this.set('second', v)
219
242
  }
220
243
 
221
244
  /**
222
245
  * Based on ISO: 1-7 is Mon-Sun.
223
246
  */
224
- dayOfWeek(): ISODayOfWeek
225
- dayOfWeek(v: ISODayOfWeek): LocalTime
226
- dayOfWeek(v?: ISODayOfWeek): ISODayOfWeek | LocalTime {
227
- const dow = (this.$date.getDay() || 7) as ISODayOfWeek
228
-
229
- if (v === undefined) {
230
- return dow
231
- }
232
-
247
+ get dayOfWeek(): ISODayOfWeek {
248
+ return (this.$date.getDay() || 7) as ISODayOfWeek
249
+ }
250
+ setDayOfWeek(v: ISODayOfWeek): LocalTime {
233
251
  _assert(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`)
234
-
252
+ const dow = this.$date.getDay() || 7
235
253
  return this.plus(v - dow, 'day')
236
254
  }
237
- hour(): number
238
- hour(v: number): LocalTime
239
- hour(v?: number): number | LocalTime {
240
- return v === undefined ? this.get('hour') : this.set('hour', v)
241
- }
242
- minute(): number
243
- minute(v: number): LocalTime
244
- minute(v?: number): number | LocalTime {
245
- return v === undefined ? this.get('minute') : this.set('minute', v)
246
- }
247
- second(): number
248
- second(v: number): LocalTime
249
- second(v?: number): number | LocalTime {
250
- return v === undefined ? this.get('second') : this.set('second', v)
251
- }
252
255
 
253
256
  setComponents(c: Partial<DateTimeObject>, mutate = false): LocalTime {
254
257
  const d = mutate ? this.$date : new Date(this.$date)
@@ -326,7 +329,7 @@ export class LocalTime {
326
329
 
327
330
  if (unit === 'year' || unit === 'month') {
328
331
  const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate)
329
- return mutate ? this : localTime.of(d)
332
+ return mutate ? this : localTime.from(d)
330
333
  }
331
334
 
332
335
  return this.set(unit, this.get(unit) + num, mutate)
@@ -341,7 +344,7 @@ export class LocalTime {
341
344
  }
342
345
 
343
346
  diff(other: LocalTimeInput, unit: LocalTimeUnit): number {
344
- const date2 = localTime.of(other).$date
347
+ const date2 = localTime.from(other).$date
345
348
 
346
349
  const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
347
350
  if (!secDiff) return 0
@@ -431,37 +434,32 @@ export class LocalTime {
431
434
  * Returns how many days are in the current month.
432
435
  * E.g 31 for January.
433
436
  */
434
- daysInMonth(): number {
437
+ get daysInMonth(): number {
435
438
  return localDate.getMonthLength(this.$date.getFullYear(), this.$date.getMonth() + 1)
436
439
  }
437
440
 
438
441
  isSame(d: LocalTimeInput): boolean {
439
- return this.cmp(d) === 0
442
+ return this.compare(d) === 0
440
443
  }
441
-
442
444
  isBefore(d: LocalTimeInput, inclusive = false): boolean {
443
- const r = this.cmp(d)
445
+ const r = this.compare(d)
444
446
  return r === -1 || (r === 0 && inclusive)
445
447
  }
446
-
447
448
  isSameOrBefore(d: LocalTimeInput): boolean {
448
- return this.cmp(d) <= 0
449
+ return this.compare(d) <= 0
449
450
  }
450
-
451
451
  isAfter(d: LocalTimeInput, inclusive = false): boolean {
452
- const r = this.cmp(d)
452
+ const r = this.compare(d)
453
453
  return r === 1 || (r === 0 && inclusive)
454
454
  }
455
-
456
455
  isSameOrAfter(d: LocalTimeInput): boolean {
457
- return this.cmp(d) >= 0
456
+ return this.compare(d) >= 0
458
457
  }
459
-
460
458
  isBetween(min: LocalTimeInput, max: LocalTimeInput, incl: Inclusiveness = '[)'): boolean {
461
- let r = this.cmp(min)
459
+ let r = this.compare(min)
462
460
  // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
463
461
  if (r < 0 || (r === 0 && incl[0] === '(')) return false
464
- r = this.cmp(max)
462
+ r = this.compare(max)
465
463
  if (r > 0 || (r === 0 && incl[1] === ')')) return false
466
464
  return true
467
465
  }
@@ -476,14 +474,14 @@ export class LocalTime {
476
474
  * Third argument allows to override "now".
477
475
  */
478
476
  isOlderThan(n: number, unit: LocalTimeUnit, now?: LocalTimeInput): boolean {
479
- return this.isBefore(localTime.of(now ?? new Date()).plus(-n, unit))
477
+ return this.isBefore(localTime.from(now ?? new Date()).plus(-n, unit))
480
478
  }
481
479
 
482
480
  /**
483
481
  * Checks if this localTime is same or older (<=) than "now" by X units.
484
482
  */
485
483
  isSameOrOlderThan(n: number, unit: LocalTimeUnit, now?: LocalTimeInput): boolean {
486
- return this.isSameOrBefore(localTime.of(now ?? new Date()).plus(-n, unit))
484
+ return this.isSameOrBefore(localTime.from(now ?? new Date()).plus(-n, unit))
487
485
  }
488
486
 
489
487
  /**
@@ -496,14 +494,14 @@ export class LocalTime {
496
494
  * Third argument allows to override "now".
497
495
  */
498
496
  isYoungerThan(n: number, unit: LocalTimeUnit, now?: LocalTimeInput): boolean {
499
- return this.isAfter(localTime.of(now ?? new Date()).plus(-n, unit))
497
+ return this.isAfter(localTime.from(now ?? new Date()).plus(-n, unit))
500
498
  }
501
499
 
502
500
  /**
503
501
  * Checks if this localTime is same or younger (>=) than "now" by X units.
504
502
  */
505
503
  isSameOrYoungerThan(n: number, unit: LocalTimeUnit, now?: LocalTimeInput): boolean {
506
- return this.isSameOrAfter(localTime.of(now ?? new Date()).plus(-n, unit))
504
+ return this.isSameOrAfter(localTime.from(now ?? new Date()).plus(-n, unit))
507
505
  }
508
506
 
509
507
  getAgeInYears(now?: LocalTimeInput): number {
@@ -525,7 +523,7 @@ export class LocalTime {
525
523
  return this.getAgeIn('second', now)
526
524
  }
527
525
  getAgeIn(unit: LocalTimeUnit, now?: LocalTimeInput): number {
528
- return localTime.of(now ?? new Date()).diff(this, unit)
526
+ return localTime.from(now ?? new Date()).diff(this, unit)
529
527
  }
530
528
 
531
529
  /**
@@ -533,21 +531,21 @@ export class LocalTime {
533
531
  * returns 0 if they are equal
534
532
  * returns -1 if this < d
535
533
  */
536
- cmp(d: LocalTimeInput): -1 | 0 | 1 {
534
+ compare(d: LocalTimeInput): -1 | 0 | 1 {
537
535
  const t1 = this.$date.valueOf()
538
- const t2 = localTime.of(d).$date.valueOf()
536
+ const t2 = localTime.from(d).$date.valueOf()
539
537
  if (t1 === t2) return 0
540
538
  return t1 < t2 ? -1 : 1
541
539
  }
542
540
 
543
- getDateTimeObject(): DateTimeObject {
541
+ toDateTimeObject(): DateTimeObject {
544
542
  return {
545
- ...this.getDateObject(),
546
- ...this.getTimeObject(),
543
+ ...this.toDateObject(),
544
+ ...this.toTimeObject(),
547
545
  }
548
546
  }
549
547
 
550
- getDateObject(): DateObject {
548
+ toDateObject(): DateObject {
551
549
  return {
552
550
  year: this.$date.getFullYear(),
553
551
  month: this.$date.getMonth() + 1,
@@ -555,7 +553,7 @@ export class LocalTime {
555
553
  }
556
554
  }
557
555
 
558
- getTimeObject(): TimeObject {
556
+ toTimeObject(): TimeObject {
559
557
  return {
560
558
  hour: this.$date.getHours(),
561
559
  minute: this.$date.getMinutes(),
@@ -563,8 +561,8 @@ export class LocalTime {
563
561
  }
564
562
  }
565
563
 
566
- fromNow(now: LocalTimeInput = new Date()): string {
567
- const msDiff = localTime.of(now).$date.valueOf() - this.$date.valueOf()
564
+ toFromNowString(now: LocalTimeInput = new Date()): string {
565
+ const msDiff = localTime.from(now).$date.valueOf() - this.$date.valueOf()
568
566
 
569
567
  if (msDiff === 0) return 'now'
570
568
 
@@ -575,7 +573,7 @@ export class LocalTime {
575
573
  return `in ${_ms(msDiff * -1)}`
576
574
  }
577
575
 
578
- getDate(): Date {
576
+ toDate(): Date {
579
577
  return this.$date
580
578
  }
581
579
 
@@ -583,11 +581,11 @@ export class LocalTime {
583
581
  return new LocalTime(new Date(this.$date))
584
582
  }
585
583
 
586
- unix(): UnixTimestampNumber {
584
+ get unix(): UnixTimestampNumber {
587
585
  return Math.floor(this.$date.valueOf() / 1000)
588
586
  }
589
587
 
590
- unixMillis(): UnixTimestampMillisNumber {
588
+ get unixMillis(): UnixTimestampMillisNumber {
591
589
  return this.$date.valueOf()
592
590
  }
593
591
 
@@ -624,7 +622,7 @@ export class LocalTime {
624
622
  * Returns e.g: `1984-06-21`, only the date part of DateTime
625
623
  */
626
624
  toISODate(): IsoDateString {
627
- const { year, month, day } = this.getDateObject()
625
+ const { year, month, day } = this.toDateObject()
628
626
 
629
627
  return [
630
628
  String(year).padStart(4, '0'),
@@ -640,7 +638,7 @@ export class LocalTime {
640
638
  * Returns e.g: `17:03:15` (or `17:03` with seconds=false)
641
639
  */
642
640
  toISOTime(seconds = true): string {
643
- const { hour, minute, second } = this.getTimeObject()
641
+ const { hour, minute, second } = this.toTimeObject()
644
642
 
645
643
  return [
646
644
  String(hour).padStart(2, '0'),
@@ -658,7 +656,7 @@ export class LocalTime {
658
656
  * Returns e.g: `19840621_1705`
659
657
  */
660
658
  toStringCompact(seconds = false): string {
661
- const { year, month, day, hour, minute, second } = this.getDateTimeObject()
659
+ const { year, month, day, hour, minute, second } = this.toDateTimeObject()
662
660
 
663
661
  return [
664
662
  String(year).padStart(4, '0'),
@@ -676,7 +674,7 @@ export class LocalTime {
676
674
  }
677
675
 
678
676
  toJSON(): UnixTimestampNumber {
679
- return this.unix()
677
+ return this.unix
680
678
  }
681
679
 
682
680
  toMonthId(): MonthId {
@@ -694,53 +692,61 @@ export class LocalTime {
694
692
 
695
693
  class LocalTimeFactory {
696
694
  /**
697
- * Parses input String into LocalDate.
698
- * Input can already be a LocalDate - it is returned as-is in that case.
695
+ * Parses input String into LocalTime.
696
+ * Input can already be a LocalTime - it is returned as-is in that case.
699
697
  */
700
- of(d: LocalTimeInput): LocalTime {
701
- const t = this.parseOrNull(d)
698
+ from(input: LocalTimeInput): LocalTime {
699
+ const lt = this.fromOrNull(input)
700
+ this.assertNotNull(lt, input)
701
+ return lt
702
+ }
702
703
 
703
- _assert(t !== null, `Cannot parse "${d}" into LocalTime`, {
704
- input: d,
705
- })
704
+ fromDate(date: Date): LocalTime {
705
+ return new LocalTime(date)
706
+ }
706
707
 
707
- return t
708
+ fromUnix(ts: UnixTimestampNumber): LocalTime {
709
+ return new LocalTime(new Date(ts * 1000))
708
710
  }
709
711
 
710
712
  /**
711
713
  * Create LocalTime from unixTimestamp in milliseconds (not in seconds).
712
714
  */
713
- ofMillis(millis: UnixTimestampMillisNumber): LocalTime {
714
- return this.of(new Date(millis))
715
+ fromMillis(millis: UnixTimestampMillisNumber): LocalTime {
716
+ return new LocalTime(new Date(millis))
715
717
  }
716
718
 
717
719
  /**
718
720
  * Returns null if invalid
719
721
  */
720
- parseOrNull(d: LocalTimeInputNullable): LocalTime | null {
722
+ fromOrNull(d: LocalTimeInputNullable): LocalTime | null {
721
723
  if (d instanceof LocalTime) return d
722
-
723
- let date
724
-
725
724
  if (d instanceof Date) {
726
- date = d
727
- } else if (typeof d === 'number') {
728
- date = new Date(d * 1000)
729
- } else if (!d) {
730
- // This check is after checking the number, to support `0`
731
- return null
732
- } else if (typeof (d as any) !== 'string') {
733
- // unexpected type, e.g Function or something
734
- return null
735
- } else {
736
- date = this.parseStringToDateOrNull(d)
737
- if (date === null) return null
725
+ return new LocalTime(d)
726
+ }
727
+ if (typeof d === 'number') {
728
+ return new LocalTime(new Date(d * 1000))
729
+ }
730
+ if (typeof d === 'string') {
731
+ return this.fromStringOrNull(d)
738
732
  }
733
+ // This check is after checking the number, to support `0`
734
+ // unexpected type, e.g Function or something
735
+ return null
736
+ }
739
737
 
740
- return new LocalTime(date)
738
+ fromStringOrNull(s: string | undefined | null): LocalTime | null {
739
+ const date = this.parseStringToDateOrNull(s)
740
+ return date ? new LocalTime(date) : null
741
+ }
742
+
743
+ fromDateTimeObject(input: DateTimeObjectInput): LocalTime {
744
+ const { year, month, day = 1, hour = 0, minute = 0, second = 0 } = input
745
+ return new LocalTime(new Date(year, month - 1, day, hour, minute, second))
741
746
  }
742
747
 
743
- private parseStringToDateOrNull(s: string): Date | null {
748
+ private parseStringToDateOrNull(s: string | undefined | null): Date | null {
749
+ if (!s) return null
744
750
  // Slicing removes the "timezone component", and makes the date "local"
745
751
  // e.g 2022-04-06T23:15:00+09:00
746
752
  // becomes 2022-04-06T23:15:00
@@ -801,8 +807,21 @@ class LocalTimeFactory {
801
807
  return new Date(year, month - 1, day, hour || 0, minute || 0, second || 0, 0)
802
808
  }
803
809
 
804
- isValid(d: LocalTimeInputNullable): boolean {
805
- return this.parseOrNull(d) !== null
810
+ isValid(input: LocalTimeInputNullable): boolean {
811
+ return this.fromOrNull(input) !== null
812
+ }
813
+
814
+ isValidString(isoString: string | undefined | null): boolean {
815
+ return this.fromStringOrNull(isoString) !== null
816
+ }
817
+
818
+ private assertNotNull(
819
+ lt: LocalTime | null,
820
+ input: LocalTimeInputNullable,
821
+ ): asserts lt is LocalTime {
822
+ _assert(lt !== null, `Cannot parse "${input}" into LocalTime`, {
823
+ input,
824
+ })
806
825
  }
807
826
 
808
827
  /**
@@ -833,21 +852,15 @@ class LocalTimeFactory {
833
852
  *
834
853
  * `localTime` function will instead return LocalTime of `now` for falsy input.
835
854
  */
836
- orUndefined(d: LocalTimeInputNullable): LocalTime | undefined {
837
- return d ? this.of(d) : undefined
855
+ orUndefined(input: LocalTimeInputNullable): LocalTime | undefined {
856
+ return input || input === 0 ? this.from(input) : undefined
838
857
  }
839
858
 
840
859
  /**
841
860
  * Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
842
861
  */
843
- orNow(d: LocalTimeInputNullable): LocalTime {
844
- return d ? this.of(d) : this.now()
845
- }
846
-
847
- fromComponents(c: { year: number; month: number } & Partial<DateTimeObject>): LocalTime {
848
- return new LocalTime(
849
- new Date(c.year, c.month - 1, c.day || 1, c.hour || 0, c.minute || 0, c.second || 0),
850
- )
862
+ orNow(input: LocalTimeInputNullable): LocalTime {
863
+ return input || input === 0 ? this.from(input) : this.now()
851
864
  }
852
865
 
853
866
  sort(items: LocalTime[], dir: SortDirection = 'asc', mutate = false): LocalTime[] {
@@ -869,7 +882,7 @@ class LocalTimeFactory {
869
882
  _assert(items2.length, 'localTime.min called on empty array')
870
883
 
871
884
  return items2
872
- .map(i => this.of(i))
885
+ .map(i => this.from(i))
873
886
  .reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item))
874
887
  }
875
888
 
@@ -882,7 +895,7 @@ class LocalTimeFactory {
882
895
  _assert(items2.length, 'localTime.max called on empty array')
883
896
 
884
897
  return items2
885
- .map(i => this.of(i))
898
+ .map(i => this.from(i))
886
899
  .reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item))
887
900
  }
888
901
  }
@@ -998,7 +1011,7 @@ interface LocalTimeFn extends LocalTimeFactory {
998
1011
 
999
1012
  const localTimeFactory = new LocalTimeFactory()
1000
1013
 
1001
- export const localTime = localTimeFactory.of.bind(localTimeFactory) as LocalTimeFn
1014
+ export const localTime = localTimeFactory.from.bind(localTimeFactory) as LocalTimeFn
1002
1015
 
1003
1016
  // The line below is the blackest of black magic I have ever written in 2024.
1004
1017
  // And probably 2023 as well.
@@ -17,7 +17,7 @@ export class TimeInterval {
17
17
  ) {}
18
18
 
19
19
  static of(start: LocalTimeInput, end: LocalTimeInput): TimeInterval {
20
- return new TimeInterval(localTime.of(start).unix(), localTime.of(end).unix())
20
+ return new TimeInterval(localTime.from(start).unix, localTime.from(end).unix)
21
21
  }
22
22
 
23
23
  get start(): UnixTimestampNumber {
@@ -74,7 +74,7 @@ export class TimeInterval {
74
74
  }
75
75
 
76
76
  includes(d: LocalTimeInput, incl: Inclusiveness = '[)'): boolean {
77
- d = localTime.of(d).unix()
77
+ d = localTime.from(d).unix
78
78
  // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
79
79
  if (d < this.$start || (d === this.$start && incl[0] === '(')) return false
80
80
  if (d > this.$end || (d === this.$end && incl[1] === ')')) return false
@@ -44,11 +44,11 @@ export interface BuildInfo {
44
44
 
45
45
  export function generateBuildInfoDev(): BuildInfo {
46
46
  const now = localTime.now()
47
- const ts = now.unix()
47
+ const ts = now.unix
48
48
  const rev = 'devRev'
49
49
  const branchName = 'devBranch'
50
50
  const repoName = 'devRepo'
51
- const tsCommit = now.unix()
51
+ const tsCommit = now.unix
52
52
 
53
53
  const ver = [now.toStringCompact(), repoName, branchName, rev].join('_')
54
54