@naturalcycles/js-lib 14.98.3 → 14.99.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.
@@ -137,7 +137,16 @@ export declare function _mapToObject<T, V>(array: T[], mapper: (item: T) => [key
137
137
  * Based on: https://stackoverflow.com/a/12646864/4919972
138
138
  */
139
139
  export declare function _shuffle<T>(array: T[], mutate?: boolean): T[];
140
+ /**
141
+ * Returns last item of non-empty array.
142
+ * Throws if array is empty.
143
+ */
144
+ export declare function _last<T>(array: T[]): T;
140
145
  /**
141
146
  * Returns last item of the array (or undefined if array is empty).
142
147
  */
143
- export declare function _last<T>(array: T[]): T | undefined;
148
+ export declare function _lastOrUndefined<T>(array: T[]): T | undefined;
149
+ export declare function _minOrUndefined<T>(array: T[]): T | undefined;
150
+ export declare function _min<T>(array: T[]): T;
151
+ export declare function _maxOrUndefined<T>(array: T[]): T | undefined;
152
+ export declare function _max<T>(array: T[]): T;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._last = exports._shuffle = exports._mapToObject = exports._sumBy = exports._sum = exports._difference = exports._intersection = exports._countBy = exports._dropRightWhile = exports._dropWhile = exports._takeRightWhile = exports._takeWhile = exports._findLast = exports._sortBy = exports._groupBy = exports._by = exports._uniqBy = exports._uniq = exports._flattenDeep = exports._flatten = exports._chunk = void 0;
3
+ exports._max = exports._maxOrUndefined = exports._min = exports._minOrUndefined = exports._lastOrUndefined = exports._last = exports._shuffle = exports._mapToObject = exports._sumBy = exports._sum = exports._difference = exports._intersection = exports._countBy = exports._dropRightWhile = exports._dropWhile = exports._takeRightWhile = exports._takeWhile = exports._findLast = exports._sortBy = exports._groupBy = exports._by = exports._uniqBy = exports._uniq = exports._flattenDeep = exports._flatten = exports._chunk = void 0;
4
4
  /**
5
5
  * Creates an array of elements split into groups the length of size. If collection can’t be split evenly, the
6
6
  * final chunk will be the remaining elements.
@@ -260,9 +260,43 @@ function _shuffle(array, mutate = false) {
260
260
  }
261
261
  exports._shuffle = _shuffle;
262
262
  /**
263
- * Returns last item of the array (or undefined if array is empty).
263
+ * Returns last item of non-empty array.
264
+ * Throws if array is empty.
264
265
  */
265
266
  function _last(array) {
267
+ if (!array.length)
268
+ throw new Error('_last called on empty array');
266
269
  return array[array.length - 1];
267
270
  }
268
271
  exports._last = _last;
272
+ /**
273
+ * Returns last item of the array (or undefined if array is empty).
274
+ */
275
+ function _lastOrUndefined(array) {
276
+ return array[array.length - 1];
277
+ }
278
+ exports._lastOrUndefined = _lastOrUndefined;
279
+ function _minOrUndefined(array) {
280
+ if (!array.length)
281
+ return;
282
+ return _min(array);
283
+ }
284
+ exports._minOrUndefined = _minOrUndefined;
285
+ function _min(array) {
286
+ if (!array.length)
287
+ throw new Error('_min called on empty array');
288
+ return array.reduce((min, item) => (min <= item ? min : item));
289
+ }
290
+ exports._min = _min;
291
+ function _maxOrUndefined(array) {
292
+ if (!array.length)
293
+ return;
294
+ return _max(array);
295
+ }
296
+ exports._maxOrUndefined = _maxOrUndefined;
297
+ function _max(array) {
298
+ if (!array.length)
299
+ throw new Error('_max called on empty array');
300
+ return array.reduce((max, item) => (max >= item ? max : item));
301
+ }
302
+ exports._max = _max;
@@ -1,8 +1,10 @@
1
1
  import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types';
2
2
  import { LocalTime } from './localTime';
3
- export declare type LocalDateUnit = 'year' | 'month' | 'day';
3
+ export declare type LocalDateUnit = LocalDateUnitStrict | 'week';
4
+ export declare type LocalDateUnitStrict = 'year' | 'month' | 'day';
4
5
  export declare type Inclusiveness = '()' | '[]' | '[)' | '(]';
5
6
  export declare type LocalDateConfig = LocalDate | IsoDateString;
7
+ export declare type LocalDateFormatter = (ld: LocalDate) => string;
6
8
  /**
7
9
  * @experimental
8
10
  */
@@ -28,13 +30,13 @@ export declare class LocalDate {
28
30
  static today(): LocalDate;
29
31
  static todayUTC(): LocalDate;
30
32
  static sort(items: LocalDate[], mutate?: boolean, descending?: boolean): LocalDate[];
31
- static earliestOrUndefined(items: LocalDate[]): LocalDate | undefined;
32
- static earliest(items: LocalDate[]): LocalDate;
33
- static latestOrUndefined(items: LocalDate[]): LocalDate | undefined;
34
- static latest(items: LocalDate[]): LocalDate;
33
+ static earliestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined;
34
+ static earliest(items: LocalDateConfig[]): LocalDate;
35
+ static latestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined;
36
+ static latest(items: LocalDateConfig[]): LocalDate;
35
37
  static range(min: LocalDateConfig, max: LocalDateConfig, incl?: Inclusiveness, step?: number, stepUnit?: LocalDateUnit): LocalDate[];
36
- get(unit: LocalDateUnit): number;
37
- set(unit: LocalDateUnit, v: number, mutate?: boolean): LocalDate;
38
+ get(unit: LocalDateUnitStrict): number;
39
+ set(unit: LocalDateUnitStrict, v: number, mutate?: boolean): LocalDate;
38
40
  year(): number;
39
41
  year(v: number): LocalDate;
40
42
  month(): number;
@@ -65,8 +67,8 @@ export declare class LocalDate {
65
67
  diff(d: LocalDateConfig, unit: LocalDateUnit): number;
66
68
  add(num: number, unit: LocalDateUnit, mutate?: boolean): LocalDate;
67
69
  subtract(num: number, unit: LocalDateUnit, mutate?: boolean): LocalDate;
68
- startOf(unit: LocalDateUnit): LocalDate;
69
- endOf(unit: LocalDateUnit): LocalDate;
70
+ startOf(unit: LocalDateUnitStrict): LocalDate;
71
+ endOf(unit: LocalDateUnitStrict): LocalDate;
70
72
  static getYearLength(year: number): number;
71
73
  static getMonthLength(year: number, month: number): number;
72
74
  static isLeapYear(year: number): boolean;
@@ -89,6 +91,7 @@ export declare class LocalDate {
89
91
  unix(): UnixTimestampNumber;
90
92
  unixMillis(): number;
91
93
  toJSON(): IsoDateString;
94
+ format(fmt: LocalDateFormatter): string;
92
95
  }
93
96
  /**
94
97
  * Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
@@ -90,16 +90,24 @@ class LocalDate {
90
90
  }
91
91
  static earliest(items) {
92
92
  (0, assert_1._assert)(items.length, 'LocalDate.earliest called on empty array');
93
- return items.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
93
+ return items
94
+ .map(i => LocalDate.of(i))
95
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
94
96
  }
95
97
  static latestOrUndefined(items) {
96
98
  return items.length ? LocalDate.latest(items) : undefined;
97
99
  }
98
100
  static latest(items) {
99
101
  (0, assert_1._assert)(items.length, 'LocalDate.latest called on empty array');
100
- return items.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
102
+ return items
103
+ .map(i => LocalDate.of(i))
104
+ .reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
101
105
  }
102
106
  static range(min, max, incl = '[)', step = 1, stepUnit = 'day') {
107
+ if (stepUnit === 'week') {
108
+ step *= 7;
109
+ stepUnit = 'day';
110
+ }
103
111
  const dates = [];
104
112
  const $min = LocalDate.of(min);
105
113
  const $max = LocalDate.of(max).startOf(stepUnit);
@@ -209,7 +217,7 @@ class LocalDate {
209
217
  if (unit === 'month') {
210
218
  return (this.$year - d.$year) * 12 + (this.$month - d.$month);
211
219
  }
212
- // unit is 'day'
220
+ // unit is 'day' or 'week'
213
221
  let days = this.$day - d.$day;
214
222
  if (d.$year < this.$year) {
215
223
  for (let year = d.$year; year < this.$year; year++) {
@@ -231,10 +239,17 @@ class LocalDate {
231
239
  days -= LocalDate.getMonthLength(d.$year, month);
232
240
  }
233
241
  }
242
+ if (unit === 'week') {
243
+ return Math.floor(days / 7);
244
+ }
234
245
  return days;
235
246
  }
236
247
  add(num, unit, mutate = false) {
237
248
  let { $day, $month, $year } = this;
249
+ if (unit === 'week') {
250
+ num *= 7;
251
+ unit = 'day';
252
+ }
238
253
  if (unit === 'day') {
239
254
  $day += num;
240
255
  }
@@ -364,6 +379,9 @@ class LocalDate {
364
379
  toJSON() {
365
380
  return this.toString();
366
381
  }
382
+ format(fmt) {
383
+ return fmt(this);
384
+ }
367
385
  }
368
386
  exports.LocalDate = LocalDate;
369
387
  /**
@@ -1,7 +1,17 @@
1
1
  import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types';
2
2
  import { Inclusiveness, LocalDate } from './localDate';
3
- export declare type LocalTimeUnit = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second';
3
+ export declare type LocalTimeUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second';
4
+ export declare enum ISODayOfWeek {
5
+ MONDAY = 1,
6
+ TUESDAY = 2,
7
+ WEDNESDAY = 3,
8
+ THURSDAY = 4,
9
+ FRIDAY = 5,
10
+ SATURDAY = 6,
11
+ SUNDAY = 7
12
+ }
4
13
  export declare type LocalTimeConfig = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber;
14
+ export declare type LocalTimeFormatter = (ld: LocalTime) => string;
5
15
  export interface LocalTimeComponents {
6
16
  year: number;
7
17
  month: number;
@@ -42,8 +52,15 @@ export declare class LocalTime {
42
52
  year(v: number): LocalTime;
43
53
  month(): number;
44
54
  month(v: number): LocalTime;
55
+ week(): number;
56
+ week(v: number): LocalTime;
45
57
  day(): number;
46
58
  day(v: number): LocalTime;
59
+ /**
60
+ * Based on ISO: 1-7 is Mon-Sun.
61
+ */
62
+ dayOfWeek(): ISODayOfWeek;
63
+ dayOfWeek(v: ISODayOfWeek): LocalTime;
47
64
  hour(): number;
48
65
  hour(v: number): LocalTime;
49
66
  minute(): number;
@@ -56,11 +73,12 @@ export declare class LocalTime {
56
73
  absDiff(other: LocalTimeConfig, unit: LocalTimeUnit): number;
57
74
  diff(other: LocalTimeConfig, unit: LocalTimeUnit): number;
58
75
  startOf(unit: LocalTimeUnit, mutate?: boolean): LocalTime;
76
+ endOf(unit: LocalTimeUnit, mutate?: boolean): LocalTime;
59
77
  static sort(items: LocalTime[], mutate?: boolean, descending?: boolean): LocalTime[];
60
- static earliestOrUndefined(items: LocalTime[]): LocalTime | undefined;
61
- static earliest(items: LocalTime[]): LocalTime;
62
- static latestOrUndefined(items: LocalTime[]): LocalTime | undefined;
63
- static latest(items: LocalTime[]): LocalTime;
78
+ static earliestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined;
79
+ static earliest(items: LocalTimeConfig[]): LocalTime;
80
+ static latestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined;
81
+ static latest(items: LocalTimeConfig[]): LocalTime;
64
82
  isSame(d: LocalTimeConfig): boolean;
65
83
  isBefore(d: LocalTimeConfig, inclusive?: boolean): boolean;
66
84
  isSameOrBefore(d: LocalTimeConfig): boolean;
@@ -100,6 +118,7 @@ export declare class LocalTime {
100
118
  toStringCompact(seconds?: boolean): string;
101
119
  toString(): string;
102
120
  toJSON(): UnixTimestampNumber;
121
+ format(fmt: LocalTimeFormatter): string;
103
122
  }
104
123
  /**
105
124
  * Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
@@ -1,9 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.localTime = exports.LocalTime = void 0;
3
+ exports.localTime = exports.LocalTime = exports.ISODayOfWeek = void 0;
4
4
  const assert_1 = require("../error/assert");
5
5
  const time_util_1 = require("../time/time.util");
6
6
  const localDate_1 = require("./localDate");
7
+ var ISODayOfWeek;
8
+ (function (ISODayOfWeek) {
9
+ ISODayOfWeek[ISODayOfWeek["MONDAY"] = 1] = "MONDAY";
10
+ ISODayOfWeek[ISODayOfWeek["TUESDAY"] = 2] = "TUESDAY";
11
+ ISODayOfWeek[ISODayOfWeek["WEDNESDAY"] = 3] = "WEDNESDAY";
12
+ ISODayOfWeek[ISODayOfWeek["THURSDAY"] = 4] = "THURSDAY";
13
+ ISODayOfWeek[ISODayOfWeek["FRIDAY"] = 5] = "FRIDAY";
14
+ ISODayOfWeek[ISODayOfWeek["SATURDAY"] = 6] = "SATURDAY";
15
+ ISODayOfWeek[ISODayOfWeek["SUNDAY"] = 7] = "SUNDAY";
16
+ })(ISODayOfWeek = exports.ISODayOfWeek || (exports.ISODayOfWeek = {}));
17
+ const weekStartsOn = 1; // mon, as per ISO
18
+ const MILLISECONDS_IN_WEEK = 604800000;
19
+ // const MILLISECONDS_IN_DAY = 86400000
20
+ // const MILLISECONDS_IN_MINUTE = 60000
21
+ const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
7
22
  /* eslint-disable no-dupe-class-members */
8
23
  /**
9
24
  * @experimental
@@ -107,6 +122,9 @@ class LocalTime {
107
122
  if (unit === 'minute') {
108
123
  return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes();
109
124
  }
125
+ if (unit === 'week') {
126
+ return getWeek(this.$date);
127
+ }
110
128
  // second
111
129
  return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds();
112
130
  }
@@ -131,6 +149,9 @@ class LocalTime {
131
149
  else if (unit === 'second') {
132
150
  this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v);
133
151
  }
152
+ else if (unit === 'week') {
153
+ setWeek(t.$date, v, true);
154
+ }
134
155
  /* eslint-enable @typescript-eslint/no-unused-expressions */
135
156
  return t;
136
157
  }
@@ -140,9 +161,21 @@ class LocalTime {
140
161
  month(v) {
141
162
  return v === undefined ? this.get('month') : this.set('month', v);
142
163
  }
164
+ week(v) {
165
+ return v === undefined ? getWeek(this.$date) : this.set('week', v);
166
+ }
143
167
  day(v) {
144
168
  return v === undefined ? this.get('day') : this.set('day', v);
145
169
  }
170
+ dayOfWeek(v) {
171
+ const dow = (this.$date.getDay() || 7);
172
+ if (v === undefined) {
173
+ return dow;
174
+ }
175
+ if (!VALID_DAYS_OF_WEEK.has(v))
176
+ throw new Error(`Invalid dayOfWeek: ${v}`);
177
+ return this.add(v - dow, 'day');
178
+ }
146
179
  hour(v) {
147
180
  return v === undefined ? this.get('hour') : this.set('hour', v);
148
181
  }
@@ -177,6 +210,10 @@ class LocalTime {
177
210
  return mutate ? this : new LocalTime(d, this.utcMode);
178
211
  }
179
212
  add(num, unit, mutate = false) {
213
+ if (unit === 'week') {
214
+ num *= 7;
215
+ unit = 'day';
216
+ }
180
217
  return this.set(unit, this.get(unit) + num, mutate);
181
218
  }
182
219
  subtract(num, unit, mutate = false) {
@@ -200,6 +237,9 @@ class LocalTime {
200
237
  if (unit === 'day') {
201
238
  r = secDiff / (24 * 60 * 60);
202
239
  }
240
+ else if (unit === 'week') {
241
+ r = secDiff / (7 * 24 * 60 * 60);
242
+ }
203
243
  else if (unit === 'hour') {
204
244
  r = secDiff / (60 * 60);
205
245
  }
@@ -210,7 +250,7 @@ class LocalTime {
210
250
  // unit === 'second'
211
251
  r = secDiff;
212
252
  }
213
- r = r < 0 ? -Math.floor(-r) : Math.floor(r);
253
+ r = Math.trunc(r);
214
254
  if (Object.is(r, -0))
215
255
  return 0;
216
256
  return r;
@@ -219,17 +259,53 @@ class LocalTime {
219
259
  if (unit === 'second')
220
260
  return this;
221
261
  const d = mutate ? this.$date : new Date(this.$date);
222
- d.setMilliseconds(0);
223
- d.setSeconds(0);
262
+ d.setSeconds(0, 0);
224
263
  /* eslint-disable @typescript-eslint/no-unused-expressions */
225
264
  if (unit !== 'minute') {
226
265
  this.utcMode ? d.setUTCMinutes(0) : d.setMinutes(0);
227
266
  if (unit !== 'hour') {
228
267
  this.utcMode ? d.setUTCHours(0) : d.setHours(0);
229
268
  if (unit !== 'day') {
230
- this.utcMode ? d.setUTCDate(0) : d.setDate(0);
231
- if (unit !== 'month') {
269
+ // year, month or week
270
+ if (unit === 'year') {
232
271
  this.utcMode ? d.setUTCMonth(0) : d.setMonth(0);
272
+ this.utcMode ? d.setUTCDate(1) : d.setDate(1);
273
+ }
274
+ else if (unit === 'month') {
275
+ this.utcMode ? d.setUTCDate(1) : d.setDate(1);
276
+ }
277
+ else {
278
+ // week
279
+ startOfWeek(d, true);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
285
+ return mutate ? this : new LocalTime(d, this.utcMode);
286
+ }
287
+ endOf(unit, mutate = false) {
288
+ if (unit === 'second')
289
+ return this;
290
+ const d = mutate ? this.$date : new Date(this.$date);
291
+ d.setSeconds(59, 0);
292
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
293
+ if (unit !== 'minute') {
294
+ this.utcMode ? d.setUTCMinutes(59) : d.setMinutes(59);
295
+ if (unit !== 'hour') {
296
+ this.utcMode ? d.setUTCHours(23) : d.setHours(23);
297
+ if (unit !== 'day') {
298
+ // year, month or week
299
+ if (unit === 'year') {
300
+ this.utcMode ? d.setUTCMonth(11) : d.setMonth(11);
301
+ }
302
+ if (unit === 'week') {
303
+ endOfWeek(d, true);
304
+ }
305
+ else {
306
+ // year or month
307
+ const lastDay = localDate_1.LocalDate.getMonthLength(d.getFullYear(), d.getMonth() + 1);
308
+ this.utcMode ? d.setUTCDate(lastDay) : d.setDate(lastDay);
233
309
  }
234
310
  }
235
311
  }
@@ -252,14 +328,18 @@ class LocalTime {
252
328
  }
253
329
  static earliest(items) {
254
330
  (0, assert_1._assert)(items.length, 'LocalTime.earliest called on empty array');
255
- return items.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
331
+ return items
332
+ .map(i => LocalTime.of(i))
333
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
256
334
  }
257
335
  static latestOrUndefined(items) {
258
336
  return items.length ? LocalTime.latest(items) : undefined;
259
337
  }
260
338
  static latest(items) {
261
339
  (0, assert_1._assert)(items.length, 'LocalTime.latest called on empty array');
262
- return items.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
340
+ return items
341
+ .map(i => LocalTime.of(i))
342
+ .reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
263
343
  }
264
344
  isSame(d) {
265
345
  return this.cmp(d) === 0;
@@ -299,7 +379,6 @@ class LocalTime {
299
379
  return 0;
300
380
  return t1 < t2 ? -1 : 1;
301
381
  }
302
- // todo: endOf
303
382
  components() {
304
383
  if (this.utcMode) {
305
384
  return {
@@ -424,6 +503,9 @@ class LocalTime {
424
503
  toJSON() {
425
504
  return this.unix();
426
505
  }
506
+ format(fmt) {
507
+ return fmt(this);
508
+ }
427
509
  }
428
510
  exports.LocalTime = LocalTime;
429
511
  /**
@@ -433,3 +515,83 @@ function localTime(d) {
433
515
  return d ? LocalTime.of(d) : LocalTime.now();
434
516
  }
435
517
  exports.localTime = localTime;
518
+ // based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
519
+ function getWeek(date) {
520
+ const diff = startOfWeek(date).getTime() - startOfWeekYear(date).getTime();
521
+ return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;
522
+ }
523
+ function setWeek(date, week, mutate = false) {
524
+ const d = mutate ? date : new Date(date);
525
+ const diff = getWeek(d) - week;
526
+ d.setDate(d.getDate() - diff * 7);
527
+ return d;
528
+ }
529
+ // based on: https://github.com/date-fns/date-fns/blob/master/src/startOfISOWeekYear/index.ts
530
+ function startOfWeekYear(date) {
531
+ const year = getWeekYear(date);
532
+ const fourthOfJanuary = new Date(0);
533
+ fourthOfJanuary.setFullYear(year, 0, 4);
534
+ fourthOfJanuary.setHours(0, 0, 0, 0);
535
+ return startOfWeek(fourthOfJanuary, true);
536
+ }
537
+ // based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/getISOWeekYear/index.ts
538
+ function getWeekYear(date) {
539
+ const year = date.getFullYear();
540
+ const fourthOfJanuaryOfNextYear = new Date(0);
541
+ fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4);
542
+ fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0);
543
+ const startOfNextYear = startOfWeek(fourthOfJanuaryOfNextYear, true);
544
+ const fourthOfJanuaryOfThisYear = new Date(0);
545
+ fourthOfJanuaryOfThisYear.setFullYear(year, 0, 4);
546
+ fourthOfJanuaryOfThisYear.setHours(0, 0, 0, 0);
547
+ const startOfThisYear = startOfWeek(fourthOfJanuaryOfThisYear, true);
548
+ if (date.getTime() >= startOfNextYear.getTime()) {
549
+ return year + 1;
550
+ }
551
+ else if (date.getTime() >= startOfThisYear.getTime()) {
552
+ return year;
553
+ }
554
+ else {
555
+ return year - 1;
556
+ }
557
+ }
558
+ // function setWeekYear(
559
+ // date: Date,
560
+ // year: number,
561
+ // ): Date {
562
+ // const diff = differenceInCalendarDays(date, startOfWeekYear(date))
563
+ // const fourthOfJanuary = new Date(0)
564
+ // fourthOfJanuary.setFullYear(year, 0, 4)
565
+ // fourthOfJanuary.setHours(0, 0, 0, 0)
566
+ // date = startOfWeekYear(fourthOfJanuary)
567
+ // date.setDate(date.getDate() + diff)
568
+ // return date
569
+ // }
570
+ // function differenceInCalendarDays(
571
+ // dateLeft: Date,
572
+ // dateRight: Date,
573
+ // ): number {
574
+ // return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
575
+ // }
576
+ // function startOfDay(date: Date, mutate = false): Date {
577
+ // const d = mutate ? date : new Date(date)
578
+ // d.setHours(0, 0, 0, 0)
579
+ // return d
580
+ // }
581
+ // based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
582
+ function startOfWeek(date, mutate = false) {
583
+ const d = mutate ? date : new Date(date);
584
+ const day = d.getDay();
585
+ const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
586
+ d.setDate(d.getDate() - diff);
587
+ d.setHours(0, 0, 0, 0);
588
+ return d;
589
+ }
590
+ // based on: https://github.com/date-fns/date-fns/blob/master/src/endOfWeek/index.ts
591
+ function endOfWeek(date, mutate = false) {
592
+ const d = mutate ? date : new Date(date);
593
+ const day = d.getDay();
594
+ const diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
595
+ d.setDate(d.getDate() + diff);
596
+ return d;
597
+ }
package/dist/index.d.ts CHANGED
@@ -64,9 +64,9 @@ export * from './datetime/localDate';
64
64
  export * from './datetime/localTime';
65
65
  export * from './datetime/dateInterval';
66
66
  export * from './datetime/timeInterval';
67
- import { LocalDateConfig, LocalDateUnit, Inclusiveness } from './datetime/localDate';
68
- import { LocalTimeConfig, LocalTimeUnit, LocalTimeComponents } from './datetime/localTime';
67
+ import { LocalDateConfig, LocalDateFormatter, LocalDateUnit, LocalDateUnitStrict, Inclusiveness } from './datetime/localDate';
68
+ import { LocalTimeConfig, LocalTimeFormatter, LocalTimeUnit, LocalTimeComponents, ISODayOfWeek } from './datetime/localTime';
69
69
  import { DateIntervalConfig, DateIntervalString } from './datetime/dateInterval';
70
70
  import { TimeIntervalConfig, TimeIntervalString } from './datetime/timeInterval';
71
- export type { DateIntervalConfig, DateIntervalString, TimeIntervalConfig, TimeIntervalString, LocalDateConfig, LocalDateUnit, Inclusiveness, LocalTimeConfig, LocalTimeUnit, LocalTimeComponents, AbortableMapper, AbortablePredicate, AbortableAsyncPredicate, AbortableAsyncMapper, PQueueCfg, MemoCache, AsyncMemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateString, IsoDateTimeString, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestampNumber, UnixTimestamp, Integer, BaseDBEntity, SavedDBEntity, Saved, Unsaved, UnsavedId, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogWithLevelFunction, CommonLogFunction, CommonLogger, };
71
+ export type { DateIntervalConfig, DateIntervalString, TimeIntervalConfig, TimeIntervalString, LocalDateConfig, LocalDateFormatter, LocalDateUnit, LocalDateUnitStrict, Inclusiveness, LocalTimeConfig, LocalTimeFormatter, LocalTimeUnit, ISODayOfWeek, LocalTimeComponents, AbortableMapper, AbortablePredicate, AbortableAsyncPredicate, AbortableAsyncMapper, PQueueCfg, MemoCache, AsyncMemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateString, IsoDateTimeString, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestampNumber, UnixTimestamp, Integer, BaseDBEntity, SavedDBEntity, Saved, Unsaved, UnsavedId, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogWithLevelFunction, CommonLogFunction, CommonLogger, };
72
72
  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, };
package/dist/index.js CHANGED
@@ -96,3 +96,4 @@ tslib_1.__exportStar(require("./datetime/localDate"), exports);
96
96
  tslib_1.__exportStar(require("./datetime/localTime"), exports);
97
97
  tslib_1.__exportStar(require("./datetime/dateInterval"), exports);
98
98
  tslib_1.__exportStar(require("./datetime/timeInterval"), exports);
99
+ const localTime_1 = require("./datetime/localTime");
@@ -1,4 +1,6 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
2
4
  /// <reference lib="es2018" />
3
5
  /// <reference lib="dom" />
4
6
  import { Class, ObservableLike, Primitive, TypedArray } from '../typeFest';
@@ -237,8 +237,37 @@ export function _shuffle(array, mutate = false) {
237
237
  return a;
238
238
  }
239
239
  /**
240
- * Returns last item of the array (or undefined if array is empty).
240
+ * Returns last item of non-empty array.
241
+ * Throws if array is empty.
241
242
  */
242
243
  export function _last(array) {
244
+ if (!array.length)
245
+ throw new Error('_last called on empty array');
246
+ return array[array.length - 1];
247
+ }
248
+ /**
249
+ * Returns last item of the array (or undefined if array is empty).
250
+ */
251
+ export function _lastOrUndefined(array) {
243
252
  return array[array.length - 1];
244
253
  }
254
+ export function _minOrUndefined(array) {
255
+ if (!array.length)
256
+ return;
257
+ return _min(array);
258
+ }
259
+ export function _min(array) {
260
+ if (!array.length)
261
+ throw new Error('_min called on empty array');
262
+ return array.reduce((min, item) => (min <= item ? min : item));
263
+ }
264
+ export function _maxOrUndefined(array) {
265
+ if (!array.length)
266
+ return;
267
+ return _max(array);
268
+ }
269
+ export function _max(array) {
270
+ if (!array.length)
271
+ throw new Error('_max called on empty array');
272
+ return array.reduce((max, item) => (max >= item ? max : item));
273
+ }
@@ -87,16 +87,24 @@ export class LocalDate {
87
87
  }
88
88
  static earliest(items) {
89
89
  _assert(items.length, 'LocalDate.earliest called on empty array');
90
- return items.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
90
+ return items
91
+ .map(i => LocalDate.of(i))
92
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
91
93
  }
92
94
  static latestOrUndefined(items) {
93
95
  return items.length ? LocalDate.latest(items) : undefined;
94
96
  }
95
97
  static latest(items) {
96
98
  _assert(items.length, 'LocalDate.latest called on empty array');
97
- return items.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
99
+ return items
100
+ .map(i => LocalDate.of(i))
101
+ .reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
98
102
  }
99
103
  static range(min, max, incl = '[)', step = 1, stepUnit = 'day') {
104
+ if (stepUnit === 'week') {
105
+ step *= 7;
106
+ stepUnit = 'day';
107
+ }
100
108
  const dates = [];
101
109
  const $min = LocalDate.of(min);
102
110
  const $max = LocalDate.of(max).startOf(stepUnit);
@@ -206,7 +214,7 @@ export class LocalDate {
206
214
  if (unit === 'month') {
207
215
  return (this.$year - d.$year) * 12 + (this.$month - d.$month);
208
216
  }
209
- // unit is 'day'
217
+ // unit is 'day' or 'week'
210
218
  let days = this.$day - d.$day;
211
219
  if (d.$year < this.$year) {
212
220
  for (let year = d.$year; year < this.$year; year++) {
@@ -228,10 +236,17 @@ export class LocalDate {
228
236
  days -= LocalDate.getMonthLength(d.$year, month);
229
237
  }
230
238
  }
239
+ if (unit === 'week') {
240
+ return Math.floor(days / 7);
241
+ }
231
242
  return days;
232
243
  }
233
244
  add(num, unit, mutate = false) {
234
245
  let { $day, $month, $year } = this;
246
+ if (unit === 'week') {
247
+ num *= 7;
248
+ unit = 'day';
249
+ }
235
250
  if (unit === 'day') {
236
251
  $day += num;
237
252
  }
@@ -361,6 +376,9 @@ export class LocalDate {
361
376
  toJSON() {
362
377
  return this.toString();
363
378
  }
379
+ format(fmt) {
380
+ return fmt(this);
381
+ }
364
382
  }
365
383
  /**
366
384
  * Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`