@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.
- package/dist/array/array.util.d.ts +10 -1
- package/dist/array/array.util.js +36 -2
- package/dist/datetime/localDate.d.ts +12 -9
- package/dist/datetime/localDate.js +21 -3
- package/dist/datetime/localTime.d.ts +24 -5
- package/dist/datetime/localTime.js +171 -9
- 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 +21 -3
- package/dist-esm/datetime/localTime.js +170 -8
- package/dist-esm/index.js +1 -0
- package/package.json +1 -1
- package/src/array/array.util.ts +30 -1
- package/src/datetime/localDate.ts +36 -12
- package/src/datetime/localTime.ts +202 -15
- package/src/index.ts +18 -2
|
@@ -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,12 @@ 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 MILLISECONDS_IN_DAY = 86400000
|
|
33
|
+
// const MILLISECONDS_IN_MINUTE = 60000
|
|
34
|
+
const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7])
|
|
35
|
+
|
|
19
36
|
/* eslint-disable no-dupe-class-members */
|
|
20
37
|
|
|
21
38
|
/**
|
|
@@ -134,6 +151,9 @@ export class LocalTime {
|
|
|
134
151
|
if (unit === 'minute') {
|
|
135
152
|
return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes()
|
|
136
153
|
}
|
|
154
|
+
if (unit === 'week') {
|
|
155
|
+
return getWeek(this.$date)
|
|
156
|
+
}
|
|
137
157
|
// second
|
|
138
158
|
return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds()
|
|
139
159
|
}
|
|
@@ -154,6 +174,8 @@ export class LocalTime {
|
|
|
154
174
|
this.utcMode ? t.$date.setUTCMinutes(v) : t.$date.setMinutes(v)
|
|
155
175
|
} else if (unit === 'second') {
|
|
156
176
|
this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v)
|
|
177
|
+
} else if (unit === 'week') {
|
|
178
|
+
setWeek(t.$date, v, true)
|
|
157
179
|
}
|
|
158
180
|
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
159
181
|
|
|
@@ -170,11 +192,33 @@ export class LocalTime {
|
|
|
170
192
|
month(v?: number): number | LocalTime {
|
|
171
193
|
return v === undefined ? this.get('month') : this.set('month', v)
|
|
172
194
|
}
|
|
195
|
+
week(): number
|
|
196
|
+
week(v: number): LocalTime
|
|
197
|
+
week(v?: number): number | LocalTime {
|
|
198
|
+
return v === undefined ? getWeek(this.$date) : this.set('week', v)
|
|
199
|
+
}
|
|
173
200
|
day(): number
|
|
174
201
|
day(v: number): LocalTime
|
|
175
202
|
day(v?: number): number | LocalTime {
|
|
176
203
|
return v === undefined ? this.get('day') : this.set('day', v)
|
|
177
204
|
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Based on ISO: 1-7 is Mon-Sun.
|
|
208
|
+
*/
|
|
209
|
+
dayOfWeek(): ISODayOfWeek
|
|
210
|
+
dayOfWeek(v: ISODayOfWeek): LocalTime
|
|
211
|
+
dayOfWeek(v?: ISODayOfWeek): ISODayOfWeek | LocalTime {
|
|
212
|
+
const dow = (this.$date.getDay() || 7) as ISODayOfWeek
|
|
213
|
+
|
|
214
|
+
if (v === undefined) {
|
|
215
|
+
return dow
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!VALID_DAYS_OF_WEEK.has(v)) throw new Error(`Invalid dayOfWeek: ${v}`)
|
|
219
|
+
|
|
220
|
+
return this.add(v - dow, 'day')
|
|
221
|
+
}
|
|
178
222
|
hour(): number
|
|
179
223
|
hour(v: number): LocalTime
|
|
180
224
|
hour(v?: number): number | LocalTime {
|
|
@@ -219,6 +263,10 @@ export class LocalTime {
|
|
|
219
263
|
}
|
|
220
264
|
|
|
221
265
|
add(num: number, unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
266
|
+
if (unit === 'week') {
|
|
267
|
+
num *= 7
|
|
268
|
+
unit = 'day'
|
|
269
|
+
}
|
|
222
270
|
return this.set(unit, this.get(unit) + num, mutate)
|
|
223
271
|
}
|
|
224
272
|
|
|
@@ -249,6 +297,8 @@ export class LocalTime {
|
|
|
249
297
|
|
|
250
298
|
if (unit === 'day') {
|
|
251
299
|
r = secDiff / (24 * 60 * 60)
|
|
300
|
+
} else if (unit === 'week') {
|
|
301
|
+
r = secDiff / (7 * 24 * 60 * 60)
|
|
252
302
|
} else if (unit === 'hour') {
|
|
253
303
|
r = secDiff / (60 * 60)
|
|
254
304
|
} else if (unit === 'minute') {
|
|
@@ -258,17 +308,15 @@ export class LocalTime {
|
|
|
258
308
|
r = secDiff
|
|
259
309
|
}
|
|
260
310
|
|
|
261
|
-
r =
|
|
311
|
+
r = Math.trunc(r)
|
|
262
312
|
if (Object.is(r, -0)) return 0
|
|
263
313
|
return r
|
|
264
314
|
}
|
|
265
315
|
|
|
266
316
|
startOf(unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
267
317
|
if (unit === 'second') return this
|
|
268
|
-
|
|
269
318
|
const d = mutate ? this.$date : new Date(this.$date)
|
|
270
|
-
d.
|
|
271
|
-
d.setSeconds(0)
|
|
319
|
+
d.setSeconds(0, 0)
|
|
272
320
|
|
|
273
321
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
274
322
|
if (unit !== 'minute') {
|
|
@@ -276,9 +324,48 @@ export class LocalTime {
|
|
|
276
324
|
if (unit !== 'hour') {
|
|
277
325
|
this.utcMode ? d.setUTCHours(0) : d.setHours(0)
|
|
278
326
|
if (unit !== 'day') {
|
|
279
|
-
|
|
280
|
-
|
|
327
|
+
// year, month or week
|
|
328
|
+
|
|
329
|
+
if (unit === 'year') {
|
|
281
330
|
this.utcMode ? d.setUTCMonth(0) : d.setMonth(0)
|
|
331
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1)
|
|
332
|
+
} else if (unit === 'month') {
|
|
333
|
+
this.utcMode ? d.setUTCDate(1) : d.setDate(1)
|
|
334
|
+
} else {
|
|
335
|
+
// week
|
|
336
|
+
startOfWeek(d, true)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
342
|
+
|
|
343
|
+
return mutate ? this : new LocalTime(d, this.utcMode)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
endOf(unit: LocalTimeUnit, mutate = false): LocalTime {
|
|
347
|
+
if (unit === 'second') return this
|
|
348
|
+
const d = mutate ? this.$date : new Date(this.$date)
|
|
349
|
+
d.setSeconds(59, 0)
|
|
350
|
+
|
|
351
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
352
|
+
if (unit !== 'minute') {
|
|
353
|
+
this.utcMode ? d.setUTCMinutes(59) : d.setMinutes(59)
|
|
354
|
+
if (unit !== 'hour') {
|
|
355
|
+
this.utcMode ? d.setUTCHours(23) : d.setHours(23)
|
|
356
|
+
if (unit !== 'day') {
|
|
357
|
+
// year, month or week
|
|
358
|
+
|
|
359
|
+
if (unit === 'year') {
|
|
360
|
+
this.utcMode ? d.setUTCMonth(11) : d.setMonth(11)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (unit === 'week') {
|
|
364
|
+
endOfWeek(d, true)
|
|
365
|
+
} else {
|
|
366
|
+
// year or month
|
|
367
|
+
const lastDay = LocalDate.getMonthLength(d.getFullYear(), d.getMonth() + 1)
|
|
368
|
+
this.utcMode ? d.setUTCDate(lastDay) : d.setDate(lastDay)
|
|
282
369
|
}
|
|
283
370
|
}
|
|
284
371
|
}
|
|
@@ -298,24 +385,28 @@ export class LocalTime {
|
|
|
298
385
|
})
|
|
299
386
|
}
|
|
300
387
|
|
|
301
|
-
static earliestOrUndefined(items:
|
|
388
|
+
static earliestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined {
|
|
302
389
|
return items.length ? LocalTime.earliest(items) : undefined
|
|
303
390
|
}
|
|
304
391
|
|
|
305
|
-
static earliest(items:
|
|
392
|
+
static earliest(items: LocalTimeConfig[]): LocalTime {
|
|
306
393
|
_assert(items.length, 'LocalTime.earliest called on empty array')
|
|
307
394
|
|
|
308
|
-
return items
|
|
395
|
+
return items
|
|
396
|
+
.map(i => LocalTime.of(i))
|
|
397
|
+
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
|
|
309
398
|
}
|
|
310
399
|
|
|
311
|
-
static latestOrUndefined(items:
|
|
400
|
+
static latestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined {
|
|
312
401
|
return items.length ? LocalTime.latest(items) : undefined
|
|
313
402
|
}
|
|
314
403
|
|
|
315
|
-
static latest(items:
|
|
404
|
+
static latest(items: LocalTimeConfig[]): LocalTime {
|
|
316
405
|
_assert(items.length, 'LocalTime.latest called on empty array')
|
|
317
406
|
|
|
318
|
-
return items
|
|
407
|
+
return items
|
|
408
|
+
.map(i => LocalTime.of(i))
|
|
409
|
+
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
|
|
319
410
|
}
|
|
320
411
|
|
|
321
412
|
isSame(d: LocalTimeConfig): boolean {
|
|
@@ -360,8 +451,6 @@ export class LocalTime {
|
|
|
360
451
|
return t1 < t2 ? -1 : 1
|
|
361
452
|
}
|
|
362
453
|
|
|
363
|
-
// todo: endOf
|
|
364
|
-
|
|
365
454
|
components(): LocalTimeComponents {
|
|
366
455
|
if (this.utcMode) {
|
|
367
456
|
return {
|
|
@@ -520,6 +609,10 @@ export class LocalTime {
|
|
|
520
609
|
toJSON(): UnixTimestampNumber {
|
|
521
610
|
return this.unix()
|
|
522
611
|
}
|
|
612
|
+
|
|
613
|
+
format(fmt: LocalTimeFormatter): string {
|
|
614
|
+
return fmt(this)
|
|
615
|
+
}
|
|
523
616
|
}
|
|
524
617
|
|
|
525
618
|
/**
|
|
@@ -528,3 +621,97 @@ export class LocalTime {
|
|
|
528
621
|
export function localTime(d?: LocalTimeConfig): LocalTime {
|
|
529
622
|
return d ? LocalTime.of(d) : LocalTime.now()
|
|
530
623
|
}
|
|
624
|
+
|
|
625
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
|
|
626
|
+
function getWeek(date: Date): number {
|
|
627
|
+
const diff = startOfWeek(date).getTime() - startOfWeekYear(date).getTime()
|
|
628
|
+
return Math.round(diff / MILLISECONDS_IN_WEEK) + 1
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function setWeek(date: Date, week: number, mutate = false): Date {
|
|
632
|
+
const d = mutate ? date : new Date(date)
|
|
633
|
+
const diff = getWeek(d) - week
|
|
634
|
+
d.setDate(d.getDate() - diff * 7)
|
|
635
|
+
return d
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/startOfISOWeekYear/index.ts
|
|
639
|
+
function startOfWeekYear(date: Date): Date {
|
|
640
|
+
const year = getWeekYear(date)
|
|
641
|
+
const fourthOfJanuary = new Date(0)
|
|
642
|
+
fourthOfJanuary.setFullYear(year, 0, 4)
|
|
643
|
+
fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
644
|
+
return startOfWeek(fourthOfJanuary, true)
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/getISOWeekYear/index.ts
|
|
648
|
+
function getWeekYear(date: Date): number {
|
|
649
|
+
const year = date.getFullYear()
|
|
650
|
+
|
|
651
|
+
const fourthOfJanuaryOfNextYear = new Date(0)
|
|
652
|
+
fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4)
|
|
653
|
+
fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0)
|
|
654
|
+
const startOfNextYear = startOfWeek(fourthOfJanuaryOfNextYear, true)
|
|
655
|
+
|
|
656
|
+
const fourthOfJanuaryOfThisYear = new Date(0)
|
|
657
|
+
fourthOfJanuaryOfThisYear.setFullYear(year, 0, 4)
|
|
658
|
+
fourthOfJanuaryOfThisYear.setHours(0, 0, 0, 0)
|
|
659
|
+
const startOfThisYear = startOfWeek(fourthOfJanuaryOfThisYear, true)
|
|
660
|
+
|
|
661
|
+
if (date.getTime() >= startOfNextYear.getTime()) {
|
|
662
|
+
return year + 1
|
|
663
|
+
} else if (date.getTime() >= startOfThisYear.getTime()) {
|
|
664
|
+
return year
|
|
665
|
+
} else {
|
|
666
|
+
return year - 1
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// function setWeekYear(
|
|
671
|
+
// date: Date,
|
|
672
|
+
// year: number,
|
|
673
|
+
// ): Date {
|
|
674
|
+
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
675
|
+
// const fourthOfJanuary = new Date(0)
|
|
676
|
+
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
677
|
+
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
678
|
+
// date = startOfWeekYear(fourthOfJanuary)
|
|
679
|
+
// date.setDate(date.getDate() + diff)
|
|
680
|
+
// return date
|
|
681
|
+
// }
|
|
682
|
+
|
|
683
|
+
// function differenceInCalendarDays(
|
|
684
|
+
// dateLeft: Date,
|
|
685
|
+
// dateRight: Date,
|
|
686
|
+
// ): number {
|
|
687
|
+
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
688
|
+
// }
|
|
689
|
+
|
|
690
|
+
// function startOfDay(date: Date, mutate = false): Date {
|
|
691
|
+
// const d = mutate ? date : new Date(date)
|
|
692
|
+
// d.setHours(0, 0, 0, 0)
|
|
693
|
+
// return d
|
|
694
|
+
// }
|
|
695
|
+
|
|
696
|
+
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
697
|
+
function startOfWeek(date: Date, mutate = false): Date {
|
|
698
|
+
const d = mutate ? date : new Date(date)
|
|
699
|
+
|
|
700
|
+
const day = d.getDay()
|
|
701
|
+
const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn
|
|
702
|
+
|
|
703
|
+
d.setDate(d.getDate() - diff)
|
|
704
|
+
d.setHours(0, 0, 0, 0)
|
|
705
|
+
return d
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// based on: https://github.com/date-fns/date-fns/blob/master/src/endOfWeek/index.ts
|
|
709
|
+
function endOfWeek(date: Date, mutate = false): Date {
|
|
710
|
+
const d = mutate ? date : new Date(date)
|
|
711
|
+
|
|
712
|
+
const day = d.getDay()
|
|
713
|
+
const diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn)
|
|
714
|
+
|
|
715
|
+
d.setDate(d.getDate() + diff)
|
|
716
|
+
return d
|
|
717
|
+
}
|
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,
|