@naturalcycles/js-lib 14.99.3 → 14.101.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/datetime/localDate.d.ts +2 -2
- package/dist/datetime/localDate.js +37 -22
- package/dist/datetime/localTime.d.ts +6 -2
- package/dist/datetime/localTime.js +54 -58
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +6 -0
- package/dist-esm/datetime/localDate.js +37 -22
- package/dist-esm/datetime/localTime.js +55 -58
- package/package.json +1 -1
- package/src/datetime/localDate.ts +49 -25
- package/src/datetime/localTime.ts +72 -66
- package/src/index.ts +2 -0
- package/src/types.ts +7 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types';
|
|
1
|
+
import { IsoDateString, IsoDateTimeString, UnixTimestampMillisNumber, UnixTimestampNumber } from '../types';
|
|
2
2
|
import { LocalTime } from './localTime';
|
|
3
3
|
export declare type LocalDateUnit = LocalDateUnitStrict | 'week';
|
|
4
4
|
export declare type LocalDateUnitStrict = 'year' | 'month' | 'day';
|
|
@@ -89,7 +89,7 @@ export declare class LocalDate {
|
|
|
89
89
|
toString(): IsoDateString;
|
|
90
90
|
toStringCompact(): string;
|
|
91
91
|
unix(): UnixTimestampNumber;
|
|
92
|
-
unixMillis():
|
|
92
|
+
unixMillis(): UnixTimestampMillisNumber;
|
|
93
93
|
toJSON(): IsoDateString;
|
|
94
94
|
format(fmt: LocalDateFormatter): string;
|
|
95
95
|
}
|
|
@@ -218,15 +218,23 @@ class LocalDate {
|
|
|
218
218
|
const [big, small] = sign === 1 ? [this, d] : [d, this];
|
|
219
219
|
if (unit === 'year') {
|
|
220
220
|
let years = big.$year - small.$year;
|
|
221
|
-
if (big.$month < small.$month ||
|
|
221
|
+
if (big.$month < small.$month ||
|
|
222
|
+
(big.$month === small.$month &&
|
|
223
|
+
big.$day < small.$day &&
|
|
224
|
+
!(big.$day === LocalDate.getMonthLength(big.$year, big.$month) &&
|
|
225
|
+
small.$day === LocalDate.getMonthLength(small.$year, small.$month)))) {
|
|
222
226
|
years--;
|
|
223
227
|
}
|
|
224
228
|
return years * sign || 0;
|
|
225
229
|
}
|
|
226
230
|
if (unit === 'month') {
|
|
227
231
|
let months = (big.$year - small.$year) * 12 + (big.$month - small.$month);
|
|
228
|
-
if (big.$day < small.$day)
|
|
229
|
-
|
|
232
|
+
if (big.$day < small.$day) {
|
|
233
|
+
const bigMonthLen = LocalDate.getMonthLength(big.$year, big.$month);
|
|
234
|
+
if (big.$day !== bigMonthLen || small.$day < bigMonthLen) {
|
|
235
|
+
months--;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
230
238
|
return months * sign || 0;
|
|
231
239
|
}
|
|
232
240
|
// unit is 'day' or 'week'
|
|
@@ -266,20 +274,36 @@ class LocalDate {
|
|
|
266
274
|
else if (unit === 'year') {
|
|
267
275
|
$year += num;
|
|
268
276
|
}
|
|
277
|
+
// check month overflow
|
|
278
|
+
while ($month > 12) {
|
|
279
|
+
$year += 1;
|
|
280
|
+
$month -= 12;
|
|
281
|
+
}
|
|
282
|
+
while ($month < 1) {
|
|
283
|
+
$year -= 1;
|
|
284
|
+
$month += 12;
|
|
285
|
+
}
|
|
269
286
|
// check day overflow
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
287
|
+
// Applies not only for 'day' unit, but also e.g 2022-05-31 plus 1 month should be 2022-06-30 (not 31!)
|
|
288
|
+
if ($day < 1) {
|
|
289
|
+
while ($day < 1) {
|
|
290
|
+
$month -= 1;
|
|
291
|
+
if ($month < 1) {
|
|
292
|
+
$year -= 1;
|
|
293
|
+
$month += 12;
|
|
294
|
+
}
|
|
295
|
+
$day += LocalDate.getMonthLength($year, $month);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
let monLen = LocalDate.getMonthLength($year, $month);
|
|
300
|
+
if (unit !== 'day') {
|
|
301
|
+
if ($day > monLen) {
|
|
302
|
+
// Case of 2022-05-31 plus 1 month should be 2022-06-30, not 31
|
|
303
|
+
$day = monLen;
|
|
279
304
|
}
|
|
280
305
|
}
|
|
281
306
|
else {
|
|
282
|
-
let monLen = LocalDate.getMonthLength($year, $month);
|
|
283
307
|
while ($day > monLen) {
|
|
284
308
|
$day -= monLen;
|
|
285
309
|
$month += 1;
|
|
@@ -291,15 +315,6 @@ class LocalDate {
|
|
|
291
315
|
}
|
|
292
316
|
}
|
|
293
317
|
}
|
|
294
|
-
// check month overflow
|
|
295
|
-
while ($month > 12) {
|
|
296
|
-
$year += 1;
|
|
297
|
-
$month -= 12;
|
|
298
|
-
}
|
|
299
|
-
while ($month < 1) {
|
|
300
|
-
$year -= 1;
|
|
301
|
-
$month += 12;
|
|
302
|
-
}
|
|
303
318
|
if (mutate) {
|
|
304
319
|
this.$year = $year;
|
|
305
320
|
this.$month = $month;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types';
|
|
1
|
+
import { IsoDateString, IsoDateTimeString, UnixTimestampMillisNumber, UnixTimestampNumber } from '../types';
|
|
2
2
|
import { Inclusiveness, LocalDate } from './localDate';
|
|
3
3
|
export declare type LocalTimeUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second';
|
|
4
4
|
export declare enum ISODayOfWeek {
|
|
@@ -31,6 +31,10 @@ export declare class LocalTime {
|
|
|
31
31
|
* Input can already be a LocalDate - it is returned as-is in that case.
|
|
32
32
|
*/
|
|
33
33
|
static of(d: LocalTimeConfig): LocalTime;
|
|
34
|
+
/**
|
|
35
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
36
|
+
*/
|
|
37
|
+
static ofMillis(millis: UnixTimestampMillisNumber): LocalTime;
|
|
34
38
|
/**
|
|
35
39
|
* Returns null if invalid
|
|
36
40
|
*/
|
|
@@ -93,7 +97,7 @@ export declare class LocalTime {
|
|
|
93
97
|
getDate(): Date;
|
|
94
98
|
clone(): LocalTime;
|
|
95
99
|
unix(): UnixTimestampNumber;
|
|
96
|
-
unixMillis():
|
|
100
|
+
unixMillis(): UnixTimestampMillisNumber;
|
|
97
101
|
valueOf(): UnixTimestampNumber;
|
|
98
102
|
toLocalDate(): LocalDate;
|
|
99
103
|
toPretty(seconds?: boolean): IsoDateTimeString;
|
|
@@ -39,6 +39,12 @@ class LocalTime {
|
|
|
39
39
|
}
|
|
40
40
|
return t;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
44
|
+
*/
|
|
45
|
+
static ofMillis(millis) {
|
|
46
|
+
return LocalTime.of(new Date(millis));
|
|
47
|
+
}
|
|
42
48
|
/**
|
|
43
49
|
* Returns null if invalid
|
|
44
50
|
*/
|
|
@@ -177,14 +183,9 @@ class LocalTime {
|
|
|
177
183
|
}
|
|
178
184
|
setComponents(c, mutate = false) {
|
|
179
185
|
const d = mutate ? this.$date : new Date(this.$date);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (c.month) {
|
|
184
|
-
d.setMonth(c.month - 1);
|
|
185
|
-
}
|
|
186
|
-
if (c.day) {
|
|
187
|
-
d.setDate(c.day);
|
|
186
|
+
// Year, month and day set all-at-once, to avoid 30/31 (and 28/29) mishap
|
|
187
|
+
if (c.day || c.month !== undefined || c.year !== undefined) {
|
|
188
|
+
d.setFullYear(c.year ?? d.getFullYear(), c.month ? c.month - 1 : d.getMonth(), c.day || d.getDate());
|
|
188
189
|
}
|
|
189
190
|
if (c.hour !== undefined) {
|
|
190
191
|
d.setHours(c.hour);
|
|
@@ -202,6 +203,10 @@ class LocalTime {
|
|
|
202
203
|
num *= 7;
|
|
203
204
|
unit = 'day';
|
|
204
205
|
}
|
|
206
|
+
if (unit === 'year' || unit === 'month') {
|
|
207
|
+
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
|
|
208
|
+
return mutate ? this : LocalTime.of(d);
|
|
209
|
+
}
|
|
205
210
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
206
211
|
}
|
|
207
212
|
subtract(num, unit, mutate = false) {
|
|
@@ -215,33 +220,14 @@ class LocalTime {
|
|
|
215
220
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
216
221
|
if (!secDiff)
|
|
217
222
|
return 0;
|
|
218
|
-
if (unit === 'year' || unit === 'month') {
|
|
219
|
-
const sign = secDiff > 0 ? 1 : -1;
|
|
220
|
-
// Put items in descending order: "big minus small"
|
|
221
|
-
const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date];
|
|
222
|
-
if (unit === 'year') {
|
|
223
|
-
let years = big.getFullYear() - small.getFullYear();
|
|
224
|
-
const big2 = new Date(big);
|
|
225
|
-
const small2 = new Date(small);
|
|
226
|
-
big2.setFullYear(1584);
|
|
227
|
-
small2.setFullYear(1584);
|
|
228
|
-
if (big2 < small2)
|
|
229
|
-
years--;
|
|
230
|
-
return years * sign || 0;
|
|
231
|
-
}
|
|
232
|
-
if (unit === 'month') {
|
|
233
|
-
let months = (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth();
|
|
234
|
-
const big2 = new Date(big);
|
|
235
|
-
const small2 = new Date(small);
|
|
236
|
-
big2.setFullYear(1584, 0);
|
|
237
|
-
small2.setFullYear(1584, 0);
|
|
238
|
-
if (big2 < small2)
|
|
239
|
-
months--;
|
|
240
|
-
return months * sign || 0;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
223
|
let r;
|
|
244
|
-
if (unit === '
|
|
224
|
+
if (unit === 'year') {
|
|
225
|
+
r = differenceInMonths(this.getDate(), date2) / 12;
|
|
226
|
+
}
|
|
227
|
+
else if (unit === 'month') {
|
|
228
|
+
r = differenceInMonths(this.getDate(), date2);
|
|
229
|
+
}
|
|
230
|
+
else if (unit === 'day') {
|
|
245
231
|
r = secDiff / SECONDS_IN_DAY;
|
|
246
232
|
}
|
|
247
233
|
else if (unit === 'week') {
|
|
@@ -486,7 +472,7 @@ class LocalTime {
|
|
|
486
472
|
].join('');
|
|
487
473
|
}
|
|
488
474
|
toString() {
|
|
489
|
-
return
|
|
475
|
+
return this.toISODateTime();
|
|
490
476
|
}
|
|
491
477
|
toJSON() {
|
|
492
478
|
return this.unix();
|
|
@@ -543,29 +529,6 @@ function getWeekYear(date) {
|
|
|
543
529
|
return year - 1;
|
|
544
530
|
}
|
|
545
531
|
}
|
|
546
|
-
// function setWeekYear(
|
|
547
|
-
// date: Date,
|
|
548
|
-
// year: number,
|
|
549
|
-
// ): Date {
|
|
550
|
-
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
551
|
-
// const fourthOfJanuary = new Date(0)
|
|
552
|
-
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
553
|
-
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
554
|
-
// date = startOfWeekYear(fourthOfJanuary)
|
|
555
|
-
// date.setDate(date.getDate() + diff)
|
|
556
|
-
// return date
|
|
557
|
-
// }
|
|
558
|
-
// function differenceInCalendarDays(
|
|
559
|
-
// dateLeft: Date,
|
|
560
|
-
// dateRight: Date,
|
|
561
|
-
// ): number {
|
|
562
|
-
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
563
|
-
// }
|
|
564
|
-
// function startOfDay(date: Date, mutate = false): Date {
|
|
565
|
-
// const d = mutate ? date : new Date(date)
|
|
566
|
-
// d.setHours(0, 0, 0, 0)
|
|
567
|
-
// return d
|
|
568
|
-
// }
|
|
569
532
|
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
570
533
|
function startOfWeek(date, mutate = false) {
|
|
571
534
|
const d = mutate ? date : new Date(date);
|
|
@@ -583,3 +546,36 @@ function endOfWeek(date, mutate = false) {
|
|
|
583
546
|
d.setDate(d.getDate() + diff);
|
|
584
547
|
return d;
|
|
585
548
|
}
|
|
549
|
+
function addMonths(d, num, mutate = false) {
|
|
550
|
+
if (!mutate)
|
|
551
|
+
d = new Date(d);
|
|
552
|
+
let day = d.getDate();
|
|
553
|
+
let month = d.getMonth() + 1 + num;
|
|
554
|
+
if (day < 29) {
|
|
555
|
+
d.setMonth(month - 1);
|
|
556
|
+
return d;
|
|
557
|
+
}
|
|
558
|
+
let year = d.getFullYear();
|
|
559
|
+
while (month > 12) {
|
|
560
|
+
year++;
|
|
561
|
+
month -= 12;
|
|
562
|
+
}
|
|
563
|
+
while (month < 1) {
|
|
564
|
+
year--;
|
|
565
|
+
month += 12;
|
|
566
|
+
}
|
|
567
|
+
const monthLen = localDate_1.LocalDate.getMonthLength(year, month);
|
|
568
|
+
if (day > monthLen)
|
|
569
|
+
day = monthLen;
|
|
570
|
+
d.setFullYear(year, month - 1, day);
|
|
571
|
+
return d;
|
|
572
|
+
}
|
|
573
|
+
function differenceInMonths(a, b) {
|
|
574
|
+
if (a.getDate() < b.getDate())
|
|
575
|
+
return -differenceInMonths(b, a);
|
|
576
|
+
const wholeMonthDiff = (b.getFullYear() - a.getFullYear()) * 12 + (b.getMonth() - a.getMonth());
|
|
577
|
+
const anchor = addMonths(a, wholeMonthDiff).getTime();
|
|
578
|
+
const sign = b.getTime() - anchor >= 0 ? 1 : -1;
|
|
579
|
+
const anchor2 = addMonths(a, wholeMonthDiff + sign).getTime();
|
|
580
|
+
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
|
|
581
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export * from './string/string.util';
|
|
|
51
51
|
import { JsonStringifyFunction, StringifyAnyOptions, _stringifyAny } from './string/stringifyAny';
|
|
52
52
|
export * from './time/time.util';
|
|
53
53
|
import { Class, ConditionalExcept, ConditionalPick, Merge, Promisable, ReadonlyDeep, Simplify } from './typeFest';
|
|
54
|
-
import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, UnsavedId, BatchResult, InstanceId, IsoDate, IsoDateString, IsoDateTimeString, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestampNumber, UnixTimestamp, Integer, ValueOf, ValuesOf, AbortableMapper, AbortableAsyncPredicate, AbortableAsyncMapper, AbortablePredicate, END, SKIP, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
|
|
54
|
+
import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, UnsavedId, BatchResult, InstanceId, IsoDate, IsoDateString, IsoDateTimeString, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestampNumber, UnixTimestampMillisNumber, UnixTimestamp, Integer, ValueOf, ValuesOf, AbortableMapper, AbortableAsyncPredicate, AbortableAsyncMapper, AbortablePredicate, END, SKIP, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
|
|
55
55
|
export * from './unit/size.util';
|
|
56
56
|
import { is } from './vendor/is';
|
|
57
57
|
import { CommonLogLevel, CommonLogFunction, CommonLogger, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, CommonLogWithLevelFunction, commonLoggerCreate } from './log/commonLogger';
|
|
@@ -68,5 +68,5 @@ import { LocalDateConfig, LocalDateFormatter, LocalDateUnit, LocalDateUnitStrict
|
|
|
68
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, 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, };
|
|
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, UnixTimestampMillisNumber, 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/types.d.ts
CHANGED
|
@@ -154,6 +154,12 @@ export declare type IsoDateTimeString = string;
|
|
|
154
154
|
* @example 1628945450
|
|
155
155
|
*/
|
|
156
156
|
export declare type UnixTimestampNumber = number;
|
|
157
|
+
/**
|
|
158
|
+
* Interface explicitly states that the value is a "Unix timestamp in **milleseconds**" (not seconds)
|
|
159
|
+
*
|
|
160
|
+
* @example 1628945450000
|
|
161
|
+
*/
|
|
162
|
+
export declare type UnixTimestampMillisNumber = number;
|
|
157
163
|
/**
|
|
158
164
|
* @deprecated use UnixTimestampNumber
|
|
159
165
|
*/
|
|
@@ -215,15 +215,23 @@ export class LocalDate {
|
|
|
215
215
|
const [big, small] = sign === 1 ? [this, d] : [d, this];
|
|
216
216
|
if (unit === 'year') {
|
|
217
217
|
let years = big.$year - small.$year;
|
|
218
|
-
if (big.$month < small.$month ||
|
|
218
|
+
if (big.$month < small.$month ||
|
|
219
|
+
(big.$month === small.$month &&
|
|
220
|
+
big.$day < small.$day &&
|
|
221
|
+
!(big.$day === LocalDate.getMonthLength(big.$year, big.$month) &&
|
|
222
|
+
small.$day === LocalDate.getMonthLength(small.$year, small.$month)))) {
|
|
219
223
|
years--;
|
|
220
224
|
}
|
|
221
225
|
return years * sign || 0;
|
|
222
226
|
}
|
|
223
227
|
if (unit === 'month') {
|
|
224
228
|
let months = (big.$year - small.$year) * 12 + (big.$month - small.$month);
|
|
225
|
-
if (big.$day < small.$day)
|
|
226
|
-
|
|
229
|
+
if (big.$day < small.$day) {
|
|
230
|
+
const bigMonthLen = LocalDate.getMonthLength(big.$year, big.$month);
|
|
231
|
+
if (big.$day !== bigMonthLen || small.$day < bigMonthLen) {
|
|
232
|
+
months--;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
227
235
|
return months * sign || 0;
|
|
228
236
|
}
|
|
229
237
|
// unit is 'day' or 'week'
|
|
@@ -263,20 +271,36 @@ export class LocalDate {
|
|
|
263
271
|
else if (unit === 'year') {
|
|
264
272
|
$year += num;
|
|
265
273
|
}
|
|
274
|
+
// check month overflow
|
|
275
|
+
while ($month > 12) {
|
|
276
|
+
$year += 1;
|
|
277
|
+
$month -= 12;
|
|
278
|
+
}
|
|
279
|
+
while ($month < 1) {
|
|
280
|
+
$year -= 1;
|
|
281
|
+
$month += 12;
|
|
282
|
+
}
|
|
266
283
|
// check day overflow
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
284
|
+
// Applies not only for 'day' unit, but also e.g 2022-05-31 plus 1 month should be 2022-06-30 (not 31!)
|
|
285
|
+
if ($day < 1) {
|
|
286
|
+
while ($day < 1) {
|
|
287
|
+
$month -= 1;
|
|
288
|
+
if ($month < 1) {
|
|
289
|
+
$year -= 1;
|
|
290
|
+
$month += 12;
|
|
291
|
+
}
|
|
292
|
+
$day += LocalDate.getMonthLength($year, $month);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
let monLen = LocalDate.getMonthLength($year, $month);
|
|
297
|
+
if (unit !== 'day') {
|
|
298
|
+
if ($day > monLen) {
|
|
299
|
+
// Case of 2022-05-31 plus 1 month should be 2022-06-30, not 31
|
|
300
|
+
$day = monLen;
|
|
276
301
|
}
|
|
277
302
|
}
|
|
278
303
|
else {
|
|
279
|
-
let monLen = LocalDate.getMonthLength($year, $month);
|
|
280
304
|
while ($day > monLen) {
|
|
281
305
|
$day -= monLen;
|
|
282
306
|
$month += 1;
|
|
@@ -288,15 +312,6 @@ export class LocalDate {
|
|
|
288
312
|
}
|
|
289
313
|
}
|
|
290
314
|
}
|
|
291
|
-
// check month overflow
|
|
292
|
-
while ($month > 12) {
|
|
293
|
-
$year += 1;
|
|
294
|
-
$month -= 12;
|
|
295
|
-
}
|
|
296
|
-
while ($month < 1) {
|
|
297
|
-
$year -= 1;
|
|
298
|
-
$month += 12;
|
|
299
|
-
}
|
|
300
315
|
if (mutate) {
|
|
301
316
|
this.$year = $year;
|
|
302
317
|
this.$month = $month;
|
|
@@ -36,6 +36,12 @@ export class LocalTime {
|
|
|
36
36
|
}
|
|
37
37
|
return t;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
41
|
+
*/
|
|
42
|
+
static ofMillis(millis) {
|
|
43
|
+
return LocalTime.of(new Date(millis));
|
|
44
|
+
}
|
|
39
45
|
/**
|
|
40
46
|
* Returns null if invalid
|
|
41
47
|
*/
|
|
@@ -173,15 +179,11 @@ export class LocalTime {
|
|
|
173
179
|
return v === undefined ? this.get('second') : this.set('second', v);
|
|
174
180
|
}
|
|
175
181
|
setComponents(c, mutate = false) {
|
|
182
|
+
var _a;
|
|
176
183
|
const d = mutate ? this.$date : new Date(this.$date);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (c.month) {
|
|
181
|
-
d.setMonth(c.month - 1);
|
|
182
|
-
}
|
|
183
|
-
if (c.day) {
|
|
184
|
-
d.setDate(c.day);
|
|
184
|
+
// Year, month and day set all-at-once, to avoid 30/31 (and 28/29) mishap
|
|
185
|
+
if (c.day || c.month !== undefined || c.year !== undefined) {
|
|
186
|
+
d.setFullYear((_a = c.year) !== null && _a !== void 0 ? _a : d.getFullYear(), c.month ? c.month - 1 : d.getMonth(), c.day || d.getDate());
|
|
185
187
|
}
|
|
186
188
|
if (c.hour !== undefined) {
|
|
187
189
|
d.setHours(c.hour);
|
|
@@ -199,6 +201,10 @@ export class LocalTime {
|
|
|
199
201
|
num *= 7;
|
|
200
202
|
unit = 'day';
|
|
201
203
|
}
|
|
204
|
+
if (unit === 'year' || unit === 'month') {
|
|
205
|
+
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate);
|
|
206
|
+
return mutate ? this : LocalTime.of(d);
|
|
207
|
+
}
|
|
202
208
|
return this.set(unit, this.get(unit) + num, mutate);
|
|
203
209
|
}
|
|
204
210
|
subtract(num, unit, mutate = false) {
|
|
@@ -212,33 +218,14 @@ export class LocalTime {
|
|
|
212
218
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
|
|
213
219
|
if (!secDiff)
|
|
214
220
|
return 0;
|
|
215
|
-
if (unit === 'year' || unit === 'month') {
|
|
216
|
-
const sign = secDiff > 0 ? 1 : -1;
|
|
217
|
-
// Put items in descending order: "big minus small"
|
|
218
|
-
const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date];
|
|
219
|
-
if (unit === 'year') {
|
|
220
|
-
let years = big.getFullYear() - small.getFullYear();
|
|
221
|
-
const big2 = new Date(big);
|
|
222
|
-
const small2 = new Date(small);
|
|
223
|
-
big2.setFullYear(1584);
|
|
224
|
-
small2.setFullYear(1584);
|
|
225
|
-
if (big2 < small2)
|
|
226
|
-
years--;
|
|
227
|
-
return years * sign || 0;
|
|
228
|
-
}
|
|
229
|
-
if (unit === 'month') {
|
|
230
|
-
let months = (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth();
|
|
231
|
-
const big2 = new Date(big);
|
|
232
|
-
const small2 = new Date(small);
|
|
233
|
-
big2.setFullYear(1584, 0);
|
|
234
|
-
small2.setFullYear(1584, 0);
|
|
235
|
-
if (big2 < small2)
|
|
236
|
-
months--;
|
|
237
|
-
return months * sign || 0;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
221
|
let r;
|
|
241
|
-
if (unit === '
|
|
222
|
+
if (unit === 'year') {
|
|
223
|
+
r = differenceInMonths(this.getDate(), date2) / 12;
|
|
224
|
+
}
|
|
225
|
+
else if (unit === 'month') {
|
|
226
|
+
r = differenceInMonths(this.getDate(), date2);
|
|
227
|
+
}
|
|
228
|
+
else if (unit === 'day') {
|
|
242
229
|
r = secDiff / SECONDS_IN_DAY;
|
|
243
230
|
}
|
|
244
231
|
else if (unit === 'week') {
|
|
@@ -483,7 +470,7 @@ export class LocalTime {
|
|
|
483
470
|
].join('');
|
|
484
471
|
}
|
|
485
472
|
toString() {
|
|
486
|
-
return
|
|
473
|
+
return this.toISODateTime();
|
|
487
474
|
}
|
|
488
475
|
toJSON() {
|
|
489
476
|
return this.unix();
|
|
@@ -538,29 +525,6 @@ function getWeekYear(date) {
|
|
|
538
525
|
return year - 1;
|
|
539
526
|
}
|
|
540
527
|
}
|
|
541
|
-
// function setWeekYear(
|
|
542
|
-
// date: Date,
|
|
543
|
-
// year: number,
|
|
544
|
-
// ): Date {
|
|
545
|
-
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
546
|
-
// const fourthOfJanuary = new Date(0)
|
|
547
|
-
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
548
|
-
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
549
|
-
// date = startOfWeekYear(fourthOfJanuary)
|
|
550
|
-
// date.setDate(date.getDate() + diff)
|
|
551
|
-
// return date
|
|
552
|
-
// }
|
|
553
|
-
// function differenceInCalendarDays(
|
|
554
|
-
// dateLeft: Date,
|
|
555
|
-
// dateRight: Date,
|
|
556
|
-
// ): number {
|
|
557
|
-
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
558
|
-
// }
|
|
559
|
-
// function startOfDay(date: Date, mutate = false): Date {
|
|
560
|
-
// const d = mutate ? date : new Date(date)
|
|
561
|
-
// d.setHours(0, 0, 0, 0)
|
|
562
|
-
// return d
|
|
563
|
-
// }
|
|
564
528
|
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
565
529
|
function startOfWeek(date, mutate = false) {
|
|
566
530
|
const d = mutate ? date : new Date(date);
|
|
@@ -578,3 +542,36 @@ function endOfWeek(date, mutate = false) {
|
|
|
578
542
|
d.setDate(d.getDate() + diff);
|
|
579
543
|
return d;
|
|
580
544
|
}
|
|
545
|
+
function addMonths(d, num, mutate = false) {
|
|
546
|
+
if (!mutate)
|
|
547
|
+
d = new Date(d);
|
|
548
|
+
let day = d.getDate();
|
|
549
|
+
let month = d.getMonth() + 1 + num;
|
|
550
|
+
if (day < 29) {
|
|
551
|
+
d.setMonth(month - 1);
|
|
552
|
+
return d;
|
|
553
|
+
}
|
|
554
|
+
let year = d.getFullYear();
|
|
555
|
+
while (month > 12) {
|
|
556
|
+
year++;
|
|
557
|
+
month -= 12;
|
|
558
|
+
}
|
|
559
|
+
while (month < 1) {
|
|
560
|
+
year--;
|
|
561
|
+
month += 12;
|
|
562
|
+
}
|
|
563
|
+
const monthLen = LocalDate.getMonthLength(year, month);
|
|
564
|
+
if (day > monthLen)
|
|
565
|
+
day = monthLen;
|
|
566
|
+
d.setFullYear(year, month - 1, day);
|
|
567
|
+
return d;
|
|
568
|
+
}
|
|
569
|
+
function differenceInMonths(a, b) {
|
|
570
|
+
if (a.getDate() < b.getDate())
|
|
571
|
+
return -differenceInMonths(b, a);
|
|
572
|
+
const wholeMonthDiff = (b.getFullYear() - a.getFullYear()) * 12 + (b.getMonth() - a.getMonth());
|
|
573
|
+
const anchor = addMonths(a, wholeMonthDiff).getTime();
|
|
574
|
+
const sign = b.getTime() - anchor >= 0 ? 1 : -1;
|
|
575
|
+
const anchor2 = addMonths(a, wholeMonthDiff + sign).getTime();
|
|
576
|
+
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign);
|
|
577
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { _assert } from '../error/assert'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
IsoDateString,
|
|
4
|
+
IsoDateTimeString,
|
|
5
|
+
UnixTimestampMillisNumber,
|
|
6
|
+
UnixTimestampNumber,
|
|
7
|
+
} from '../types'
|
|
3
8
|
import { LocalTime } from './localTime'
|
|
4
9
|
|
|
5
10
|
export type LocalDateUnit = LocalDateUnitStrict | 'week'
|
|
@@ -269,7 +274,15 @@ export class LocalDate {
|
|
|
269
274
|
if (unit === 'year') {
|
|
270
275
|
let years = big.$year - small.$year
|
|
271
276
|
|
|
272
|
-
if (
|
|
277
|
+
if (
|
|
278
|
+
big.$month < small.$month ||
|
|
279
|
+
(big.$month === small.$month &&
|
|
280
|
+
big.$day < small.$day &&
|
|
281
|
+
!(
|
|
282
|
+
big.$day === LocalDate.getMonthLength(big.$year, big.$month) &&
|
|
283
|
+
small.$day === LocalDate.getMonthLength(small.$year, small.$month)
|
|
284
|
+
))
|
|
285
|
+
) {
|
|
273
286
|
years--
|
|
274
287
|
}
|
|
275
288
|
|
|
@@ -278,7 +291,12 @@ export class LocalDate {
|
|
|
278
291
|
|
|
279
292
|
if (unit === 'month') {
|
|
280
293
|
let months = (big.$year - small.$year) * 12 + (big.$month - small.$month)
|
|
281
|
-
if (big.$day < small.$day)
|
|
294
|
+
if (big.$day < small.$day) {
|
|
295
|
+
const bigMonthLen = LocalDate.getMonthLength(big.$year, big.$month)
|
|
296
|
+
if (big.$day !== bigMonthLen || small.$day < bigMonthLen) {
|
|
297
|
+
months--
|
|
298
|
+
}
|
|
299
|
+
}
|
|
282
300
|
return months * sign || 0
|
|
283
301
|
}
|
|
284
302
|
|
|
@@ -324,21 +342,37 @@ export class LocalDate {
|
|
|
324
342
|
$year += num
|
|
325
343
|
}
|
|
326
344
|
|
|
345
|
+
// check month overflow
|
|
346
|
+
while ($month > 12) {
|
|
347
|
+
$year += 1
|
|
348
|
+
$month -= 12
|
|
349
|
+
}
|
|
350
|
+
while ($month < 1) {
|
|
351
|
+
$year -= 1
|
|
352
|
+
$month += 12
|
|
353
|
+
}
|
|
354
|
+
|
|
327
355
|
// check day overflow
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
356
|
+
// Applies not only for 'day' unit, but also e.g 2022-05-31 plus 1 month should be 2022-06-30 (not 31!)
|
|
357
|
+
if ($day < 1) {
|
|
358
|
+
while ($day < 1) {
|
|
359
|
+
$month -= 1
|
|
360
|
+
if ($month < 1) {
|
|
361
|
+
$year -= 1
|
|
362
|
+
$month += 12
|
|
363
|
+
}
|
|
336
364
|
|
|
337
|
-
|
|
365
|
+
$day += LocalDate.getMonthLength($year, $month)
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
let monLen = LocalDate.getMonthLength($year, $month)
|
|
369
|
+
|
|
370
|
+
if (unit !== 'day') {
|
|
371
|
+
if ($day > monLen) {
|
|
372
|
+
// Case of 2022-05-31 plus 1 month should be 2022-06-30, not 31
|
|
373
|
+
$day = monLen
|
|
338
374
|
}
|
|
339
375
|
} else {
|
|
340
|
-
let monLen = LocalDate.getMonthLength($year, $month)
|
|
341
|
-
|
|
342
376
|
while ($day > monLen) {
|
|
343
377
|
$day -= monLen
|
|
344
378
|
$month += 1
|
|
@@ -352,16 +386,6 @@ export class LocalDate {
|
|
|
352
386
|
}
|
|
353
387
|
}
|
|
354
388
|
|
|
355
|
-
// check month overflow
|
|
356
|
-
while ($month > 12) {
|
|
357
|
-
$year += 1
|
|
358
|
-
$month -= 12
|
|
359
|
-
}
|
|
360
|
-
while ($month < 1) {
|
|
361
|
-
$year -= 1
|
|
362
|
-
$month += 12
|
|
363
|
-
}
|
|
364
|
-
|
|
365
389
|
if (mutate) {
|
|
366
390
|
this.$year = $year
|
|
367
391
|
this.$month = $month
|
|
@@ -458,7 +482,7 @@ export class LocalDate {
|
|
|
458
482
|
return Math.floor(this.toDate().valueOf() / 1000)
|
|
459
483
|
}
|
|
460
484
|
|
|
461
|
-
unixMillis():
|
|
485
|
+
unixMillis(): UnixTimestampMillisNumber {
|
|
462
486
|
return this.toDate().valueOf()
|
|
463
487
|
}
|
|
464
488
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { _assert } from '../error/assert'
|
|
2
2
|
import { _ms } from '../time/time.util'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
IsoDateString,
|
|
5
|
+
IsoDateTimeString,
|
|
6
|
+
UnixTimestampMillisNumber,
|
|
7
|
+
UnixTimestampNumber,
|
|
8
|
+
} from '../types'
|
|
4
9
|
import { Inclusiveness, LocalDate } from './localDate'
|
|
5
10
|
|
|
6
11
|
export type LocalTimeUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second'
|
|
@@ -56,6 +61,13 @@ export class LocalTime {
|
|
|
56
61
|
return t
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Create LocalTime from unixTimestamp in milliseconds (not in seconds).
|
|
66
|
+
*/
|
|
67
|
+
static ofMillis(millis: UnixTimestampMillisNumber): LocalTime {
|
|
68
|
+
return LocalTime.of(new Date(millis))
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
/**
|
|
60
72
|
* Returns null if invalid
|
|
61
73
|
*/
|
|
@@ -229,15 +241,15 @@ export class LocalTime {
|
|
|
229
241
|
setComponents(c: Partial<LocalTimeComponents>, mutate = false): LocalTime {
|
|
230
242
|
const d = mutate ? this.$date : new Date(this.$date)
|
|
231
243
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
d.setDate(c.day)
|
|
244
|
+
// Year, month and day set all-at-once, to avoid 30/31 (and 28/29) mishap
|
|
245
|
+
if (c.day || c.month !== undefined || c.year !== undefined) {
|
|
246
|
+
d.setFullYear(
|
|
247
|
+
c.year ?? d.getFullYear(),
|
|
248
|
+
c.month ? c.month - 1 : d.getMonth(),
|
|
249
|
+
c.day || d.getDate(),
|
|
250
|
+
)
|
|
240
251
|
}
|
|
252
|
+
|
|
241
253
|
if (c.hour !== undefined) {
|
|
242
254
|
d.setHours(c.hour)
|
|
243
255
|
}
|
|
@@ -256,6 +268,12 @@ export class LocalTime {
|
|
|
256
268
|
num *= 7
|
|
257
269
|
unit = 'day'
|
|
258
270
|
}
|
|
271
|
+
|
|
272
|
+
if (unit === 'year' || unit === 'month') {
|
|
273
|
+
const d = addMonths(this.$date, unit === 'month' ? num : num * 12, mutate)
|
|
274
|
+
return mutate ? this : LocalTime.of(d)
|
|
275
|
+
}
|
|
276
|
+
|
|
259
277
|
return this.set(unit, this.get(unit) + num, mutate)
|
|
260
278
|
}
|
|
261
279
|
|
|
@@ -273,37 +291,13 @@ export class LocalTime {
|
|
|
273
291
|
const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
|
|
274
292
|
if (!secDiff) return 0
|
|
275
293
|
|
|
276
|
-
if (unit === 'year' || unit === 'month') {
|
|
277
|
-
const sign = secDiff > 0 ? 1 : -1
|
|
278
|
-
|
|
279
|
-
// Put items in descending order: "big minus small"
|
|
280
|
-
const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date]
|
|
281
|
-
|
|
282
|
-
if (unit === 'year') {
|
|
283
|
-
let years = big.getFullYear() - small.getFullYear()
|
|
284
|
-
const big2 = new Date(big)
|
|
285
|
-
const small2 = new Date(small)
|
|
286
|
-
big2.setFullYear(1584)
|
|
287
|
-
small2.setFullYear(1584)
|
|
288
|
-
if (big2 < small2) years--
|
|
289
|
-
return years * sign || 0
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (unit === 'month') {
|
|
293
|
-
let months =
|
|
294
|
-
(big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth()
|
|
295
|
-
const big2 = new Date(big)
|
|
296
|
-
const small2 = new Date(small)
|
|
297
|
-
big2.setFullYear(1584, 0)
|
|
298
|
-
small2.setFullYear(1584, 0)
|
|
299
|
-
if (big2 < small2) months--
|
|
300
|
-
return months * sign || 0
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
294
|
let r
|
|
305
295
|
|
|
306
|
-
if (unit === '
|
|
296
|
+
if (unit === 'year') {
|
|
297
|
+
r = differenceInMonths(this.getDate(), date2) / 12
|
|
298
|
+
} else if (unit === 'month') {
|
|
299
|
+
r = differenceInMonths(this.getDate(), date2)
|
|
300
|
+
} else if (unit === 'day') {
|
|
307
301
|
r = secDiff / SECONDS_IN_DAY
|
|
308
302
|
} else if (unit === 'week') {
|
|
309
303
|
r = secDiff / (7 * 24 * 60 * 60)
|
|
@@ -489,7 +483,7 @@ export class LocalTime {
|
|
|
489
483
|
return Math.floor(this.$date.valueOf() / 1000)
|
|
490
484
|
}
|
|
491
485
|
|
|
492
|
-
unixMillis():
|
|
486
|
+
unixMillis(): UnixTimestampMillisNumber {
|
|
493
487
|
return this.$date.valueOf()
|
|
494
488
|
}
|
|
495
489
|
|
|
@@ -587,7 +581,7 @@ export class LocalTime {
|
|
|
587
581
|
}
|
|
588
582
|
|
|
589
583
|
toString(): string {
|
|
590
|
-
return
|
|
584
|
+
return this.toISODateTime()
|
|
591
585
|
}
|
|
592
586
|
|
|
593
587
|
toJSON(): UnixTimestampNumber {
|
|
@@ -651,32 +645,6 @@ function getWeekYear(date: Date): number {
|
|
|
651
645
|
}
|
|
652
646
|
}
|
|
653
647
|
|
|
654
|
-
// function setWeekYear(
|
|
655
|
-
// date: Date,
|
|
656
|
-
// year: number,
|
|
657
|
-
// ): Date {
|
|
658
|
-
// const diff = differenceInCalendarDays(date, startOfWeekYear(date))
|
|
659
|
-
// const fourthOfJanuary = new Date(0)
|
|
660
|
-
// fourthOfJanuary.setFullYear(year, 0, 4)
|
|
661
|
-
// fourthOfJanuary.setHours(0, 0, 0, 0)
|
|
662
|
-
// date = startOfWeekYear(fourthOfJanuary)
|
|
663
|
-
// date.setDate(date.getDate() + diff)
|
|
664
|
-
// return date
|
|
665
|
-
// }
|
|
666
|
-
|
|
667
|
-
// function differenceInCalendarDays(
|
|
668
|
-
// dateLeft: Date,
|
|
669
|
-
// dateRight: Date,
|
|
670
|
-
// ): number {
|
|
671
|
-
// return Math.round((startOfDay(dateLeft).getTime() - startOfDay(dateRight).getTime()) / MILLISECONDS_IN_DAY)
|
|
672
|
-
// }
|
|
673
|
-
|
|
674
|
-
// function startOfDay(date: Date, mutate = false): Date {
|
|
675
|
-
// const d = mutate ? date : new Date(date)
|
|
676
|
-
// d.setHours(0, 0, 0, 0)
|
|
677
|
-
// return d
|
|
678
|
-
// }
|
|
679
|
-
|
|
680
648
|
// based on: https://github.com/date-fns/date-fns/blob/fd6bb1a0bab143f2da068c05a9c562b9bee1357d/src/startOfWeek/index.ts
|
|
681
649
|
function startOfWeek(date: Date, mutate = false): Date {
|
|
682
650
|
const d = mutate ? date : new Date(date)
|
|
@@ -699,3 +667,41 @@ function endOfWeek(date: Date, mutate = false): Date {
|
|
|
699
667
|
d.setDate(d.getDate() + diff)
|
|
700
668
|
return d
|
|
701
669
|
}
|
|
670
|
+
|
|
671
|
+
function addMonths(d: Date, num: number, mutate = false): Date {
|
|
672
|
+
if (!mutate) d = new Date(d)
|
|
673
|
+
|
|
674
|
+
let day = d.getDate()
|
|
675
|
+
let month = d.getMonth() + 1 + num
|
|
676
|
+
|
|
677
|
+
if (day < 29) {
|
|
678
|
+
d.setMonth(month - 1)
|
|
679
|
+
return d
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
let year = d.getFullYear()
|
|
683
|
+
|
|
684
|
+
while (month > 12) {
|
|
685
|
+
year++
|
|
686
|
+
month -= 12
|
|
687
|
+
}
|
|
688
|
+
while (month < 1) {
|
|
689
|
+
year--
|
|
690
|
+
month += 12
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const monthLen = LocalDate.getMonthLength(year, month)
|
|
694
|
+
if (day > monthLen) day = monthLen
|
|
695
|
+
|
|
696
|
+
d.setFullYear(year, month - 1, day)
|
|
697
|
+
return d
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function differenceInMonths(a: Date, b: Date): number {
|
|
701
|
+
if (a.getDate() < b.getDate()) return -differenceInMonths(b, a)
|
|
702
|
+
const wholeMonthDiff = (b.getFullYear() - a.getFullYear()) * 12 + (b.getMonth() - a.getMonth())
|
|
703
|
+
const anchor = addMonths(a, wholeMonthDiff).getTime()
|
|
704
|
+
const sign = b.getTime() - anchor >= 0 ? 1 : -1
|
|
705
|
+
const anchor2 = addMonths(a, wholeMonthDiff + sign).getTime()
|
|
706
|
+
return -(wholeMonthDiff + ((b.getTime() - anchor) / (anchor2 - anchor)) * sign)
|
|
707
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -120,6 +120,7 @@ import {
|
|
|
120
120
|
SavedDBEntity,
|
|
121
121
|
StringMap,
|
|
122
122
|
UnixTimestampNumber,
|
|
123
|
+
UnixTimestampMillisNumber,
|
|
123
124
|
UnixTimestamp,
|
|
124
125
|
Integer,
|
|
125
126
|
ValueOf,
|
|
@@ -243,6 +244,7 @@ export type {
|
|
|
243
244
|
ConditionalExcept,
|
|
244
245
|
Class,
|
|
245
246
|
UnixTimestampNumber,
|
|
247
|
+
UnixTimestampMillisNumber,
|
|
246
248
|
UnixTimestamp,
|
|
247
249
|
Integer,
|
|
248
250
|
BaseDBEntity,
|
package/src/types.ts
CHANGED
|
@@ -213,6 +213,13 @@ export type IsoDateTimeString = string
|
|
|
213
213
|
*/
|
|
214
214
|
export type UnixTimestampNumber = number
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Interface explicitly states that the value is a "Unix timestamp in **milleseconds**" (not seconds)
|
|
218
|
+
*
|
|
219
|
+
* @example 1628945450000
|
|
220
|
+
*/
|
|
221
|
+
export type UnixTimestampMillisNumber = number
|
|
222
|
+
|
|
216
223
|
/**
|
|
217
224
|
* @deprecated use UnixTimestampNumber
|
|
218
225
|
*/
|