@naturalcycles/js-lib 14.97.0 → 14.98.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/types.d.ts CHANGED
@@ -5,7 +5,7 @@ import { Merge, Promisable } from './typeFest';
5
5
  * Alternative: Record<string, T | undefined>
6
6
  */
7
7
  export interface StringMap<T = string> {
8
- [k: string]: T | undefined;
8
+ [k: string | number]: T | undefined;
9
9
  }
10
10
  /**
11
11
  * Object to be passed to pProps to resolve all promises into properties.
@@ -24,14 +24,37 @@ export interface CreatedUpdated {
24
24
  created: number;
25
25
  updated: number;
26
26
  }
27
- export interface CreatedUpdatedId<ID = string> extends CreatedUpdated {
27
+ export interface CreatedUpdatedId<ID extends string | number = string | number> extends CreatedUpdated {
28
28
  id: ID;
29
29
  }
30
- export interface ObjectWithId<ID = string> {
30
+ export interface ObjectWithId<ID extends string | number = string | number> {
31
31
  id: ID;
32
32
  }
33
- export interface AnyObjectWithId<ID = string> extends AnyObject, ObjectWithId<ID> {
33
+ export interface AnyObjectWithId<ID extends string | number = string | number> extends AnyObject, ObjectWithId<ID> {
34
34
  }
35
+ /**
36
+ * Base interface for any Entity that was saved to DB.
37
+ */
38
+ export interface SavedDBEntity<ID extends string | number = string> {
39
+ id: ID;
40
+ /**
41
+ * unixTimestamp of when the entity was first created (in the DB).
42
+ */
43
+ created: UnixTimestampNumber;
44
+ /**
45
+ * unixTimestamp of when the entity was last updated (in the DB).
46
+ */
47
+ updated: UnixTimestampNumber;
48
+ }
49
+ /**
50
+ * Base interface for any Entity that can be saved to DB.
51
+ * This interface fits when entity was NOT YET saved to DB,
52
+ * hence `id`, `created` and `updated` fields CAN BE undefined (yet).
53
+ * When it's known to be saved - `SavedDBEntity` interface can be used instead.
54
+ */
55
+ export declare type BaseDBEntity<ID extends string | number = string> = Partial<SavedDBEntity<ID>>;
56
+ export declare type Saved<T extends Partial<ObjectWithId>> = Merge<T, SavedDBEntity<Exclude<T['id'], undefined>>>;
57
+ export declare type Unsaved<T extends ObjectWithId> = Merge<T, BaseDBEntity<T['id']>>;
35
58
  /**
36
59
  * Convenience type shorthand.
37
60
  * Because `Function` type is discouraged by eslint.
@@ -136,29 +159,6 @@ export declare type UnixTimestamp = number;
136
159
  * Same as `number`, but with semantic meaning that it's an Integer.
137
160
  */
138
161
  export declare type Integer = number;
139
- /**
140
- * Base interface for any Entity that was saved to DB.
141
- */
142
- export interface SavedDBEntity<ID = string> {
143
- id: ID;
144
- /**
145
- * unixTimestamp of when the entity was first created (in the DB).
146
- */
147
- created: UnixTimestampNumber;
148
- /**
149
- * unixTimestamp of when the entity was last updated (in the DB).
150
- */
151
- updated: UnixTimestampNumber;
152
- }
153
- /**
154
- * Base interface for any Entity that can be saved to DB.
155
- * This interface fits when entity was NOT YET saved to DB,
156
- * hence `id`, `created` and `updated` fields CAN BE undefined (yet).
157
- * When it's known to be saved - `SavedDBEntity` interface can be used instead.
158
- */
159
- export declare type BaseDBEntity<ID = string> = Partial<SavedDBEntity<ID>>;
160
- export declare type Saved<E, ID = string> = Merge<E, SavedDBEntity<ID>>;
161
- export declare type Unsaved<E, ID = string> = Merge<E, BaseDBEntity<ID>>;
162
162
  /**
163
163
  * Named type for JSON.parse / JSON.stringify second argument
164
164
  */
