@dereekb/date 9.24.46 → 9.25.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 (77) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +2 -2
  3. package/src/lib/date/date.block.d.ts +373 -16
  4. package/src/lib/date/date.block.day.d.ts +1 -0
  5. package/src/lib/date/date.block.day.js +1 -0
  6. package/src/lib/date/date.block.day.js.map +1 -1
  7. package/src/lib/date/date.block.js +236 -24
  8. package/src/lib/date/date.block.js.map +1 -1
  9. package/src/lib/date/{date.validator.d.ts → date.block.validator.d.ts} +6 -0
  10. package/src/lib/date/{date.validator.js → date.block.validator.js} +7 -1
  11. package/src/lib/date/date.block.validator.js.map +1 -0
  12. package/src/lib/date/date.block.week.d.ts +24 -0
  13. package/src/lib/date/date.block.week.js +12 -0
  14. package/src/lib/date/date.block.week.js.map +1 -1
  15. package/src/lib/date/date.cell.d.ts +357 -0
  16. package/src/lib/date/date.cell.factory.d.ts +337 -0
  17. package/src/lib/date/date.cell.factory.js +479 -0
  18. package/src/lib/date/date.cell.factory.js.map +1 -0
  19. package/src/lib/date/date.cell.filter.d.ts +18 -0
  20. package/src/lib/date/date.cell.filter.js +65 -0
  21. package/src/lib/date/date.cell.filter.js.map +1 -0
  22. package/src/lib/date/date.cell.index.d.ts +375 -0
  23. package/src/lib/date/date.cell.index.js +731 -0
  24. package/src/lib/date/date.cell.index.js.map +1 -0
  25. package/src/lib/date/date.cell.js +518 -0
  26. package/src/lib/date/date.cell.js.map +1 -0
  27. package/src/lib/date/date.cell.schedule.d.ts +409 -0
  28. package/src/lib/date/date.cell.schedule.day.d.ts +9 -0
  29. package/src/lib/date/date.cell.schedule.day.js +15 -0
  30. package/src/lib/date/date.cell.schedule.day.js.map +1 -0
  31. package/src/lib/date/date.cell.schedule.js +667 -0
  32. package/src/lib/date/date.cell.schedule.js.map +1 -0
  33. package/src/lib/date/date.cell.validator.d.ts +14 -0
  34. package/src/lib/date/date.cell.validator.js +67 -0
  35. package/src/lib/date/date.cell.validator.js.map +1 -0
  36. package/src/lib/date/date.cell.week.d.ts +31 -0
  37. package/src/lib/date/date.cell.week.js +40 -0
  38. package/src/lib/date/date.cell.week.js.map +1 -0
  39. package/src/lib/date/date.d.ts +18 -0
  40. package/src/lib/date/date.duration.d.ts +2 -1
  41. package/src/lib/date/date.duration.js +6 -1
  42. package/src/lib/date/date.duration.js.map +1 -1
  43. package/src/lib/date/date.format.js +2 -1
  44. package/src/lib/date/date.format.js.map +1 -1
  45. package/src/lib/date/date.js +29 -1
  46. package/src/lib/date/date.js.map +1 -1
  47. package/src/lib/date/date.range.d.ts +4 -2
  48. package/src/lib/date/date.range.js +6 -4
  49. package/src/lib/date/date.range.js.map +1 -1
  50. package/src/lib/date/date.range.timezone.d.ts +27 -6
  51. package/src/lib/date/date.range.timezone.js +21 -7
  52. package/src/lib/date/date.range.timezone.js.map +1 -1
  53. package/src/lib/date/date.schedule.d.ts +99 -0
  54. package/src/lib/date/date.schedule.js +63 -0
  55. package/src/lib/date/date.schedule.js.map +1 -1
  56. package/src/lib/date/date.time.js +3 -3
  57. package/src/lib/date/date.time.js.map +1 -1
  58. package/src/lib/date/date.timezone.d.ts +98 -3
  59. package/src/lib/date/date.timezone.js +191 -24
  60. package/src/lib/date/date.timezone.js.map +1 -1
  61. package/src/lib/date/date.week.js +3 -1
  62. package/src/lib/date/date.week.js.map +1 -1
  63. package/src/lib/date/index.d.ts +8 -1
  64. package/src/lib/date/index.js +8 -1
  65. package/src/lib/date/index.js.map +1 -1
  66. package/src/lib/expires/expires.js +1 -1
  67. package/src/lib/expires/expires.js.map +1 -1
  68. package/src/lib/timezone/index.d.ts +1 -0
  69. package/src/lib/timezone/index.js +1 -0
  70. package/src/lib/timezone/index.js.map +1 -1
  71. package/src/lib/timezone/timezone.d.ts +7 -0
  72. package/src/lib/timezone/timezone.js +14 -2
  73. package/src/lib/timezone/timezone.js.map +1 -1
  74. package/src/lib/timezone/timezone.validator.d.ts +6 -0
  75. package/src/lib/timezone/timezone.validator.js +26 -0
  76. package/src/lib/timezone/timezone.validator.js.map +1 -0
  77. package/src/lib/date/date.validator.js.map +0 -1
