@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
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { _assert } from '../error/assert'
|
|
2
|
-
import { IsoDateString, UnixTimestampNumber } from '../types'
|
|
2
|
+
import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types'
|
|
3
3
|
import { LocalTime } from './localTime'
|
|
4
4
|
|
|
5
|
-
export type LocalDateUnit =
|
|
5
|
+
export type LocalDateUnit = LocalDateUnitStrict | 'week'
|
|
6
|
+
export type LocalDateUnitStrict = 'year' | 'month' | 'day'
|
|
6
7
|
export type Inclusiveness = '()' | '[]' | '[)' | '(]'
|
|
7
8
|
|
|
8
9
|
const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
9
10
|
const DATE_REGEX = /^(\d\d\d\d)-(\d\d)-(\d\d)$/
|
|
10
11
|
|
|
11
12
|
export type LocalDateConfig = LocalDate | IsoDateString
|
|
13
|
+
export type LocalDateFormatter = (ld: LocalDate) => string
|
|
12
14
|
|
|
13
15
|
/* eslint-disable no-dupe-class-members */
|
|
14
16
|
|
|
@@ -106,24 +108,28 @@ export class LocalDate {
|
|
|
106
108
|
return (mutate ? items : [...items]).sort((a, b) => a.cmp(b) * mod)
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
static earliestOrUndefined(items:
|
|
111
|
+
static earliestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined {
|
|
110
112
|
return items.length ? LocalDate.earliest(items) : undefined
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
static earliest(items:
|
|
115
|
+
static earliest(items: LocalDateConfig[]): LocalDate {
|
|
114
116
|
_assert(items.length, 'LocalDate.earliest called on empty array')
|
|
115
117
|
|
|
116
|
-
return items
|
|
118
|
+
return items
|
|
119
|
+
.map(i => LocalDate.of(i))
|
|
120
|
+
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
static latestOrUndefined(items:
|
|
123
|
+
static latestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined {
|
|
120
124
|
return items.length ? LocalDate.latest(items) : undefined
|
|
121
125
|
}
|
|
122
126
|
|
|
123
|
-
static latest(items:
|
|
127
|
+
static latest(items: LocalDateConfig[]): LocalDate {
|
|
124
128
|
_assert(items.length, 'LocalDate.latest called on empty array')
|
|
125
129
|
|
|
126
|
-
return items
|
|
130
|
+
return items
|
|
131
|
+
.map(i => LocalDate.of(i))
|
|
132
|
+
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
static range(
|
|
@@ -133,6 +139,11 @@ export class LocalDate {
|
|
|
133
139
|
step = 1,
|
|
134
140
|
stepUnit: LocalDateUnit = 'day',
|
|
135
141
|
): LocalDate[] {
|
|
142
|
+
if (stepUnit === 'week') {
|
|
143
|
+
step *= 7
|
|
144
|
+
stepUnit = 'day'
|
|
145
|
+
}
|
|
146
|
+
|
|
136
147
|
const dates: LocalDate[] = []
|
|
137
148
|
const $min = LocalDate.of(min)
|
|
138
149
|
const $max = LocalDate.of(max).startOf(stepUnit)
|
|
@@ -153,11 +164,11 @@ export class LocalDate {
|
|
|
153
164
|
return dates
|
|
154
165
|
}
|
|
155
166
|
|
|
156
|
-
get(unit:
|
|
167
|
+
get(unit: LocalDateUnitStrict): number {
|
|
157
168
|
return unit === 'year' ? this.$year : unit === 'month' ? this.$month : this.$day
|
|
158
169
|
}
|
|
159
170
|
|
|
160
|
-
set(unit:
|
|
171
|
+
set(unit: LocalDateUnitStrict, v: number, mutate = false): LocalDate {
|
|
161
172
|
const t = mutate ? this : this.clone()
|
|
162
173
|
|
|
163
174
|
if (unit === 'year') {
|
|
@@ -242,50 +253,69 @@ export class LocalDate {
|
|
|
242
253
|
}
|
|
243
254
|
|
|
244
255
|
/**
|
|
245
|
-
* Returns the number of **full** units difference (aka `Math.
|
|
256
|
+
* Returns the number of **full** units difference (aka `Math.floor`).
|
|
246
257
|
*
|
|
247
258
|
* a.diff(b) means "a minus b"
|
|
248
259
|
*/
|
|
249
260
|
diff(d: LocalDateConfig, unit: LocalDateUnit): number {
|
|
250
261
|
d = LocalDate.of(d)
|
|
251
262
|
|
|
263
|
+
const sign = this.cmp(d)
|
|
264
|
+
if (!sign) return 0
|
|
265
|
+
|
|
266
|
+
// Put items in descending order: "big minus small"
|
|
267
|
+
const [big, small] = sign === 1 ? [this, d] : [d, this]
|
|
268
|
+
|
|
252
269
|
if (unit === 'year') {
|
|
253
|
-
|
|
270
|
+
let years = big.$year - small.$year
|
|
271
|
+
|
|
272
|
+
if (big.$month < small.$month || (big.$month === small.$month && big.$day < small.$day)) {
|
|
273
|
+
years--
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return years * sign || 0
|
|
254
277
|
}
|
|
255
278
|
|
|
256
279
|
if (unit === 'month') {
|
|
257
|
-
|
|
280
|
+
let months = (big.$year - small.$year) * 12 + (big.$month - small.$month)
|
|
281
|
+
if (big.$day < small.$day) months--
|
|
282
|
+
return months * sign || 0
|
|
258
283
|
}
|
|
259
284
|
|
|
260
|
-
// unit is 'day'
|
|
261
|
-
let days =
|
|
285
|
+
// unit is 'day' or 'week'
|
|
286
|
+
let days = big.$day - small.$day
|
|
262
287
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
} else if (this.$year < d.$year) {
|
|
268
|
-
for (let year = this.$year; year < d.$year; year++) {
|
|
269
|
-
days -= LocalDate.getYearLength(year)
|
|
270
|
-
}
|
|
288
|
+
// If small date is after 1st of March - next year's "leapness" should be used
|
|
289
|
+
const offsetYear = small.$month >= 3 ? 1 : 0
|
|
290
|
+
for (let year = small.$year; year < big.$year; year++) {
|
|
291
|
+
days += LocalDate.getYearLength(year + offsetYear)
|
|
271
292
|
}
|
|
272
293
|
|
|
273
|
-
if (
|
|
274
|
-
for (let month =
|
|
275
|
-
days += LocalDate.getMonthLength(
|
|
294
|
+
if (small.$month < big.$month) {
|
|
295
|
+
for (let month = small.$month; month < big.$month; month++) {
|
|
296
|
+
days += LocalDate.getMonthLength(big.$year, month)
|
|
276
297
|
}
|
|
277
|
-
} else if (
|
|
278
|
-
for (let month =
|
|
279
|
-
days -= LocalDate.getMonthLength(
|
|
298
|
+
} else if (big.$month < small.$month) {
|
|
299
|
+
for (let month = big.$month; month < small.$month; month++) {
|
|
300
|
+
days -= LocalDate.getMonthLength(big.$year, month)
|
|
280
301
|
}
|
|
281
302
|
}
|
|
282
303
|
|
|
283
|
-
|
|
304
|
+
if (unit === 'week') {
|
|
305
|
+
return Math.trunc(days / 7) * sign || 0
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return days * sign || 0
|
|
284
309
|
}
|
|
285
310
|
|
|
286
311
|
add(num: number, unit: LocalDateUnit, mutate = false): LocalDate {
|
|
287
312
|
let { $day, $month, $year } = this
|
|
288
313
|
|
|
314
|
+
if (unit === 'week') {
|
|
315
|
+
num *= 7
|
|
316
|
+
unit = 'day'
|
|
317
|
+
}
|
|
318
|
+
|
|
289
319
|
if (unit === 'day') {
|
|
290
320
|
$day += num
|
|
291
321
|
} else if (unit === 'month') {
|
|
@@ -346,14 +376,14 @@ export class LocalDate {
|
|
|
346
376
|
return this.add(-num, unit, mutate)
|
|
347
377
|
}
|
|
348
378
|
|
|
349
|
-
startOf(unit:
|
|
379
|
+
startOf(unit: LocalDateUnitStrict): LocalDate {
|
|
350
380
|
if (unit === 'day') return this
|
|
351
381
|
if (unit === 'month') return LocalDate.create(this.$year, this.$month, 1)
|
|
352
382
|
// year
|
|
353
383
|
return LocalDate.create(this.$year, 1, 1)
|
|
354
384
|
}
|
|
355
385
|
|
|
356
|
-
endOf(unit:
|
|
386
|
+
endOf(unit: LocalDateUnitStrict): LocalDate {
|
|
357
387
|
if (unit === 'day') return this
|
|
358
388
|
if (unit === 'month')
|
|
359
389
|
return LocalDate.create(
|
|
@@ -400,6 +430,13 @@ export class LocalDate {
|
|
|
400
430
|
return this.toString()
|
|
401
431
|
}
|
|
402
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Returns e.g: `1984-06-21T17:56:21`
|
|
435
|
+
*/
|
|
436
|
+
toISODateTime(): IsoDateTimeString {
|
|
437
|
+
return this.toString() + 'T00:00:00'
|
|
438
|
+
}
|
|
439
|
+
|
|
403
440
|
toString(): IsoDateString {
|
|
404
441
|
return [
|
|
405
442
|
String(this.$year).padStart(4, '0'),
|
|
@@ -428,6 +465,10 @@ export class LocalDate {
|
|
|
428
465
|
toJSON(): IsoDateString {
|
|
429
466
|
return this.toString()
|
|
430
467
|
}
|
|
468
|
+
|
|
469
|
+
format(fmt: LocalDateFormatter): string {
|
|
470
|
+
return fmt(this)
|
|
471
|
+
}
|
|
431
472
|
}
|
|
432
473
|
|
|
433
474
|
/**
|
|
@@ -3,9 +3,20 @@ import { _ms } from '../time/time.util'
|
|
|
3
3
|
import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types'
|
|
4
4
|
import { Inclusiveness, LocalDate } from './localDate'
|
|
5
5
|
|
|
6
|
-
export type LocalTimeUnit = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'
|
|
6
|
+
export type LocalTimeUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second'
|
|
7
|
+
|
|
8
|
+
export enum ISODayOfWeek {
|
|
9
|
+
MONDAY = 1,
|
|
10
|
+
TUESDAY = 2,
|
|
11
|
+
WEDNESDAY = 3,
|
|
12
|
+
THURSDAY = 4,
|
|
13
|
+
FRIDAY = 5,
|
|
14
|
+
SATURDAY = 6,
|
|
15
|
+
SUNDAY = 7,
|
|
16
|
+
}
|
|
7
17
|
|
|
8
18
|
export type LocalTimeConfig = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber
|
|
19
|
+
export type LocalTimeFormatter = (ld: LocalTime) => string
|
|
9
20
|
|
|
10
21
|
export interface LocalTimeComponents {
|
|
11
22
|
year: number
|
|
@@ -16,6 +27,13 @@ export interface LocalTimeComponents {
|
|
|
16
27
|
second: number
|
|
17
28
|
}
|
|
18
29
|
|
|
30
|
+
const weekStartsOn = 1 // mon, as per ISO
|
|
31
|
+
const MILLISECONDS_IN_WEEK = 604800000
|
|
32
|
+
const SECONDS_IN_DAY = 86400
|
|
33
|
+
// const MILLISECONDS_IN_DAY = 86400000
|
|
34
|
+
// const MILLISECONDS_IN_MINUTE = 60000
|
|
35
|
+
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7])
|
|
36
|
+
|
|
19
37
|
/* eslint-disable no-dupe-class-members */
|
|
20
38
|
|
|
21
39
|
/**
|
|
@@ -134,6 +152,9 @@ export class LocalTime {
|
|
|
134
152
|
if (unit === 'minute') {
|
|
135
153
|
return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes()
|
|
136
154
|
}
|
|
155
|
+
if (unit === 'week') {
|
|
156
|
+
return getWeek(this.$date)
|
|
157
|
+
}
|
|
137
158
|
// second
|
|
138
159
|
return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds()
|
|
139
160
|
}
|
|
@@ -154,6 +175,8 @@ export class LocalTime {
|
|
|
154
175
|
this.utcMode ? t.$date.setUTCMinutes(v) : t.$date.setMinutes(v)
|
|
155
176
|
} else if (unit === 'second') {
|
|
156
177
|
this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v)
|
|
178
|
+
} else if (unit === 'week') {
|
|
179
|
+
setWeek(t.$date, v, true)
|
|
157
180
|
}
|
|
158
181
|
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
159
182
|
|
|
@@ -170,11 +193,33 @@ export class LocalTime {
|
|
|
170
193
|
month(v?: number): number | LocalTime {
|
|
171
194
|
return v === undefined ? this.get('month') : this.set('month', v)
|
|
172
195
|
}
|
|
196
|
+
week(): number
|
|
197
|
+
week(v: number): LocalTime
|
|
198
|
+
week(v?: number): number | LocalTime {
|
|
199
|
+
return v === undefined ? getWeek(this.$date) : this.set('week', v)
|
|
200
|
+
}
|
|
173
201
|
day(): number
|
|
174
202
|
day(v: number): LocalTime
|
|
175
203
|
day(v?: number): number | LocalTime {
|
|
176
204
|
return v === undefined ? this.get('day') : this.set('day', v)
|
|
177
205
|
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Based on ISO: 1-7 is Mon-Sun.
|
|
209
|
+
*/
|
|
210
|
+
dayOfWeek(): ISODayOfWeek
|
|
211
|
+
dayOfWeek(v: ISODayOfWeek): LocalTime
|
|
212
|
+
dayOfWeek(v?: ISODayOfWeek): ISODayOfWeek | LocalTime {
|
|
213
|
+
const dow = (this.$date.getDay() || 7) as ISODayOfWeek
|
|
214
|
+
|
|
215
|
+
if (v === undefined) {
|
|
216
|
+
return dow
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!VALID_DAYS_OF_WEEK.has(v)) throw new Error(`Invalid dayOfWeek: ${v}`)
|
|
220
|
+
|
|
221
|
+
return this.add(v - dow, 'day')
|
|
222
|
+
}
|
|
178
223
|
hour(): number
|
|
179
224
|
hour(v: number): LocalTime
|
|
180
225
|
hour(v?: number): number | LocalTime {
|
|
@@ -219,6 +264,10 @@ export class LocalTime {
|
|
|
219
264
|
}
|
|
220
265
|
|
|
221
266
|
add(num: number, unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
267
|
+
if (unit === 'week') {
|
|
268
|
+
num *= 7
|
|
269
|
+
unit = 'day'
|
|
270
|
+
}
|
|
222
271
|
return this.set(unit, this.get(unit) + num, mutate)
|
|
223
272
|
}
|
|
224
273
|
|
|
@@ -233,24 +282,45 @@ export class LocalTime {
|
|
|
233
282
|
diff(other: LocalTimeConfig, unit: LocalTimeUnit): number {
|
|
234
283
|
const date2 = LocalTime.parseToDate(other)
|
|
235
284
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (unit === 'month') {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
285
|
+
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
|
|
286
|
+
if (!secDiff) return 0
|
|
287
|
+
|
|
288
|
+
if (unit === 'year' || unit === 'month') {
|
|
289
|
+
const sign = secDiff > 0 ? 1 : -1
|
|
290
|
+
|
|
291
|
+
// Put items in descending order: "big minus small"
|
|
292
|
+
const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date]
|
|
293
|
+
|
|
294
|
+
if (unit === 'year') {
|
|
295
|
+
let years = big.getFullYear() - small.getFullYear()
|
|
296
|
+
const big2 = new Date(big)
|
|
297
|
+
const small2 = new Date(small)
|
|
298
|
+
big2.setFullYear(1584)
|
|
299
|
+
small2.setFullYear(1584)
|
|
300
|
+
if (big2 < small2) years--
|
|
301
|
+
return years * sign || 0
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (unit === 'month') {
|
|
305
|
+
let months =
|
|
306
|
+
(big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth()
|
|
307
|
+
const big2 = new Date(big)
|
|
308
|
+
const small2 = new Date(small)
|
|
309
|
+
big2.setFullYear(1584, 0)
|
|
310
|
+
small2.setFullYear(1584, 0)
|
|
311
|
+
if (big2 < small2) months--
|
|
312
|
+
return months * sign || 0
|
|
313
|
+
}
|
|
245
314
|
}
|
|
246
315
|
|
|
247
|
-
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
|
|
248
316
|
let r
|
|
249
317
|
|
|
250
318
|
if (unit === 'day') {
|
|
251
|
-
r = secDiff /
|
|
319
|
+
r = secDiff / SECONDS_IN_DAY
|
|
320
|
+
} else if (unit === 'week') {
|
|
321
|
+
r = secDiff / (7 * 24 * 60 * 60)
|
|
252
322
|
} else if (unit === 'hour') {
|
|
253
|
-
r = secDiff /
|
|
323
|
+
r = secDiff / 3600
|
|
254
324
|
} else if (unit === 'minute') {
|
|
255
325
|
r = secDiff / 60
|
|
256
326
|
} else {
|
|
@@ -258,26 +328,63 @@ export class LocalTime {
|
|
|
258
328
|
r = secDiff
|
|
259
329
|
}
|
|
260
330
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return r
|
|
331
|
+
// `|| 0` is to avoid returning -0
|
|
332
|
+
return Math.trunc(r) || 0
|
|
264
333
|
}
|
|
265
334
|
|
|
266
335
|
startOf(unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
267
336
|
if (unit === 'second') return this
|
|
268
|
-
|
|
269
337
|
const d = mutate ? this.$date : new Date(this.$date)
|
|
338
|
+
d.setSeconds(0, 0)
|
|
270
339
|
|
|
271
340
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
272
|
-
this.utcMode ? d.setUTCSeconds(0) : d.setSeconds(0)
|
|
273
341
|
if (unit !== 'minute') {
|
|
274
342
|
this.utcMode ? d.setUTCMinutes(0) : d.setMinutes(0)
|
|
275
343
|
if (unit !== 'hour') {
|
|
276
344
|
this.utcMode ? d.setUTCHours(0) : d.setHours(0)
|
|
277
345
|
if (unit !== 'day') {
|
|
278
|
-
|
|
279
|
-
|
|
346
|
+
// year, month or week
|
|
347
|
+
|
|
348
|
+
if (unit === 'year') {
|
|
280
349
|
this.utcMode ? d.setUTCMonth(0) : d.setMonth(0)
|
|
350
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1)
|
|
351
|
+
} else if (unit === 'month') {
|
|
352
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1)
|
|
353
|
+
} else {
|
|
354
|
+
// week
|
|
355
|
+
startOfWeek(d, true)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
361
|
+
|
|
362
|
+
return mutate ? this : new LocalTime(d, this.utcMode)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
endOf(unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
366
|
+
if (unit === 'second') return this
|
|
367
|
+
const d = mutate ? this.$date : new Date(this.$date)
|
|
368
|
+
d.setSeconds(59, 0)
|
|
369
|
+
|
|
370
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
371
|
+
if (unit !== 'minute') {
|
|
372
|
+
this.utcMode ? d.setUTCMinutes(59) : d.setMinutes(59)
|
|
373
|
+
if (unit !== 'hour') {
|
|
374
|
+
this.utcMode ? d.setUTCHours(23) : d.setHours(23)
|
|
375
|
+
if (unit !== 'day') {
|
|
376
|
+
// year, month or week
|
|
377
|
+
|
|
378
|
+
if (unit === 'year') {
|
|
379
|
+
this.utcMode ? d.setUTCMonth(11) : d.setMonth(11)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (unit === 'week') {
|
|
383
|
+
endOfWeek(d, true)
|
|
384
|
+
} else {
|
|
385
|
+
// year or month
|
|
386
|
+
const lastDay = LocalDate.getMonthLength(d.getFullYear(), d.getMonth() + 1)
|
|
387
|
+
this.utcMode ? d.setUTCDate(lastDay) : d.setDate(lastDay)
|
|
281
388
|
}
|
|
282
389
|
}
|
|
283
390
|
}
|
|
@@ -297,24 +404,28 @@ export class LocalTime {
|
|
|
297
404
|
})
|
|
298
405
|
}
|
|
299
406
|
|
|
300
|
-
static earliestOrUndefined(items:
|
|
407
|
+
static earliestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined {
|
|
301
408
|
return items.length ? LocalTime.earliest(items) : undefined
|
|
302
409
|
}
|
|
303
410
|
|
|
304
|
-
static earliest(items:
|
|
411
|
+
static earliest(items: LocalTimeConfig[]): LocalTime {
|
|
305
412
|
_assert(items.length, 'LocalTime.earliest called on empty array')
|
|
306
413
|
|
|
307
|
-
return items
|
|
414
|
+
return items
|
|
415
|
+
.map(i => LocalTime.of(i))
|
|
416
|
+
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
|
|
308
417
|
}
|
|
309
418
|
|
|
310
|
-
static latestOrUndefined(items:
|
|
419
|
+
static latestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined {
|
|
311
420
|
return items.length ? LocalTime.latest(items) : undefined
|
|
312
421
|
}
|
|
313
422
|
|
|
314
|
-
static latest(items:
|
|
423
|
+
static latest(items: LocalTimeConfig[]): LocalTime {
|
|
315
424
|
_assert(items.length, 'LocalTime.latest called on empty array')
|
|
316
425
|
|
|
317
|
-
return items
|
|
426
|
+
return items
|
|
427
|
+
.map(i => LocalTime.of(i))
|
|
428
|
+
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
|
|
318
429
|
}
|
|
319
430
|
|
|
320
431
|
isSame(d: LocalTimeConfig): boolean {
|
|
@@ -359,8 +470,6 @@ export class LocalTime {
|
|
|
359
470
|
return t1 < t2 ? -1 : 1
|
|
360
471
|
}
|
|
361
472
|
|
|
362
|
-
// todo: endOf
|
|
363
|
-
|
|
364
473
|
components(): LocalTimeComponents {
|
|
365
474
|
if (this.utcMode) {
|
|
366
475
|
return {
|
|
@@ -458,7 +567,7 @@ export class LocalTime {
|
|
|
458
567
|
}
|
|
459
568
|
|
|
460
569
|
/**
|
|
461
|
-
* Returns e.g: `1984-06-21T17:56:21
|
|
570
|
+
* Returns e.g: `1984-06-21T17:56:21`
|
|
462
571
|
*/
|
|
463
572
|
toISODateTime(): IsoDateTimeString {
|
|
464
573
|
return this.$date.toISOString().slice(0, 19)
|
|
@@ -519,6 +628,10 @@ export class LocalTime {
|
|
|
519
628
|
toJSON(): UnixTimestampNumber {
|
|
520
629
|
return this.unix()
|
|
521
630
|
}
|
|
631
|
+
|
|
632
|
+
format(fmt: LocalTimeFormatter): string {
|
|
633
|
+
return fmt(this)
|
|
634
|
+
}
|
|
522
635
|
}
|
|
523
636
|
|
|
524
637
|
/**
|
|
@@ -527,3 +640,97 @@ export class LocalTime {
|
|
|
527
640
|
export function localTime(d?: LocalTimeConfig): LocalTime {
|
|
528
641
|
return d ? LocalTime.of(d) : LocalTime.now()
|
|
529
642
|
}
|
|
643
|
+
|
|
644
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
|
|
645
|
+
function getWeek(date: Date): number {
|
|
646
|
+
const diff = startOfWeek(date).getTime() - startOfWeekYear(date).getTime()
|
|
647
|
+
return Math.round(diff / MILLISECONDS_IN_WEEK) + 1
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function setWeek(date: Date, week: number, mutate = false): Date {
|
|
651
|
+
const d = mutate ? date : new Date(date)
|
|
652
|
+
const diff = getWeek(d) - week
|
|
653
|
+
d.setDate(d.getDate() - diff * 7)
|
|
654
|
+
return d
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/startOfISOWeekYear/index.ts
|
|
658
|
+
function startOfWeekYear(date: Date): Date {
|
|
659
|
+
const year = getWeekYear(date)
|
|
660
|
+
const fourthOfJanuary = new Date(0)
|
|
661
|
+
fourthOfJanuary.setFullYear(year, 0, 4)
|
|
662
|
+
fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
663
|
+
return startOfWeek(fourthOfJanuary, true)
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/getISOWeekYear/index.ts
|
|
667
|
+
function getWeekYear(date: Date): number {
|
|
668
|
+
const year = date.getFullYear()
|
|
669
|
+
|
|
670
|
+
const fourthOfJanuaryOfNextYear = new Date(0)
|
|
671
|
+
fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4)
|
|
672
|
+
fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0)
|
|
673
|
+
const startOfNextYear = startOfWeek(fourthOfJanuaryOfNextYear, true)
|
|
674
|
+
|
|
675
|
+
const fourthOfJanuaryOfThisYear = new Date(0)
|
|
676
|
+
fourthOfJanuaryOfThisYear.setFullYear(year, 0, 4)
|
|
677
|
+
fourthOfJanuaryOfThisYear.setHours(0, 0, 0, 0)
|
|
678
|
+
const startOfThisYear = startOfWeek(fourthOfJanuaryOfThisYear, true)
|
|
679
|
+
|
|
680
|
+
if (date.getTime() >= startOfNextYear.getTime()) {
|
|
681
|
+
return year + 1
|
|
682
|
+
} else if (date.getTime() >= startOfThisYear.getTime()) {
|
|
683
|
+
return year
|
|
684
|
+
} else {
|
|
685
|
+
return year - 1
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// function setWeekYear(
|
|
690
|
+
// date: Date,
|
|
691
|
+
// year: number,
|
|
692
|
+
// ): Date {
|
|
693
|
+
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
694
|
+
// const fourthOfJanuary = new Date(0)
|
|
695
|
+
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
696
|
+
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
697
|
+
// date = startOfWeekYear(fourthOfJanuary)
|
|
698
|
+
// date.setDate(date.getDate() + diff)
|
|
699
|
+
// return date
|
|
700
|
+
// }
|
|
701
|
+
|
|
702
|
+
// function differenceInCalendarDays(
|
|
703
|
+
// dateLeft: Date,
|
|
704
|
+
// dateRight: Date,
|
|
705
|
+
// ): number {
|
|
706
|
+
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
707
|
+
// }
|
|
708
|
+
|
|
709
|
+
// function startOfDay(date: Date, mutate = false): Date {
|
|
710
|
+
// const d = mutate ? date : new Date(date)
|
|
711
|
+
// d.setHours(0, 0, 0, 0)
|
|
712
|
+
// return d
|
|
713
|
+
// }
|
|
714
|
+
|
|
715
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
716
|
+
function startOfWeek(date: Date, mutate = false): Date {
|
|
717
|
+
const d = mutate ? date : new Date(date)
|
|
718
|
+
|
|
719
|
+
const day = d.getDay()
|
|
720
|
+
const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn
|
|
721
|
+
|
|
722
|
+
d.setDate(d.getDate() - diff)
|
|
723
|
+
d.setHours(0, 0, 0, 0)
|
|
724
|
+
return d
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/endOfWeek/index.ts
|
|
728
|
+
function endOfWeek(date: Date, mutate = false): Date {
|
|
729
|
+
const d = mutate ? date : new Date(date)
|
|
730
|
+
|
|
731
|
+
const day = d.getDay()
|
|
732
|
+
const diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn)
|
|
733
|
+
|
|
734
|
+
d.setDate(d.getDate() + diff)
|
|
735
|
+
return d
|
|
736
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -162,8 +162,20 @@ export * from './datetime/localDate'
|
|
|
162
162
|
export * from './datetime/localTime'
|
|
163
163
|
export * from './datetime/dateInterval'
|
|
164
164
|
export * from './datetime/timeInterval'
|
|
165
|
-
import {
|
|
166
|
-
|
|
165
|
+
import {
|
|
166
|
+
LocalDateConfig,
|
|
167
|
+
LocalDateFormatter,
|
|
168
|
+
LocalDateUnit,
|
|
169
|
+
LocalDateUnitStrict,
|
|
170
|
+
Inclusiveness,
|
|
171
|
+
} from './datetime/localDate'
|
|
172
|
+
import {
|
|
173
|
+
LocalTimeConfig,
|
|
174
|
+
LocalTimeFormatter,
|
|
175
|
+
LocalTimeUnit,
|
|
176
|
+
LocalTimeComponents,
|
|
177
|
+
ISODayOfWeek,
|
|
178
|
+
} from './datetime/localTime'
|
|
167
179
|
import { DateIntervalConfig, DateIntervalString } from './datetime/dateInterval'
|
|
168
180
|
import { TimeIntervalConfig, TimeIntervalString } from './datetime/timeInterval'
|
|
169
181
|
|
|
@@ -173,10 +185,14 @@ export type {
|
|
|
173
185
|
TimeIntervalConfig,
|
|
174
186
|
TimeIntervalString,
|
|
175
187
|
LocalDateConfig,
|
|
188
|
+
LocalDateFormatter,
|
|
176
189
|
LocalDateUnit,
|
|
190
|
+
LocalDateUnitStrict,
|
|
177
191
|
Inclusiveness,
|
|
178
192
|
LocalTimeConfig,
|
|
193
|
+
LocalTimeFormatter,
|
|
179
194
|
LocalTimeUnit,
|
|
195
|
+
ISODayOfWeek,
|
|
180
196
|
LocalTimeComponents,
|
|
181
197
|
AbortableMapper,
|
|
182
198
|
AbortablePredicate,
|
package/src/promise/pRetry.ts
CHANGED
|
@@ -169,7 +169,7 @@ export async function pRetry<T>(
|
|
|
169
169
|
|
|
170
170
|
const r = await fn(attempt)
|
|
171
171
|
|
|
172
|
-
clearTimeout(timer
|
|
172
|
+
clearTimeout(timer)
|
|
173
173
|
|
|
174
174
|
if (logSuccess) {
|
|
175
175
|
logger.log(`${fname} attempt #${attempt} succeeded in ${_since(started)}`)
|
|
@@ -177,7 +177,7 @@ export async function pRetry<T>(
|
|
|
177
177
|
|
|
178
178
|
resolve(r)
|
|
179
179
|
} catch (err) {
|
|
180
|
-
clearTimeout(timer
|
|
180
|
+
clearTimeout(timer)
|
|
181
181
|
|
|
182
182
|
if (logFailures) {
|
|
183
183
|
logger.warn(
|