@@ -27,14 +27,16 @@ export class DateInterval {
27
27
  isSame(d) {
28
28
  return this.cmp(d) === 0;
29
29
  }
30
- isBefore(d) {
31
- return this.cmp(d) === -1;
30
+ isBefore(d, inclusive = false) {
31
+ const r = this.cmp(d);
32
+ return r === -1 || (r === 0 && inclusive);
32
33
  }
33
34
  isSameOrBefore(d) {
34
35
  return this.cmp(d) <= 0;
35
36
  }
36
- isAfter(d) {
37
- return this.cmp(d) === 1;
37
+ isAfter(d, inclusive = false) {
38
+ const r = this.cmp(d);
39
+ return r === 1 || (r === 0 && inclusive);
38
40
  }
39
41
  isSameOrAfter(d) {
40
42
  return this.cmp(d) >= 0;
@@ -42,9 +44,14 @@ export class DateInterval {
42
44
  /**
43
45
  * Ranges of DateInterval (start, end) are INCLUSIVE.
44
46
  */
45
- includes(d) {
47
+ includes(d, incl = '[]') {
46
48
  d = LocalDate.of(d);
47
- return d.isSameOrAfter(this.start) && d.isSameOrBefore(this.end);
49
+ return d.isAfter(this.start, incl[0] === '[') && d.isBefore(this.end, incl[1] === ']');
50
+ }
51
+ intersects(int, inclusive = true) {
52
+ const $int = DateInterval.parse(int);
53
+ const incl = inclusive ? '[]' : '()';
54
+ return this.includes($int.start, incl) || this.includes($int.end, incl);
48
55
  }
49
56
  /**
50
57
  * DateIntervals compare by start date.
@@ -54,18 +61,14 @@ export class DateInterval {
54
61
  d = DateInterval.parse(d);
55
62
  return this.start.cmp(d.start) || this.end.cmp(d.end);
56
63
  }
64
+ getDays(incl = '[]') {
65
+ return LocalDate.range(this.start, this.end, incl, 1, 'day');
66
+ }
57
67
  /**
58
68
  * Returns an array of LocalDates that are included in the interval.
59
- * Ranges are INCLUSIVE.
60
69
  */
61
- getDays() {
62
- const days = [];
63
- let current = this.start;
64
- do {
65
- days.push(current);
66
- current = current.add(1, 'day');
67
- } while (current.isSameOrBefore(this.end));
68
- return days;
70
+ range(incl = '[]', step = 1, stepUnit = 'day') {
71
+ return LocalDate.range(this.start, this.end, incl, step, stepUnit);
69
72
  }
70
73
  toString() {
71
74
  return [this.start, this.end].join('/');
@@ -1,8 +1,7 @@
1
1
  import { _assert } from '../error/assert';
2
- import { Sequence } from '../seq/seq';
3
- import { END } from '../types';
4
2
  import { LocalTime } from './localTime';
5
- const m31 = new Set([1, 3, 5, 7, 8, 10, 12]);
3
+ const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
4
+ const DATE_REGEX = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
6
5
  /* eslint-disable no-dupe-class-members */
7
6
  /**
8
7
  * @experimental
@@ -48,8 +47,13 @@ export class LocalDate {
48
47
  return null;
49
48
  if (d instanceof LocalDate)
50
49
  return d;
51
- // todo: explore more performant options
52
- const [year, month, day] = d.slice(0, 10).split('-').map(Number);
50
+ // const [year, month, day] = d.slice(0, 10).split('-').map(Number)
51
+ const matches = DATE_REGEX.exec(d.slice(0, 10));
52
+ if (!matches)
53
+ return null;
54
+ const year = Number(matches[1]);
55
+ const month = Number(matches[2]);
56
+ const day = Number(matches[3]);
53
57
  if (!year ||
54
58
  !month ||
55
59
  month < 1 ||
@@ -61,6 +65,10 @@ export class LocalDate {
61
65
  }
62
66
  return new LocalDate(year, month, day);
63
67
  }
68
+ // Can use just .toString()
69
+ // static parseToString(d: LocalDateConfig): IsoDateString {
70
+ // return typeof d === 'string' ? d : d.toString()
71
+ // }
64
72
  static isValid(iso) {
65
73
  return this.parseOrNull(iso) !== null;
66
74
  }
@@ -88,32 +96,23 @@ export class LocalDate {
88
96
  _assert(items.length, 'LocalDate.latest called on empty array');
89
97
  return items.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
90
98
  }
91
- static range(minIncl, maxExcl, step = 1, stepUnit = 'day') {
92
- const days = [];
93
- let current = LocalDate.of(minIncl).startOf(stepUnit);
94
- const max = LocalDate.of(maxExcl).startOf(stepUnit);
95
- do {
96
- days.push(current);
99
+ static range(min, max, incl = '[)', step = 1, stepUnit = 'day') {
100
+ const dates = [];
101
+ const $min = LocalDate.of(min);
102
+ const $max = LocalDate.of(max).startOf(stepUnit);
103
+ let current = $min.startOf(stepUnit);
104
+ if (current.isAfter($min, incl[0] === '[')) {
105
+ // ok
106
+ }
107
+ else {
108
+ current.add(1, stepUnit, true);
109
+ }
110
+ const incl2 = incl[1] === ']';
111
+ while (current.isBefore($max, incl2)) {
112
+ dates.push(current);
97
113
  current = current.add(step, stepUnit);
98
- } while (current.isBefore(max));
99
- return days;
100
- }
101
- static rangeSeq(minIncl, maxExcl, step = 1, stepUnit = 'day') {
102
- const min = LocalDate.of(minIncl).startOf(stepUnit);
103
- const max = LocalDate.of(maxExcl).startOf(stepUnit);
104
- return Sequence.create(min, d => {
105
- const next = d.add(step, stepUnit);
106
- return next.isAfter(max) ? END : next;
107
- });
108
- }
109
- static rangeString(minIncl, maxExcl, step = 1, stepUnit = 'day') {
110
- return LocalDate.range(minIncl, maxExcl, step, stepUnit).map(ld => ld.toString());
111
- }
112
- static rangeIncl(minIncl, maxIncl, step = 1, stepUnit = 'day') {
113
- return LocalDate.range(minIncl, LocalDate.of(maxIncl).add(1, stepUnit), step, stepUnit);
114
- }
115
- static rangeInclString(minIncl, maxIncl, step = 1, stepUnit = 'day') {
116
- return LocalDate.range(minIncl, LocalDate.of(maxIncl).add(1, stepUnit), step, stepUnit).map(ld => ld.toString());
114
+ }
115
+ return dates;
117
116
  }
118
117
  get(unit) {
119
118
  return unit === 'year' ? this.$year : unit === 'month' ? this.$month : this.$day;
@@ -144,14 +143,16 @@ export class LocalDate {
144
143
  d = LocalDate.of(d);
145
144
  return this.$day === d.$day && this.$month === d.$month && this.$year === d.$year;
146
145
  }
147
- isBefore(d) {
148
- return this.cmp(d) === -1;
146
+ isBefore(d, inclusive = false) {
147
+ const r = this.cmp(d);
148
+ return r === -1 || (r === 0 && inclusive);
149
149
  }
150
150
  isSameOrBefore(d) {
151
151
  return this.cmp(d) <= 0;
152
152
  }
153
- isAfter(d) {
154
- return this.cmp(d) === 1;
153
+ isAfter(d, inclusive = false) {
154
+ const r = this.cmp(d);
155
+ return r === 1 || (r === 0 && inclusive);
155
156
  }
156
157
  isSameOrAfter(d) {
157
158
  return this.cmp(d) >= 0;
@@ -241,24 +242,29 @@ export class LocalDate {
241
242
  $year += num;
242
243
  }
243
244
  // check day overflow
244
- let monLen = LocalDate.getMonthLength($year, $month);
245
- while ($day > monLen) {
246
- $day -= monLen;
247
- $month += 1;
248
- if ($month > 12) {
249
- $year += 1;
250
- $month -= 12;
245
+ if (unit === 'day') {
246
+ if ($day < 1) {
247
+ while ($day < 1) {
248
+ $month -= 1;
249
+ if ($month < 1) {
250
+ $year -= 1;
251
+ $month += 12;
252
+ }
253
+ $day += LocalDate.getMonthLength($year, $month);
254
+ }
251
255
  }
252
- monLen = LocalDate.getMonthLength($year, $month);
253
- }
254
- while ($day < 1) {
255
- $day += monLen;
256
- $month -= 1;
257
- if ($month < 1) {
258
- $year -= 1;
259
- $month += 12;
256
+ else {
257
+ let monLen = LocalDate.getMonthLength($year, $month);
258
+ while ($day > monLen) {
259
+ $day -= monLen;
260
+ $month += 1;
261
+ if ($month > 12) {
262
+ $year += 1;
263
+ $month -= 12;
264
+ }
265
+ monLen = LocalDate.getMonthLength($year, $month);
266
+ }
260
267
  }
261
- monLen = LocalDate.getMonthLength($year, $month);
262
268
  }
263
269
  // check month overflow
264
270
  while ($month > 12) {
@@ -302,14 +308,10 @@ export class LocalDate {
302
308
  static getMonthLength(year, month) {
303
309
  if (month === 2)
304
310
  return this.isLeapYear(year) ? 29 : 28;
305
- return m31.has(month) ? 31 : 30;
311
+ return MDAYS[month];
306
312
  }
307
313
  static isLeapYear(year) {
308
- if (year % 4 !== 0)
309
- return false;
310
- if (year % 100 !== 0)
311
- return true;
312
- return year % 400 === 0;
314
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
313
315
  }
314
316
  clone() {
315
317
  return new LocalDate(this.$year, this.$month, this.$day);
@@ -45,7 +45,7 @@ export class LocalTime {
45
45
  date = new Date(d * 1000);
46
46
  }
47
47
  else {
48
- date = new Date(d);
48
+ date = new Date(d.slice(0, 19));
49
49
  }
50
50
  // validation
51
51
  if (isNaN(date.getDate())) {
@@ -57,6 +57,28 @@ export class LocalTime {
57
57
  // }
58
58
  return new LocalTime(date, false);
59
59
  }
60
+ static parseToDate(d) {
61
+ if (d instanceof LocalTime)
62
+ return d.$date;
63
+ if (d instanceof Date)
64
+ return d;
65
+ const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
66
+ if (isNaN(date.getDate())) {
67
+ throw new TypeError(`Cannot parse "${d}" to Date`);
68
+ }
69
+ return date;
70
+ }
71
+ static parseToUnixTimestamp(d) {
72
+ if (typeof d === 'number')
73
+ return d;
74
+ if (d instanceof LocalTime)
75
+ return d.unix();
76
+ const date = d instanceof Date ? d : new Date(d);
77
+ if (isNaN(date.getDate())) {
78
+ throw new TypeError(`Cannot parse "${d}" to UnixTimestamp`);
79
+ }
80
+ return date.valueOf() / 1000;
81
+ }
60
82
  static isValid(d) {
61
83
  return this.parseOrNull(d) !== null;
62
84
  }
@@ -161,7 +183,7 @@ export class LocalTime {
161
183
  return Math.abs(this.diff(other, unit));
162
184
  }
163
185
  diff(other, unit) {
164
- const date2 = LocalTime.of(other).$date;
186
+ const date2 = LocalTime.parseToDate(other);
165
187
  if (unit === 'year') {
166
188
  return this.$date.getFullYear() - date2.getFullYear();
167
189
  }
@@ -238,14 +260,16 @@ export class LocalTime {
238
260
  isSame(d) {
239
261
  return this.cmp(d) === 0;
240
262
  }
241
- isBefore(d) {
242
- return this.cmp(d) === -1;
263
+ isBefore(d, inclusive = false) {
264
+ const r = this.cmp(d);
265
+ return r === -1 || (r === 0 && inclusive);
243
266
  }
244
267
  isSameOrBefore(d) {
245
268
  return this.cmp(d) <= 0;
246
269
  }
247
- isAfter(d) {
248
- return this.cmp(d) === 1;
270
+ isAfter(d, inclusive = false) {
271
+ const r = this.cmp(d);
272
+ return r === 1 || (r === 0 && inclusive);
249
273
  }
250
274
  isSameOrAfter(d) {
251
275
  return this.cmp(d) >= 0;
@@ -266,7 +290,7 @@ export class LocalTime {
266
290
  */
267
291
  cmp(d) {
268
292
  const t1 = this.$date.valueOf();
269
- const t2 = LocalTime.of(d).$date.valueOf();
293
+ const t2 = LocalTime.parseToDate(d).valueOf();
270
294
  if (t1 === t2)
271
295
  return 0;
272
296
  return t1 < t2 ? -1 : 1;
@@ -292,8 +316,8 @@ export class LocalTime {
292
316
  second: this.$date.getSeconds(),
293
317
  };
294
318
  }
295
- fromNow(now = LocalTime.now()) {
296
- const msDiff = LocalTime.of(now).unixMillis() - this.unixMillis();
319
+ fromNow(now = new Date()) {
320
+ const msDiff = LocalTime.parseToDate(now).valueOf() - this.$date.valueOf();
297
321
  if (msDiff === 0)
298
322
  return 'now';
299
323
  if (msDiff >= 0) {
@@ -403,4 +427,3 @@ export class LocalTime {
403
427
  export function localTime(d) {
404
428
  return d ? LocalTime.of(d) : LocalTime.now();
405
429
  }
406
- // todo: range
@@ -0,0 +1,87 @@
1
+ import { LocalTime } from './localTime';
2
+ /**
3
+ * Class that supports an "interval of time" between 2 timestamps - start and end.
4
+ * Example: `1649267185/1649267187`.
5
+ *
6
+ * @experimental
7
+ */
8
+ export class TimeInterval {
9
+ constructor($start, $end) {
10
+ this.$start = $start;
11
+ this.$end = $end;
12
+ }
13
+ static of(start, end) {
14
+ return new TimeInterval(LocalTime.parseToUnixTimestamp(start), LocalTime.parseToUnixTimestamp(end));
15
+ }
16
+ get start() {
17
+ return this.$start;
18
+ }
19
+ get end() {
20
+ return this.$end;
21
+ }
22
+ get startTime() {
23
+ return LocalTime.of(this.$start);
24
+ }
25
+ get endTime() {
26
+ return LocalTime.of(this.$end);
27
+ }
28
+ /**
29
+ * Parses string like `1649267185/1649267187` into a TimeInterval.
30
+ */
31
+ static parse(d) {
32
+ if (d instanceof TimeInterval)
33
+ return d;
34
+ const [start, end] = d.split('/').map(Number);
35
+ if (!end || !start) {
36
+ throw new Error(`Cannot parse "${d}" into TimeInterval`);
37
+ }
38
+ return new TimeInterval(start, end);
39
+ }
40
+ isSame(d) {
41
+ return this.cmp(d) === 0;
42
+ }
43
+ isBefore(d, inclusive = false) {
44
+ const r = this.cmp(d);
45
+ return r === -1 || (r === 0 && inclusive);
46
+ }
47
+ isSameOrBefore(d) {
48
+ return this.cmp(d) <= 0;
49
+ }
50
+ isAfter(d, inclusive = false) {
51
+ const r = this.cmp(d);
52
+ return r === 1 || (r === 0 && inclusive);
53
+ }
54
+ isSameOrAfter(d) {
55
+ return this.cmp(d) >= 0;
56
+ }
57
+ includes(d, incl = '[)') {
58
+ d = LocalTime.parseToUnixTimestamp(d);
59
+ if (d < this.$start || (d === this.$start && incl[0] === '('))
60
+ return false;
61
+ if (d > this.$end || (d === this.$end && incl[1] === ')'))
62
+ return false;
63
+ return true;
64
+ }
65
+ /**
66
+ * TimeIntervals compare by start date.
67
+ * If it's the same - then by end date.
68
+ */
69
+ cmp(d) {
70
+ d = TimeInterval.parse(d);
71
+ if (this.$start > d.$start)
72
+ return 1;
73
+ if (this.$start < d.$start)
74
+ return -1;
75
+ if (this.$end > d.$end)
76
+ return 1;
77
+ if (this.$end < d.$end)
78
+ return -1;
79
+ return 0;
80
+ }
81
+ toString() {
82
+ return [this.$start, this.$end].join('/');
83
+ }
84
+ toJSON() {
85
+ return this.toString();
86
+ }
87
+ }
package/dist-esm/index.js CHANGED
@@ -59,4 +59,5 @@ export * from './string/leven';
59
59
  export * from './datetime/localDate';
60
60
  export * from './datetime/localTime';
61
61
  export * from './datetime/dateInterval';
62
+ export * from './datetime/timeInterval';
62
63
  export { is, _createPromiseDecorator, _stringMapValues, _stringMapEntries, _objectKeys, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, ErrorMode, pDefer, AggregatedError, pRetry, pRetryFn, pTimeout, pTimeoutFn, _tryCatch, _TryCatch, _stringifyAny, jsonSchema, JsonSchemaAnyBuilder, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, PQueue, END, SKIP, };
@@ -10,6 +10,12 @@ import { _sortNumbers } from '../number/number.util';
10
10
  export function _average(values) {
11
11
  return values.reduce((a, b) => a + b) / values.length;
12
12
  }
13
+ /**
14
+ * Same as _average, but safely returns null if input array is empty or nullish.
15
+ */
16
+ export function _averageOrNull(values) {
17
+ return (values === null || values === void 0 ? void 0 : values.length) ? values.reduce((a, b) => a + b) / values.length : null;
18
+ }
13
19
  /**
14
20
  * valuesArray and weightsArray length is expected to be the same.
15
21
  */
@@ -15,6 +15,10 @@ export class SimpleMovingAverage {
15
15
  */
16
16
  this.avg = 0;
17
17
  }
18
+ /**
19
+ * Push new value.
20
+ * Returns newly calculated average (using newly pushed value).
21
+ */
18
22
  push(n) {
19
23
  this.data[this.nextIndex] = n;
20
24
  this.nextIndex =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.97.0",
3
+ "version": "14.98.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -1,6 +1,6 @@
1
- import { LocalDate, LocalDateConfig } from './localDate'
1
+ import { Inclusiveness, LocalDate, LocalDateConfig, LocalDateUnit } from './localDate'
2
2
 
3
- export type DateIntervalConfig = DateInterval | string
3
+ export type DateIntervalConfig = DateInterval | DateIntervalString
4
4
  export type DateIntervalString = string
5
5
 
6
6
  /**
@@ -34,16 +34,18 @@ export class DateInterval {
34
34
  return this.cmp(d) === 0
35
35
  }
36
36
 
37
- isBefore(d: DateIntervalConfig): boolean {
38
- return this.cmp(d) === -1
37
+ isBefore(d: DateIntervalConfig, inclusive = false): boolean {
38
+ const r = this.cmp(d)
39
+ return r === -1 || (r === 0 && inclusive)
39
40
  }
40
41
 
41
42
  isSameOrBefore(d: DateIntervalConfig): boolean {
42
43
  return this.cmp(d) <= 0
43
44
  }
44
45
 
45
- isAfter(d: DateIntervalConfig): boolean {
46
- return this.cmp(d) === 1
46
+ isAfter(d: DateIntervalConfig, inclusive = false): boolean {
47
+ const r = this.cmp(d)
48
+ return r === 1 || (r === 0 && inclusive)
47
49
  }
48
50
 
49
51
  isSameOrAfter(d: DateIntervalConfig): boolean {
@@ -53,9 +55,15 @@ export class DateInterval {
53
55
  /**
54
56
  * Ranges of DateInterval (start, end) are INCLUSIVE.
55
57
  */
56
- includes(d: LocalDateConfig): boolean {
58
+ includes(d: LocalDateConfig, incl: Inclusiveness = '[]'): boolean {
57
59
  d = LocalDate.of(d)
58
- return d.isSameOrAfter(this.start) && d.isSameOrBefore(this.end)
60
+ return d.isAfter(this.start, incl[0] === '[') && d.isBefore(this.end, incl[1] === ']')
61
+ }
62
+
63
+ intersects(int: DateIntervalConfig, inclusive = true): boolean {
64
+ const $int = DateInterval.parse(int)
65
+ const incl = inclusive ? '[]' : '()'
66
+ return this.includes($int.start, incl) || this.includes($int.end, incl)
59
67
  }
60
68
 
61
69
  /**
@@ -67,19 +75,15 @@ export class DateInterval {
67
75
  return this.start.cmp(d.start) || this.end.cmp(d.end)
68
76
  }
69
77
 
78
+ getDays(incl: Inclusiveness = '[]'): LocalDate[] {
79
+ return LocalDate.range(this.start, this.end, incl, 1, 'day')
80
+ }
81
+
70
82
  /**
71
83
  * Returns an array of LocalDates that are included in the interval.
72
- * Ranges are INCLUSIVE.
73
84
  */
74
- getDays(): LocalDate[] {
75
- const days: LocalDate[] = []
76
- let current = this.start
77
- do {
78
- days.push(current)
79
- current = current.add(1, 'day')
80
- } while (current.isSameOrBefore(this.end))
81
-
82
- return days
85
+ range(incl: Inclusiveness = '[]', step = 1, stepUnit: LocalDateUnit = 'day'): LocalDate[] {
86
+ return LocalDate.range(this.start, this.end, incl, step, stepUnit)
83
87
  }
84
88
 
85
89
  toString(): DateIntervalString {