@@ -0,0 +1,731 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expandUniqueDateCellsFunction = exports.groupUniqueDateCells = exports.dateCellEndIndex = exports.dateCellRangeHasRange = exports.expandDateCellRange = exports.dateRelativeStateForDateCellRangeComparedToIndex = exports.getNextDateCellTimingIndex = exports.dateCellRangesFullyCoverDateCellRangeFunction = exports.dateCellRangeBlocksCount = exports.dateCellRangeBlocksCountInfo = exports.isDateCellWithinDateCellRange = exports.isDateCellWithinDateCellRangeFunction = exports.filterDateCellsInDateCellRange = exports.allIndexesInDateCellRanges = exports.allIndexesInDateCellRange = exports.groupToDateCellRanges = exports.sortDateCellRanges = exports.sortDateCellRangeAndSizeFunction = exports.dateCellRangeOverlapsRange = exports.dateCellRangeOverlapsRangeFunction = exports.dateCellRangeIncludedByRangeFunction = exports.dateCellRangeWithRange = exports.dateCellRangeWithRangeFromIndex = exports.dateCellRange = exports.getLeastAndGreatestDateCellIndexInDateCellRanges = exports.getGreatestDateCellIndexInDateCellRanges = exports.getLeastDateCellIndexInDateCellRanges = exports.isValidDateCellRangeSeries = exports.isValidDateCellRange = exports.isDateCellRange = exports.DateCellRange = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const util_1 = require("@dereekb/util");
6
+ const class_transformer_1 = require("class-transformer");
7
+ const class_validator_1 = require("class-validator");
8
+ const date_cell_1 = require("./date.cell");
9
+ class DateCellRange extends date_cell_1.DateCell {
10
+ constructor(template) {
11
+ super(template);
12
+ if (template) {
13
+ this.to = template.to;
14
+ }
15
+ }
16
+ }
17
+ tslib_1.__decorate([
18
+ (0, class_transformer_1.Expose)(),
19
+ (0, class_validator_1.IsNumber)(),
20
+ (0, class_validator_1.IsOptional)(),
21
+ (0, class_validator_1.Min)(0),
22
+ tslib_1.__metadata("design:type", Number)
23
+ ], DateCellRange.prototype, "to", void 0);
24
+ exports.DateCellRange = DateCellRange;
25
+ /**
26
+ * Returns true if the input is a DateCellRange.
27
+ *
28
+ * Does not check validity. Use isValidDateCellRange()
29
+ *
30
+ * @param input
31
+ * @returns
32
+ */
33
+ function isDateCellRange(input) {
34
+ return typeof input === 'object' ? (Number.isInteger(input.i) && input.to === undefined) || Number.isInteger(input.to) : false;
35
+ }
36
+ exports.isDateCellRange = isDateCellRange;
37
+ /**
38
+ * Returns true if the input is a valid DateCellRange.
39
+ *
40
+ * @param input
41
+ * @returns
42
+ */
43
+ function isValidDateCellRange(input) {
44
+ const { i, to } = input;
45
+ if (!(0, date_cell_1.isValidDateCellIndex)(i)) {
46
+ return false;
47
+ }
48
+ else if (to != null && (!(0, date_cell_1.isValidDateCellIndex)(to) || to < i)) {
49
+ return false;
50
+ }
51
+ return true;
52
+ }
53
+ exports.isValidDateCellRange = isValidDateCellRange;
54
+ /**
55
+ * Returns true if the input is a sorted DateCellRange array and there are no repeat indexes.
56
+ *
57
+ * @param input
58
+ * @returns
59
+ */
60
+ function isValidDateCellRangeSeries(input) {
61
+ if (!Array.isArray(input)) {
62
+ return false;
63
+ }
64
+ const invalidRange = input.findIndex((range) => !isValidDateCellRange(range));
65
+ if (invalidRange !== -1) {
66
+ return false;
67
+ }
68
+ let greatestIndex = -1;
69
+ for (let i = 0; i < input.length; i += 1) {
70
+ const range = input[i];
71
+ if (range.i <= greatestIndex) {
72
+ return false;
73
+ }
74
+ else {
75
+ const nextGreatestIndex = range.to || range.i; // to is greater than or equal to i in a valid date block range.
76
+ greatestIndex = nextGreatestIndex;
77
+ }
78
+ }
79
+ return true;
80
+ }
81
+ exports.isValidDateCellRangeSeries = isValidDateCellRangeSeries;
82
+ /**
83
+ * Returns the lowest index between all the input date block ranges. Returns 0 by default if there is no minimum or input blocks.
84
+ *
85
+ * The input range is not expected to be sorted.
86
+ */
87
+ function getLeastDateCellIndexInDateCellRanges(input) {
88
+ var _a, _b;
89
+ return (_b = (_a = getLeastAndGreatestDateCellIndexInDateCellRanges(input)) === null || _a === void 0 ? void 0 : _a.leastIndex) !== null && _b !== void 0 ? _b : 0;
90
+ }
91
+ exports.getLeastDateCellIndexInDateCellRanges = getLeastDateCellIndexInDateCellRanges;
92
+ /**
93
+ * Returns the largest index between all the input date block ranges. Returns 0 by default.
94
+ *
95
+ * The input range is not expected to be sorted.
96
+ */
97
+ function getGreatestDateCellIndexInDateCellRanges(input) {
98
+ var _a, _b;
99
+ return (_b = (_a = getLeastAndGreatestDateCellIndexInDateCellRanges(input)) === null || _a === void 0 ? void 0 : _a.greatestIndex) !== null && _b !== void 0 ? _b : 0;
100
+ }
101
+ exports.getGreatestDateCellIndexInDateCellRanges = getGreatestDateCellIndexInDateCellRanges;
102
+ /**
103
+ * Returns the largest index between all the input date block ranges. Returns null if the input is empty.
104
+ *
105
+ * The input range is not expected to be sorted.
106
+ */
107
+ function getLeastAndGreatestDateCellIndexInDateCellRanges(input) {
108
+ if (!input.length) {
109
+ return null;
110
+ }
111
+ let leastIndex = Number.MAX_SAFE_INTEGER;
112
+ let greatestIndex = 0;
113
+ let leastIndexItem = input[0];
114
+ let greatestIndexItem = input[0];
115
+ for (let i = 0; i < input.length; i += 1) {
116
+ const range = input[i];
117
+ const leastRangeIndex = range.i;
118
+ const greatestRangeIndex = range.to || range.i;
119
+ if (leastRangeIndex < leastIndex) {
120
+ leastIndex = leastRangeIndex;
121
+ leastIndexItem = range;
122
+ }
123
+ if (greatestRangeIndex > greatestIndex) {
124
+ greatestIndex = greatestRangeIndex;
125
+ greatestIndexItem = range;
126
+ }
127
+ }
128
+ return {
129
+ leastIndex,
130
+ leastIndexItem,
131
+ greatestIndex,
132
+ greatestIndexItem
133
+ };
134
+ }
135
+ exports.getLeastAndGreatestDateCellIndexInDateCellRanges = getLeastAndGreatestDateCellIndexInDateCellRanges;
136
+ /**
137
+ * Creates a DateCellRange
138
+ *
139
+ * @param i
140
+ * @param to
141
+ * @returns
142
+ */
143
+ function dateCellRange(i, to) {
144
+ return { i, to: to !== null && to !== void 0 ? to : i };
145
+ }
146
+ exports.dateCellRange = dateCellRange;
147
+ /**
148
+ * Creates a DateCellRangeWithRange from the input DateCellIndex.
149
+ *
150
+ * @param dateCellIndex
151
+ * @returns
152
+ */
153
+ function dateCellRangeWithRangeFromIndex(dateCellIndex) {
154
+ return dateCellRange(dateCellIndex, dateCellIndex);
155
+ }
156
+ exports.dateCellRangeWithRangeFromIndex = dateCellRangeWithRangeFromIndex;
157
+ /**
158
+ * Creates a DateCellRangeWithRange from the input DateCellIndex, DateCell, or DateCellRange.
159
+ *
160
+ * @param input
161
+ * @returns
162
+ */
163
+ function dateCellRangeWithRange(input) {
164
+ if (typeof input === 'number') {
165
+ return dateCellRangeWithRangeFromIndex(input);
166
+ }
167
+ else {
168
+ return dateCellRange(input.i, input.to);
169
+ }
170
+ }
171
+ exports.dateCellRangeWithRange = dateCellRangeWithRange;
172
+ /**
173
+ * Creates a DateCellRangeIncludedByRangeFunction
174
+ *
175
+ * @param inputRange
176
+ * @returns
177
+ */
178
+ function dateCellRangeIncludedByRangeFunction(inputRange) {
179
+ const { i, to } = dateCellRangeWithRange(inputRange);
180
+ return (input) => {
181
+ var _a;
182
+ const range = dateCellRangeWithRange(input);
183
+ return range.i <= i && ((_a = range === null || range === void 0 ? void 0 : range.to) !== null && _a !== void 0 ? _a : range.i) >= to;
184
+ };
185
+ }
186
+ exports.dateCellRangeIncludedByRangeFunction = dateCellRangeIncludedByRangeFunction;
187
+ /**
188
+ * Creates a DateCellRangeOverlapsRangeFunction
189
+ *
190
+ * @param inputRange
191
+ * @returns
192
+ */
193
+ function dateCellRangeOverlapsRangeFunction(inputRange) {
194
+ const { i, to } = dateCellRangeWithRange(inputRange);
195
+ return (input) => {
196
+ var _a;
197
+ const range = dateCellRangeWithRange(input);
198
+ return range.i <= to && ((_a = range === null || range === void 0 ? void 0 : range.to) !== null && _a !== void 0 ? _a : range.i) >= i;
199
+ };
200
+ }
201
+ exports.dateCellRangeOverlapsRangeFunction = dateCellRangeOverlapsRangeFunction;
202
+ /**
203
+ * Returns true if either of the ranges overlap eachother.
204
+ *
205
+ * @param rangeA
206
+ * @param rangeB
207
+ * @returns
208
+ */
209
+ function dateCellRangeOverlapsRange(rangeA, rangeB) {
210
+ return dateCellRangeOverlapsRangeFunction(rangeA)(rangeB);
211
+ }
212
+ exports.dateCellRangeOverlapsRange = dateCellRangeOverlapsRange;
213
+ /**
214
+ * Sorts the input ranges by index and distance (to values).
215
+ *
216
+ * In many cases sortAscendingIndexNumberRefFunction may be preferential since
217
+ *
218
+ * @returns
219
+ */
220
+ function sortDateCellRangeAndSizeFunction() {
221
+ return (a, b) => { var _a, _b; return a.i - b.i || ((_a = a.to) !== null && _a !== void 0 ? _a : a.i) - ((_b = b.to) !== null && _b !== void 0 ? _b : b.i); };
222
+ }
223
+ exports.sortDateCellRangeAndSizeFunction = sortDateCellRangeAndSizeFunction;
224
+ /**
225
+ * Sorts the input date ranges. This will retain the before/after order while also sorting items by index.
226
+ *
227
+ * @param input
228
+ * @returns
229
+ */
230
+ function sortDateCellRanges(input) {
231
+ return input.sort((0, util_1.sortAscendingIndexNumberRefFunction)());
232
+ }
233
+ exports.sortDateCellRanges = sortDateCellRanges;
234
+ /**
235
+ * Groups the input values into DateCellRange values.
236
+ *
237
+ * @param input
238
+ */
239
+ function groupToDateCellRanges(input) {
240
+ var _a;
241
+ if (input.length === 0) {
242
+ return [];
243
+ }
244
+ // sort by index in ascending order
245
+ const blocks = sortDateCellRanges(input);
246
+ function newBlockFromBlocksArrayIndex(blocksArrayIndex) {
247
+ const { i, to } = blocks[blocksArrayIndex];
248
+ return {
249
+ i,
250
+ to: to !== null && to !== void 0 ? to : i
251
+ };
252
+ }
253
+ // start at the first block
254
+ let current = newBlockFromBlocksArrayIndex(0);
255
+ const results = [];
256
+ for (let i = 1; i < blocks.length; i += 1) {
257
+ const block = blocks[i];
258
+ const isContinuous = block.i <= current.to + 1;
259
+ if (isContinuous) {
260
+ // extend the current block.
261
+ current.to = (_a = blocks[i].to) !== null && _a !== void 0 ? _a : blocks[i].i;
262
+ }
263
+ else {
264
+ // complete/create new block.
265
+ results.push(current);
266
+ current = newBlockFromBlocksArrayIndex(i);
267
+ }
268
+ }
269
+ results.push(current);
270
+ return results;
271
+ }
272
+ exports.groupToDateCellRanges = groupToDateCellRanges;
273
+ /**
274
+ * Returns an array containing all indexes in the date block range.
275
+ */
276
+ function allIndexesInDateCellRange(input) {
277
+ return input.to != null ? (0, util_1.range)(input.i, input.to + 1) : [input.i];
278
+ }
279
+ exports.allIndexesInDateCellRange = allIndexesInDateCellRange;
280
+ /**
281
+ * Returns the set of all indexes within the input.
282
+ *
283
+ * @param input
284
+ * @returns
285
+ */
286
+ function allIndexesInDateCellRanges(input) {
287
+ const set = new Set();
288
+ input.forEach((x) => {
289
+ if (typeof x === 'number') {
290
+ set.add(x);
291
+ }
292
+ else {
293
+ const allIndexes = allIndexesInDateCellRange(x);
294
+ (0, util_1.addToSet)(set, allIndexes);
295
+ }
296
+ });
297
+ return set;
298
+ }
299
+ exports.allIndexesInDateCellRanges = allIndexesInDateCellRanges;
300
+ /**
301
+ * Returns blocks that are only in the given DateCellRange.
302
+ *
303
+ * @param blocks
304
+ * @param range
305
+ * @returns
306
+ */
307
+ function filterDateCellsInDateCellRange(blocks, range) {
308
+ const dateCellIsWithinDateCellRange = isDateCellWithinDateCellRangeFunction(range);
309
+ return blocks.filter(dateCellIsWithinDateCellRange);
310
+ }
311
+ exports.filterDateCellsInDateCellRange = filterDateCellsInDateCellRange;
312
+ function isDateCellWithinDateCellRangeFunction(inputRange) {
313
+ const range = dateCellRangeWithRange(inputRange);
314
+ return (input) => {
315
+ var _a;
316
+ if (typeof input === 'number') {
317
+ input = { i: input };
318
+ }
319
+ if (input.i >= range.i) {
320
+ const to = (_a = input.to) !== null && _a !== void 0 ? _a : input.i;
321
+ return to <= range.to;
322
+ }
323
+ return false;
324
+ };
325
+ }
326
+ exports.isDateCellWithinDateCellRangeFunction = isDateCellWithinDateCellRangeFunction;
327
+ /**
328
+ * Returns true if the first DateCell or DateCellRange contains the second input.
329
+ *
330
+ * @param range
331
+ * @param isContainedWithin
332
+ * @returns
333
+ */
334
+ function isDateCellWithinDateCellRange(range, contains) {
335
+ return isDateCellWithinDateCellRangeFunction(range)(dateCellRangeWithRange(contains));
336
+ }
337
+ exports.isDateCellWithinDateCellRange = isDateCellWithinDateCellRange;
338
+ /**
339
+ * Counts the number of blocks in the input range.
340
+ *
341
+ * @param inputDateCellRange
342
+ * @returns
343
+ */
344
+ function dateCellRangeBlocksCountInfo(inputDateCellRange) {
345
+ const group = groupToDateCellRanges((0, util_1.asArray)(inputDateCellRange));
346
+ let count = 0;
347
+ let total = 0;
348
+ group.forEach((x) => {
349
+ const blocks = Math.abs(x.to - x.i) + 1; // +1 for inclusivity
350
+ count += blocks;
351
+ const size = (0, util_1.sumOfIntegersBetween)(x.i, x.to);
352
+ total += size;
353
+ });
354
+ return {
355
+ count,
356
+ total,
357
+ average: count > 0 ? total / count : 0
358
+ };
359
+ }
360
+ exports.dateCellRangeBlocksCountInfo = dateCellRangeBlocksCountInfo;
361
+ /**
362
+ * Counts the number of blocks in the input range.
363
+ *
364
+ * @param inputDateCellRange
365
+ * @returns
366
+ */
367
+ function dateCellRangeBlocksCount(inputDateCellRange) {
368
+ return dateCellRangeBlocksCountInfo(inputDateCellRange).count;
369
+ }
370
+ exports.dateCellRangeBlocksCount = dateCellRangeBlocksCount;
371
+ /**
372
+ * Creates a dateCellRangesFullyCoverDateCellRangeFunction
373
+ *
374
+ * @param ranges
375
+ * @returns
376
+ */
377
+ function dateCellRangesFullyCoverDateCellRangeFunction(ranges) {
378
+ const groupedRanges = Array.isArray(ranges) ? groupToDateCellRanges(ranges) : [dateCellRangeWithRange(ranges)];
379
+ return (inputRange) => {
380
+ const fn = dateCellRangeIncludedByRangeFunction(inputRange);
381
+ return groupedRanges.findIndex(fn) !== -1;
382
+ };
383
+ }
384
+ exports.dateCellRangesFullyCoverDateCellRangeFunction = dateCellRangesFullyCoverDateCellRangeFunction;
385
+ /**
386
+ * Computes a GetNextDateCellTimingIndexResult from the input.
387
+ *
388
+ * @param input
389
+ */
390
+ function getNextDateCellTimingIndex(input) {
391
+ var _a, _b, _c;
392
+ const { ranges, currentIndex } = input;
393
+ const relativeStateGroups = (0, util_1.makeValuesGroupMap)((0, util_1.asArray)(ranges), (range) => {
394
+ return dateRelativeStateForDateCellRangeComparedToIndex(range, currentIndex);
395
+ });
396
+ const pastResults = (_a = relativeStateGroups.get('past')) !== null && _a !== void 0 ? _a : [];
397
+ const presentResults = (_b = relativeStateGroups.get('present')) !== null && _b !== void 0 ? _b : [];
398
+ const futureResults = (_c = relativeStateGroups.get('future')) !== null && _c !== void 0 ? _c : [];
399
+ const currentResult = presentResults[0];
400
+ let nextResult;
401
+ let nextIndex = currentIndex + 1;
402
+ const nextResultFromPresent = presentResults.find((x) => dateRelativeStateForDateCellRangeComparedToIndex(x, nextIndex) === 'present');
403
+ if (nextResultFromPresent) {
404
+ nextResult = nextResultFromPresent;
405
+ }
406
+ else {
407
+ // search through the future indexes, looking for the one with the lowest index.
408
+ const greatestAndLeastIndexResult = getLeastAndGreatestDateCellIndexInDateCellRanges(futureResults);
409
+ if (greatestAndLeastIndexResult) {
410
+ nextIndex = greatestAndLeastIndexResult.leastIndex;
411
+ nextResult = greatestAndLeastIndexResult.leastIndexItem;
412
+ }
413
+ else {
414
+ nextIndex = undefined;
415
+ }
416
+ }
417
+ return {
418
+ currentResult,
419
+ nextIndex,
420
+ nextResult,
421
+ pastResults,
422
+ presentResults,
423
+ futureResults
424
+ };
425
+ }
426
+ exports.getNextDateCellTimingIndex = getNextDateCellTimingIndex;
427
+ /**
428
+ * Returns the DateRelativeState for the given index and range.
429
+ *
430
+ * @param nowIndex
431
+ * @param range
432
+ */
433
+ function dateRelativeStateForDateCellRangeComparedToIndex(range, nowIndex) {
434
+ const { i, to } = dateCellRange(range.i, range.to);
435
+ let state;
436
+ if (i > nowIndex) {
437
+ state = 'future'; // if i greater, then the range is in the future.
438
+ }
439
+ else if (to < nowIndex) {
440
+ state = 'past'; // if i is less than or equal, and to is less than i, then it is in the past
441
+ }
442
+ else {
443
+ state = 'present';
444
+ }
445
+ return state;
446
+ }
447
+ exports.dateRelativeStateForDateCellRangeComparedToIndex = dateRelativeStateForDateCellRangeComparedToIndex;
448
+ /**
449
+ * Expands a DateCellRange into an array of DateCell values.
450
+ *
451
+ * @param block
452
+ * @returns
453
+ */
454
+ function expandDateCellRange(block) {
455
+ return (0, util_1.range)(block.i, dateCellEndIndex(block) + 1).map((i) => {
456
+ return Object.assign(Object.assign({}, block), { i, to: i }); // copy block, set to as i
457
+ });
458
+ }
459
+ exports.expandDateCellRange = expandDateCellRange;
460
+ /**
461
+ * Returns true if the input DateCellRange is longer than 1 block (I.E. has a "to" value greater than it's "i" value).
462
+ *
463
+ * @param input
464
+ */
465
+ function dateCellRangeHasRange(input) {
466
+ return input.to != null && input.to > input.i;
467
+ }
468
+ exports.dateCellRangeHasRange = dateCellRangeHasRange;
469
+ /**
470
+ * Reads the to index if it exists, or returns the block's index itself.
471
+ *
472
+ * @param input
473
+ * @returns
474
+ */
475
+ function dateCellEndIndex(input) {
476
+ var _a;
477
+ return (_a = input.to) !== null && _a !== void 0 ? _a : input.i;
478
+ }
479
+ exports.dateCellEndIndex = dateCellEndIndex;
480
+ /**
481
+ * Groups all input DateCellRange or UniqueDateCell values into a UniqueDateCellRangeGroup value amd sorts the input.
482
+ */
483
+ function groupUniqueDateCells(input) {
484
+ var _a;
485
+ const blocks = sortDateCellRanges([...input]);
486
+ const i = 0;
487
+ let to;
488
+ if (blocks.length === 0) {
489
+ to = i;
490
+ }
491
+ else {
492
+ const lastBlock = (0, util_1.lastValue)(blocks);
493
+ to = (_a = lastBlock.to) !== null && _a !== void 0 ? _a : lastBlock.i;
494
+ }
495
+ return {
496
+ i,
497
+ to,
498
+ blocks
499
+ };
500
+ }
501
+ exports.groupUniqueDateCells = groupUniqueDateCells;
502
+ function expandUniqueDateCellsFunction(config) {
503
+ const { startAtIndex = 0, endAtIndex, fillOption: fill, fillFactory: inputFillFactory, retainOnOverlap: inputRetainOnOverlap } = config;
504
+ const retainOnOverlap = inputRetainOnOverlap !== null && inputRetainOnOverlap !== void 0 ? inputRetainOnOverlap : 'next';
505
+ const maxAllowedIndex = endAtIndex !== null && endAtIndex !== void 0 ? endAtIndex : Number.MAX_SAFE_INTEGER;
506
+ const fillFactory = inputFillFactory;
507
+ if (!fillFactory && fill === 'fill') {
508
+ throw new Error('fillFactory is required when fillOption is "fill".');
509
+ }
510
+ return (input, newBlocks) => {
511
+ const inputGroup = Array.isArray(input) ? groupUniqueDateCells(input) : input;
512
+ const sorted = inputGroup.blocks.map((block) => ({ priority: 'current', block }));
513
+ if (newBlocks != null) {
514
+ const inputOverwriteGroup = Array.isArray(newBlocks) ? groupUniqueDateCells(newBlocks) : newBlocks;
515
+ (0, util_1.mergeArrayIntoArray)(sorted, inputOverwriteGroup.blocks.map((block) => ({ priority: 'next', block }))).sort((a, b) => a.block.i - b.block.i);
516
+ }
517
+ const blocks = [];
518
+ const discarded = [];
519
+ let current = sorted[0];
520
+ let currentNextIndex;
521
+ let next = sorted[1];
522
+ let nextStartIndex;
523
+ let i = 0;
524
+ let latestTo = startAtIndex - 1;
525
+ function addBlockWithRange(inputBlock, i, inputTo = i) {
526
+ // Add in any necessary gap block first
527
+ const gapSizeBetweenBlocks = i - (latestTo + 1);
528
+ if (gapSizeBetweenBlocks > 0) {
529
+ // start at the startAtIndex at a minimum
530
+ const gapStartIndex = Math.max(latestTo + 1, startAtIndex);
531
+ addGapBlock(gapStartIndex, i - 1);
532
+ }
533
+ const to = Math.min(inputTo, maxAllowedIndex) || 0;
534
+ const block = Object.assign(Object.assign({}, inputBlock), { i,
535
+ to });
536
+ blocks.push(block);
537
+ latestTo = to;
538
+ return block;
539
+ }
540
+ function completeBlocks() {
541
+ // extend or fill if there is an endAtIndex value present
542
+ if (endAtIndex != null && latestTo < endAtIndex) {
543
+ addGapBlock(latestTo + 1, endAtIndex);
544
+ }
545
+ }
546
+ function addGapBlock(i, inputTo = i) {
547
+ const to = Math.min(inputTo, maxAllowedIndex);
548
+ if (fill === 'fill') {
549
+ const dateCellRange = {
550
+ i,
551
+ to
552
+ };
553
+ const block = fillFactory(dateCellRange);
554
+ addBlockWithRange(block, i, to !== null && to !== void 0 ? to : i);
555
+ }
556
+ else if (blocks.length > 0) {
557
+ // do not extend if no blocks have been pushed.
558
+ const blockToExtend = (0, util_1.lastValue)(blocks);
559
+ blockToExtend.to = inputTo;
560
+ }
561
+ latestTo = to;
562
+ }
563
+ function continueToNext(use, priority) {
564
+ i += 1;
565
+ current = use != null ? { block: use, priority } : sorted[i];
566
+ next = sorted[i + 1];
567
+ if (next) {
568
+ nextStartIndex = next.block.i;
569
+ // complete loop once past the max allowed index
570
+ if (nextStartIndex > maxAllowedIndex) {
571
+ continueLoop = false;
572
+ }
573
+ else {
574
+ const nextEndIndex = dateCellEndIndex(next.block);
575
+ if (nextEndIndex <= latestTo) {
576
+ discardCurrent(); // skip until next is not less than or equal to the latest to
577
+ continueToNext();
578
+ }
579
+ }
580
+ }
581
+ else {
582
+ continueLoop = false;
583
+ }
584
+ }
585
+ function discard(pair) {
586
+ discarded.push(pair.block);
587
+ }
588
+ function discardCurrent() {
589
+ discard(current);
590
+ }
591
+ function discardNext() {
592
+ discard(next);
593
+ i += 1;
594
+ continueToNext();
595
+ }
596
+ let continueLoop = Boolean(next); // only loop if next is defined, otherwise we just add the final item.
597
+ /**
598
+ * Used to determine how to handle two neighboring objects.
599
+ */
600
+ function shouldRetainCurrentOverNext() {
601
+ if (current.priority === next.priority) {
602
+ return retainOnOverlap === 'current';
603
+ }
604
+ else {
605
+ return current.priority === retainOnOverlap;
606
+ }
607
+ }
608
+ while (continueLoop) {
609
+ currentNextIndex = current.block.i;
610
+ nextStartIndex = next.block.i;
611
+ const currentEndIndex = dateCellEndIndex(current.block);
612
+ const nextEndIndex = dateCellEndIndex(next.block);
613
+ if (nextStartIndex < startAtIndex || currentEndIndex < startAtIndex) {
614
+ // do nothing if the next index is still before the current start index.
615
+ discardCurrent();
616
+ continueToNext();
617
+ }
618
+ else if (currentNextIndex === nextStartIndex) {
619
+ // if next has the same range as current, then look at the tie-breaker
620
+ if (nextEndIndex === currentEndIndex) {
621
+ // if they're both on the same index, then take the one based on the overwrite value
622
+ if (shouldRetainCurrentOverNext()) {
623
+ // add current
624
+ addBlockWithRange(current.block, currentNextIndex, nextEndIndex);
625
+ // discard and skip the "next" value
626
+ discardNext();
627
+ }
628
+ else {
629
+ // discard the current
630
+ discardCurrent();
631
+ // move on to next
632
+ continueToNext();
633
+ }
634
+ }
635
+ else if (nextEndIndex > currentEndIndex) {
636
+ // handle overlap
637
+ if (shouldRetainCurrentOverNext()) {
638
+ // add current
639
+ addBlockWithRange(current.block, currentNextIndex, currentEndIndex);
640
+ // change next to start at the next range
641
+ continueToNext(Object.assign(Object.assign({}, next.block), { i: currentEndIndex + 1, to: nextEndIndex }), next.priority);
642
+ }
643
+ else {
644
+ //
645
+ discardCurrent();
646
+ continueToNext();
647
+ }
648
+ }
649
+ else {
650
+ // the next item ends before the current item.
651
+ if (shouldRetainCurrentOverNext()) {
652
+ // discard the next value.
653
+ discard(next);
654
+ // continue with the current value
655
+ continueToNext(current.block, current.priority);
656
+ }
657
+ else {
658
+ // add the next item first since it overwrites the current
659
+ addBlockWithRange(next.block, nextStartIndex, nextEndIndex);
660
+ // continue with the current item as next.
661
+ continueToNext(Object.assign(Object.assign({}, current.block), { i: nextEndIndex + 1, to: currentEndIndex }), current.priority);
662
+ }
663
+ }
664
+ }
665
+ else {
666
+ // Check for any overlap
667
+ if (currentEndIndex >= nextStartIndex) {
668
+ // handle overlap
669
+ if (shouldRetainCurrentOverNext()) {
670
+ // add current
671
+ addBlockWithRange(current.block, currentNextIndex, currentEndIndex);
672
+ if (nextEndIndex > currentEndIndex) {
673
+ // change next to start at the next range
674
+ continueToNext(Object.assign(Object.assign({}, next.block), { i: currentEndIndex + 1, to: nextEndIndex }), next.priority);
675
+ }
676
+ else {
677
+ // continue normally
678
+ continueToNext();
679
+ }
680
+ }
681
+ else {
682
+ // add current up to the start index of next
683
+ addBlockWithRange(current.block, currentNextIndex, nextStartIndex - 1);
684
+ // check if the next one is fully contained
685
+ if (nextEndIndex < currentEndIndex) {
686
+ // add the next
687
+ addBlockWithRange(next.block, nextStartIndex, nextEndIndex);
688
+ // continue with the current
689
+ continueToNext(Object.assign(Object.assign({}, current.block), { i: nextEndIndex + 1, to: currentEndIndex }), next.priority);
690
+ }
691
+ else {
692
+ // continue to next
693
+ continueToNext();
694
+ }
695
+ }
696
+ }
697
+ else {
698
+ // no overlap
699
+ // add the current block
700
+ addBlockWithRange(current.block, currentNextIndex, currentEndIndex);
701
+ // continue to next
702
+ continueToNext();
703
+ }
704
+ }
705
+ }
706
+ if (current != null) {
707
+ // if current != null, then atleast one block was input/remaining.
708
+ const lastStartIndex = current.block.i;
709
+ const lastEndIndex = dateCellEndIndex(current.block);
710
+ if (lastEndIndex < startAtIndex || lastEndIndex <= latestTo || lastStartIndex > maxAllowedIndex) {
711
+ // if the block ends before the start index, then do nothing.
712
+ discardCurrent();
713
+ }
714
+ else {
715
+ addBlockWithRange(current.block, Math.max(startAtIndex, lastStartIndex), Math.min(lastEndIndex, maxAllowedIndex));
716
+ }
717
+ completeBlocks();
718
+ }
719
+ else if (fill === 'fill') {
720
+ completeBlocks();
721
+ }
722
+ const result = {
723
+ i: 0,
724
+ blocks,
725
+ discarded
726
+ };
727
+ return result;
728
+ };
729
+ }
730
+ exports.expandUniqueDateCellsFunction = expandUniqueDateCellsFunction;
731
+ //# sourceMappingURL=date.cell.index.js.map