@naturalcycles/js-lib 14.98.2 → 14.99.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/array/array.util.d.ts +10 -1
- package/dist/array/array.util.js +36 -2
- package/dist/datetime/localDate.d.ts +18 -11
- package/dist/datetime/localDate.js +53 -22
- package/dist/datetime/localTime.d.ts +25 -6
- package/dist/datetime/localTime.js +203 -22
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -0
- package/dist/vendor/is.d.ts +2 -0
- package/dist-esm/array/array.util.js +30 -1
- package/dist-esm/datetime/localDate.js +53 -22
- package/dist-esm/datetime/localTime.js +202 -21
- package/dist-esm/index.js +1 -0
- package/package.json +2 -2
- package/src/array/array.util.ts +30 -1
- package/src/datetime/localDate.ts +73 -32
- package/src/datetime/localTime.ts +236 -29
- package/src/index.ts +18 -2
- package/src/promise/pRetry.ts +2 -2
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");
|
package/dist/vendor/is.d.ts
CHANGED
|
@@ -237,8 +237,37 @@ export function _shuffle(array, mutate = false) {
|
|
|
237
237
|
return a;
|
|
238
238
|
}
|
|
239
239
|
/**
|
|
240
|
-
* Returns last item of
|
|
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
|
|
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
|
|
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);
|
|
@@ -194,44 +202,58 @@ export class LocalDate {
|
|
|
194
202
|
return Math.abs(this.diff(d, unit));
|
|
195
203
|
}
|
|
196
204
|
/**
|
|
197
|
-
* Returns the number of **full** units difference (aka `Math.
|
|
205
|
+
* Returns the number of **full** units difference (aka `Math.floor`).
|
|
198
206
|
*
|
|
199
207
|
* a.diff(b) means "a minus b"
|
|
200
208
|
*/
|
|
201
209
|
diff(d, unit) {
|
|
202
210
|
d = LocalDate.of(d);
|
|
211
|
+
const sign = this.cmp(d);
|
|
212
|
+
if (!sign)
|
|
213
|
+
return 0;
|
|
214
|
+
// Put items in descending order: "big minus small"
|
|
215
|
+
const [big, small] = sign === 1 ? [this, d] : [d, this];
|
|
203
216
|
if (unit === 'year') {
|
|
204
|
-
|
|
217
|
+
let years = big.$year - small.$year;
|
|
218
|
+
if (big.$month < small.$month || (big.$month === small.$month && big.$day < small.$day)) {
|
|
219
|
+
years--;
|
|
220
|
+
}
|
|
221
|
+
return years * sign || 0;
|
|
205
222
|
}
|
|
206
223
|
if (unit === 'month') {
|
|
207
|
-
|
|
224
|
+
let months = (big.$year - small.$year) * 12 + (big.$month - small.$month);
|
|
225
|
+
if (big.$day < small.$day)
|
|
226
|
+
months--;
|
|
227
|
+
return months * sign || 0;
|
|
208
228
|
}
|
|
209
|
-
// unit is 'day'
|
|
210
|
-
let days =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
229
|
+
// unit is 'day' or 'week'
|
|
230
|
+
let days = big.$day - small.$day;
|
|
231
|
+
// If small date is after 1st of March - next year's "leapness" should be used
|
|
232
|
+
const offsetYear = small.$month >= 3 ? 1 : 0;
|
|
233
|
+
for (let year = small.$year; year < big.$year; year++) {
|
|
234
|
+
days += LocalDate.getYearLength(year + offsetYear);
|
|
215
235
|
}
|
|
216
|
-
|
|
217
|
-
for (let
|
|
218
|
-
days
|
|
236
|
+
if (small.$month < big.$month) {
|
|
237
|
+
for (let month = small.$month; month < big.$month; month++) {
|
|
238
|
+
days += LocalDate.getMonthLength(big.$year, month);
|
|
219
239
|
}
|
|
220
240
|
}
|
|
221
|
-
if (
|
|
222
|
-
for (let month =
|
|
223
|
-
days
|
|
241
|
+
else if (big.$month < small.$month) {
|
|
242
|
+
for (let month = big.$month; month < small.$month; month++) {
|
|
243
|
+
days -= LocalDate.getMonthLength(big.$year, month);
|
|
224
244
|
}
|
|
225
245
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
days -= LocalDate.getMonthLength(d.$year, month);
|
|
229
|
-
}
|
|
246
|
+
if (unit === 'week') {
|
|
247
|
+
return Math.trunc(days / 7) * sign || 0;
|
|
230
248
|
}
|
|
231
|
-
return days;
|
|
249
|
+
return days * sign || 0;
|
|
232
250
|
}
|
|
233
251
|
add(num, unit, mutate = false) {
|
|
234
252
|
let { $day, $month, $year } = this;
|
|
253
|
+
if (unit === 'week') {
|
|
254
|
+
num *= 7;
|
|
255
|
+
unit = 'day';
|
|
256
|
+
}
|
|
235
257
|
if (unit === 'day') {
|
|
236
258
|
$day += num;
|
|
237
259
|
}
|
|
@@ -331,6 +353,12 @@ export class LocalDate {
|
|
|
331
353
|
toISODate() {
|
|
332
354
|
return this.toString();
|
|
333
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Returns e.g: `1984-06-21T17:56:21`
|
|
358
|
+
*/
|
|
359
|
+
toISODateTime() {
|
|
360
|
+
return this.toString() + 'T00:00:00';
|
|
361
|
+
}
|
|
334
362
|
toString() {
|
|
335
363
|
return [
|
|
336
364
|
String(this.$year).padStart(4, '0'),
|
|
@@ -355,6 +383,9 @@ export class LocalDate {
|
|
|
355
383
|
toJSON() {
|
|
356
384
|
return this.toString();
|
|
357
385
|
}
|
|
386
|
+
format(fmt) {
|
|
387
|
+
return fmt(this);
|
|
388
|
+
}
|
|
358
389
|
}
|
|
359
390
|
/**
|
|
360
391
|
* Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { _assert } from '../error/assert';
|
|
2
2
|
import { _ms } from '../time/time.util';
|
|
3
3
|
import { LocalDate } from './localDate';
|
|
4
|
+
export var ISODayOfWeek;
|
|
5
|
+
(function (ISODayOfWeek) {
|
|
6
|
+
ISODayOfWeek[ISODayOfWeek["MONDAY"] = 1] = "MONDAY";
|
|
7
|
+
ISODayOfWeek[ISODayOfWeek["TUESDAY"] = 2] = "TUESDAY";
|
|
8
|
+
ISODayOfWeek[ISODayOfWeek["WEDNESDAY"] = 3] = "WEDNESDAY";
|
|
9
|
+
ISODayOfWeek[ISODayOfWeek["THURSDAY"] = 4] = "THURSDAY";
|
|
10
|
+
ISODayOfWeek[ISODayOfWeek["FRIDAY"] = 5] = "FRIDAY";
|
|
11
|
+
ISODayOfWeek[ISODayOfWeek["SATURDAY"] = 6] = "SATURDAY";
|
|
12
|
+
ISODayOfWeek[ISODayOfWeek["SUNDAY"] = 7] = "SUNDAY";
|
|
13
|
+
})(ISODayOfWeek || (ISODayOfWeek = {}));
|
|
14
|
+
const weekStartsOn = 1; // mon, as per ISO
|
|
15
|
+
const MILLISECONDS_IN_WEEK = 604800000;
|
|
16
|
+
const SECONDS_IN_DAY = 86400;
|
|
17
|
+
// const MILLISECONDS_IN_DAY = 86400000
|
|
18
|
+
// const MILLISECONDS_IN_MINUTE = 60000
|
|
19
|
+
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
|
|
4
20
|
/* eslint-disable no-dupe-class-members */
|
|
5
21
|
/**
|
|
6
22
|
* @experimental
|
|
@@ -104,6 +120,9 @@ export class LocalTime {
|
|
|
104
120
|
if (unit === 'minute') {
|
|
105
121
|
return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes();
|
|
106
122
|
}
|
|
123
|
+
if (unit === 'week') {
|
|
124
|
+
return getWeek(this.$date);
|
|
125
|
+
}
|
|
107
126
|
// second
|
|
108
127
|
return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds();
|
|
109
128
|
}
|
|
@@ -128,6 +147,9 @@ export class LocalTime {
|
|
|
128
147
|
else if (unit === 'second') {
|
|
129
148
|
this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v);
|
|
130
149
|
}
|
|
150
|
+
else if (unit === 'week') {
|
|
151
|
+
setWeek(t.$date, v, true);
|
|
152
|
+
}
|
|
131
153
|
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
132
154
|
return t;
|
|
133
155
|
}
|
|
@@ -137,9 +159,21 @@ export class LocalTime {
|
|
|
137
159
|
month(v) {
|
|
138
160
|
return v === undefined ? this.get('month') : this.set('month', v);
|
|
139
161
|
}
|
|
162
|
+
week(v) {
|
|
163
|
+
return v === undefined ? getWeek(this.$date) : this.set('week', v);
|
|
164
|
+
}
|
|
140
165
|
day(v) {
|
|
141
166
|
return v === undefined ? this.get('day') : this.set('day', v);
|
|
142
167
|
}
|
|
168
|
+
dayOfWeek(v) {
|
|
169
|
+
const dow = (this.$date.getDay() || 7);
|
|
170
|
+
if (v === undefined) {
|
|
171
|
+
return dow;
|
|
172
|
+
}
|
|
173
|
+
if (!VALID_DAYS_OF_WEEK.has(v))
|
|
174
|
+
throw new Error(`Invalid dayOfWeek: ${v}`);
|
|
175
|
+
return this.add(v - dow, 'day');
|
|
176
|
+
}
|
|
143
177
|
hour(v) {
|
|
144
178
|
return v === undefined ? this.get('hour') : this.set('hour', v);
|
|
145
179
|
}
|
|
@@ -174,6 +208,10 @@ export class LocalTime {
|
|
|
174
208
|
return mutate ? this : new LocalTime(d, this.utcMode);
|
|
175
209
|
}
|
|
176
210
|
add(num, unit, mutate = false) {
|
|
211
|
+
if (unit === 'week') {
|
|
212
|
+
num *= 7;
|
|
213
|
+
unit = 'day';
|
|
214
|
+
}
|
|
177
215
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
178
216
|
}
|
|
179
217
|
subtract(num, unit, mutate = false) {
|
|
@@ -184,21 +222,43 @@ export class LocalTime {
|
|
|
184
222
|
}
|
|
185
223
|
diff(other, unit) {
|
|
186
224
|
const date2 = LocalTime.parseToDate(other);
|
|
187
|
-
if (unit === 'year') {
|
|
188
|
-
return this.$date.getFullYear() - date2.getFullYear();
|
|
189
|
-
}
|
|
190
|
-
if (unit === 'month') {
|
|
191
|
-
return ((this.$date.getFullYear() - date2.getFullYear()) * 12 +
|
|
192
|
-
this.$date.getMonth() -
|
|
193
|
-
date2.getMonth());
|
|
194
|
-
}
|
|
195
225
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
226
|
+
if (!secDiff)
|
|
227
|
+
return 0;
|
|
228
|
+
if (unit === 'year' || unit === 'month') {
|
|
229
|
+
const sign = secDiff > 0 ? 1 : -1;
|
|
230
|
+
// Put items in descending order: "big minus small"
|
|
231
|
+
const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date];
|
|
232
|
+
if (unit === 'year') {
|
|
233
|
+
let years = big.getFullYear() - small.getFullYear();
|
|
234
|
+
const big2 = new Date(big);
|
|
235
|
+
const small2 = new Date(small);
|
|
236
|
+
big2.setFullYear(1584);
|
|
237
|
+
small2.setFullYear(1584);
|
|
238
|
+
if (big2 < small2)
|
|
239
|
+
years--;
|
|
240
|
+
return years * sign || 0;
|
|
241
|
+
}
|
|
242
|
+
if (unit === 'month') {
|
|
243
|
+
let months = (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth();
|
|
244
|
+
const big2 = new Date(big);
|
|
245
|
+
const small2 = new Date(small);
|
|
246
|
+
big2.setFullYear(1584, 0);
|
|
247
|
+
small2.setFullYear(1584, 0);
|
|
248
|
+
if (big2 < small2)
|
|
249
|
+
months--;
|
|
250
|
+
return months * sign || 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
196
253
|
let r;
|
|
197
254
|
if (unit === 'day') {
|
|
198
|
-
r = secDiff /
|
|
255
|
+
r = secDiff / SECONDS_IN_DAY;
|
|
256
|
+
}
|
|
257
|
+
else if (unit === 'week') {
|
|
258
|
+
r = secDiff / (7 * 24 * 60 * 60);
|
|
199
259
|
}
|
|
200
260
|
else if (unit === 'hour') {
|
|
201
|
-
r = secDiff /
|
|
261
|
+
r = secDiff / 3600;
|
|
202
262
|
}
|
|
203
263
|
else if (unit === 'minute') {
|
|
204
264
|
r = secDiff / 60;
|
|
@@ -207,25 +267,60 @@ export class LocalTime {
|
|
|
207
267
|
// unit === 'second'
|
|
208
268
|
r = secDiff;
|
|
209
269
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return 0;
|
|
213
|
-
return r;
|
|
270
|
+
// `|| 0` is to avoid returning -0
|
|
271
|
+
return Math.trunc(r) || 0;
|
|
214
272
|
}
|
|
215
273
|
startOf(unit, mutate = false) {
|
|
216
274
|
if (unit === 'second')
|
|
217
275
|
return this;
|
|
218
276
|
const d = mutate ? this.$date : new Date(this.$date);
|
|
277
|
+
d.setSeconds(0, 0);
|
|
219
278
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
220
|
-
this.utcMode ? d.setUTCSeconds(0) : d.setSeconds(0);
|
|
221
279
|
if (unit !== 'minute') {
|
|
222
280
|
this.utcMode ? d.setUTCMinutes(0) : d.setMinutes(0);
|
|
223
281
|
if (unit !== 'hour') {
|
|
224
282
|
this.utcMode ? d.setUTCHours(0) : d.setHours(0);
|
|
225
283
|
if (unit !== 'day') {
|
|
226
|
-
|
|
227
|
-
if (unit
|
|
284
|
+
// year, month or week
|
|
285
|
+
if (unit === 'year') {
|
|
228
286
|
this.utcMode ? d.setUTCMonth(0) : d.setMonth(0);
|
|
287
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1);
|
|
288
|
+
}
|
|
289
|
+
else if (unit === 'month') {
|
|
290
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// week
|
|
294
|
+
startOfWeek(d, true);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
300
|
+
return mutate ? this : new LocalTime(d, this.utcMode);
|
|
301
|
+
}
|
|
302
|
+
endOf(unit, mutate = false) {
|
|
303
|
+
if (unit === 'second')
|
|
304
|
+
return this;
|
|
305
|
+
const d = mutate ? this.$date : new Date(this.$date);
|
|
306
|
+
d.setSeconds(59, 0);
|
|
307
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
308
|
+
if (unit !== 'minute') {
|
|
309
|
+
this.utcMode ? d.setUTCMinutes(59) : d.setMinutes(59);
|
|
310
|
+
if (unit !== 'hour') {
|
|
311
|
+
this.utcMode ? d.setUTCHours(23) : d.setHours(23);
|
|
312
|
+
if (unit !== 'day') {
|
|
313
|
+
// year, month or week
|
|
314
|
+
if (unit === 'year') {
|
|
315
|
+
this.utcMode ? d.setUTCMonth(11) : d.setMonth(11);
|
|
316
|
+
}
|
|
317
|
+
if (unit === 'week') {
|
|
318
|
+
endOfWeek(d, true);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
// year or month
|
|
322
|
+
const lastDay = LocalDate.getMonthLength(d.getFullYear(), d.getMonth() + 1);
|
|
323
|
+
this.utcMode ? d.setUTCDate(lastDay) : d.setDate(lastDay);
|
|
229
324
|
}
|
|
230
325
|
}
|
|
231
326
|
}
|
|
@@ -248,14 +343,18 @@ export class LocalTime {
|
|
|
248
343
|
}
|
|
249
344
|
static earliest(items) {
|
|
250
345
|
_assert(items.length, 'LocalTime.earliest called on empty array');
|
|
251
|
-
return items
|
|
346
|
+
return items
|
|
347
|
+
.map(i => LocalTime.of(i))
|
|
348
|
+
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
|
|
252
349
|
}
|
|
253
350
|
static latestOrUndefined(items) {
|
|
254
351
|
return items.length ? LocalTime.latest(items) : undefined;
|
|
255
352
|
}
|
|
256
353
|
static latest(items) {
|
|
257
354
|
_assert(items.length, 'LocalTime.latest called on empty array');
|
|
258
|
-
return items
|
|
355
|
+
return items
|
|
356
|
+
.map(i => LocalTime.of(i))
|
|
357
|
+
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
|
|
259
358
|
}
|
|
260
359
|
isSame(d) {
|
|
261
360
|
return this.cmp(d) === 0;
|
|
@@ -295,7 +394,6 @@ export class LocalTime {
|
|
|
295
394
|
return 0;
|
|
296
395
|
return t1 < t2 ? -1 : 1;
|
|
297
396
|
}
|
|
298
|
-
// todo: endOf
|
|
299
397
|
components() {
|
|
300
398
|
if (this.utcMode) {
|
|
301
399
|
return {
|
|
@@ -368,7 +466,7 @@ export class LocalTime {
|
|
|
368
466
|
// .join(' ')
|
|
369
467
|
}
|
|
370
468
|
/**
|
|
371
|
-
* Returns e.g: `1984-06-21T17:56:21
|
|
469
|
+
* Returns e.g: `1984-06-21T17:56:21`
|
|
372
470
|
*/
|
|
373
471
|
toISODateTime() {
|
|
374
472
|
return this.$date.toISOString().slice(0, 19);
|
|
@@ -420,6 +518,9 @@ export class LocalTime {
|
|
|
420
518
|
toJSON() {
|
|
421
519
|
return this.unix();
|
|
422
520
|
}
|
|
521
|
+
format(fmt) {
|
|
522
|
+
return fmt(this);
|
|
523
|
+
}
|
|
423
524
|
}
|
|
424
525
|
/**
|
|
425
526
|
* Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
|
|
@@ -427,3 +528,83 @@ export class LocalTime {
|
|
|
427
528
|
export function localTime(d) {
|
|
428
529
|
return d ? LocalTime.of(d) : LocalTime.now();
|
|
429
530
|
}
|
|
531
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
|
|
532
|
+
function getWeek(date) {
|
|
533
|
+
const diff = startOfWeek(date).getTime() - startOfWeekYear(date).getTime();
|
|
534
|
+
return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;
|
|
535
|
+
}
|
|
536
|
+
function setWeek(date, week, mutate = false) {
|
|
537
|
+
const d = mutate ? date : new Date(date);
|
|
538
|
+
const diff = getWeek(d) - week;
|
|
539
|
+
d.setDate(d.getDate() - diff * 7);
|
|
540
|
+
return d;
|
|
541
|
+
}
|
|
542
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/startOfISOWeekYear/index.ts
|
|
543
|
+
function startOfWeekYear(date) {
|
|
544
|
+
const year = getWeekYear(date);
|
|
545
|
+
const fourthOfJanuary = new Date(0);
|
|
546
|
+
fourthOfJanuary.setFullYear(year, 0, 4);
|
|
547
|
+
fourthOfJanuary.setHours(0, 0, 0, 0);
|
|
548
|
+
return startOfWeek(fourthOfJanuary, true);
|
|
549
|
+
}
|
|
550
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/getISOWeekYear/index.ts
|
|
551
|
+
function getWeekYear(date) {
|
|
552
|
+
const year = date.getFullYear();
|
|
553
|
+
const fourthOfJanuaryOfNextYear = new Date(0);
|
|
554
|
+
fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4);
|
|
555
|
+
fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0);
|
|
556
|
+
const startOfNextYear = startOfWeek(fourthOfJanuaryOfNextYear, true);
|
|
557
|
+
const fourthOfJanuaryOfThisYear = new Date(0);
|
|
558
|
+
fourthOfJanuaryOfThisYear.setFullYear(year, 0, 4);
|
|
559
|
+
fourthOfJanuaryOfThisYear.setHours(0, 0, 0, 0);
|
|
560
|
+
const startOfThisYear = startOfWeek(fourthOfJanuaryOfThisYear, true);
|
|
561
|
+
if (date.getTime() >= startOfNextYear.getTime()) {
|
|
562
|
+
return year + 1;
|
|
563
|
+
}
|
|
564
|
+
else if (date.getTime() >= startOfThisYear.getTime()) {
|
|
565
|
+
return year;
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
return year - 1;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
// function setWeekYear(
|
|
572
|
+
// date: Date,
|
|
573
|
+
// year: number,
|
|
574
|
+
// ): Date {
|
|
575
|
+
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
576
|
+
// const fourthOfJanuary = new Date(0)
|
|
577
|
+
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
578
|
+
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
579
|
+
// date = startOfWeekYear(fourthOfJanuary)
|
|
580
|
+
// date.setDate(date.getDate() + diff)
|
|
581
|
+
// return date
|
|
582
|
+
// }
|
|
583
|
+
// function differenceInCalendarDays(
|
|
584
|
+
// dateLeft: Date,
|
|
585
|
+
// dateRight: Date,
|
|
586
|
+
// ): number {
|
|
587
|
+
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
588
|
+
// }
|
|
589
|
+
// function startOfDay(date: Date, mutate = false): Date {
|
|
590
|
+
// const d = mutate ? date : new Date(date)
|
|
591
|
+
// d.setHours(0, 0, 0, 0)
|
|
592
|
+
// return d
|
|
593
|
+
// }
|
|
594
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
595
|
+
function startOfWeek(date, mutate = false) {
|
|
596
|
+
const d = mutate ? date : new Date(date);
|
|
597
|
+
const day = d.getDay();
|
|
598
|
+
const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
|
|
599
|
+
d.setDate(d.getDate() - diff);
|
|
600
|
+
d.setHours(0, 0, 0, 0);
|
|
601
|
+
return d;
|
|
602
|
+
}
|
|
603
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/endOfWeek/index.ts
|
|
604
|
+
function endOfWeek(date, mutate = false) {
|
|
605
|
+
const d = mutate ? date : new Date(date);
|
|
606
|
+
const day = d.getDay();
|
|
607
|
+
const diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
|
|
608
|
+
d.setDate(d.getDate() + diff);
|
|
609
|
+
return d;
|
|
610
|
+
}
|
package/dist-esm/index.js
CHANGED
|
@@ -60,4 +60,5 @@ export * from './datetime/localDate';
|
|
|
60
60
|
export * from './datetime/localTime';
|
|
61
61
|
export * from './datetime/dateInterval';
|
|
62
62
|
export * from './datetime/timeInterval';
|
|
63
|
+
import { ISODayOfWeek, } from './datetime/localTime';
|
|
63
64
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.99.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@naturalcycles/nodejs-lib": "^12.33.4",
|
|
17
17
|
"@naturalcycles/time-lib": "^3.5.1",
|
|
18
18
|
"@types/node": "^17.0.4",
|
|
19
|
-
"jest": "^
|
|
19
|
+
"jest": "^28.0.3",
|
|
20
20
|
"patch-package": "^6.2.1",
|
|
21
21
|
"prettier": "^2.1.2",
|
|
22
22
|
"rxjs": "^7.0.1",
|
package/src/array/array.util.ts
CHANGED
|
@@ -272,9 +272,38 @@ export function _shuffle<T>(array: T[], mutate = false): T[] {
|
|
|
272
272
|
return a
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Returns last item of non-empty array.
|
|
277
|
+
* Throws if array is empty.
|
|
278
|
+
*/
|
|
279
|
+
export function _last<T>(array: T[]): T {
|
|
280
|
+
if (!array.length) throw new Error('_last called on empty array')
|
|
281
|
+
return array[array.length - 1]!
|
|
282
|
+
}
|
|
283
|
+
|
|
275
284
|
/**
|
|
276
285
|
* Returns last item of the array (or undefined if array is empty).
|
|
277
286
|
*/
|
|
278
|
-
export function
|
|
287
|
+
export function _lastOrUndefined<T>(array: T[]): T | undefined {
|
|
279
288
|
return array[array.length - 1]
|
|
280
289
|
}
|
|
290
|
+
|
|
291
|
+
export function _minOrUndefined<T>(array: T[]): T | undefined {
|
|
292
|
+
if (!array.length) return
|
|
293
|
+
return _min(array)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function _min<T>(array: T[]): T {
|
|
297
|
+
if (!array.length) throw new Error('_min called on empty array')
|
|
298
|
+
return array.reduce((min, item) => (min <= item ? min : item))
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export function _maxOrUndefined<T>(array: T[]): T | undefined {
|
|
302
|
+
if (!array.length) return
|
|
303
|
+
return _max(array)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export function _max<T>(array: T[]): T {
|
|
307
|
+
if (!array.length) throw new Error('_max called on empty array')
|
|
308
|
+
return array.reduce((max, item) => (max >= item ? max : item))
|
|
309
|
+
}
|