@naturalcycles/js-lib 14.243.0 → 14.244.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/dateInterval.js +1 -1
- package/dist/datetime/localDate.d.ts +31 -26
- package/dist/datetime/localDate.js +180 -154
- package/dist/datetime/localTime.d.ts +43 -41
- package/dist/datetime/localTime.js +178 -118
- package/dist/datetime/timeInterval.js +2 -2
- package/dist/env/buildInfo.js +2 -2
- package/dist-esm/datetime/dateInterval.js +1 -1
- package/dist-esm/datetime/localDate.js +180 -154
- package/dist-esm/datetime/localTime.js +178 -118
- package/dist-esm/datetime/timeInterval.js +2 -2
- package/dist-esm/env/buildInfo.js +2 -2
- package/package.json +2 -1
- package/src/datetime/dateInterval.ts +1 -1
- package/src/datetime/localDate.ts +188 -168
- package/src/datetime/localTime.ts +191 -149
- package/src/datetime/timeInterval.ts +2 -5
- package/src/env/buildInfo.ts +2 -2
|
@@ -7,69 +7,70 @@ const is_util_1 = require("../is.util");
|
|
|
7
7
|
const iterable2_1 = require("../iter/iterable2");
|
|
8
8
|
const localTime_1 = require("./localTime");
|
|
9
9
|
const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
10
|
-
|
|
10
|
+
// Regex is open-ended (no $ at the end) to support e.g Date+Time string to be parsed (time part will be dropped)
|
|
11
|
+
const DATE_REGEX = /^(\d\d\d\d)-(\d\d)-(\d\d)/;
|
|
11
12
|
/**
|
|
12
13
|
* LocalDate represents a date without time.
|
|
13
14
|
* It is timezone-independent.
|
|
14
15
|
*/
|
|
15
16
|
class LocalDate {
|
|
16
|
-
constructor(
|
|
17
|
-
this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
17
|
+
constructor(year, month, day) {
|
|
18
|
+
this.year = year;
|
|
19
|
+
this.month = month;
|
|
20
|
+
this.day = day;
|
|
20
21
|
}
|
|
21
22
|
get(unit) {
|
|
22
|
-
return unit === 'year' ? this
|
|
23
|
+
return unit === 'year' ? this.year : unit === 'month' ? this.month : this.day;
|
|
23
24
|
}
|
|
24
25
|
set(unit, v, mutate = false) {
|
|
25
26
|
const t = mutate ? this : this.clone();
|
|
26
27
|
if (unit === 'year') {
|
|
27
|
-
t
|
|
28
|
+
t.year = v;
|
|
28
29
|
}
|
|
29
30
|
else if (unit === 'month') {
|
|
30
|
-
t
|
|
31
|
+
t.month = v;
|
|
31
32
|
}
|
|
32
33
|
else {
|
|
33
|
-
t
|
|
34
|
+
t.day = v;
|
|
34
35
|
}
|
|
35
36
|
return t;
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
-
return
|
|
38
|
+
setYear(v) {
|
|
39
|
+
return this.set('year', v);
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
return
|
|
41
|
+
setMonth(v) {
|
|
42
|
+
return this.set('month', v);
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
return
|
|
44
|
+
setDay(v) {
|
|
45
|
+
return this.set('day', v);
|
|
45
46
|
}
|
|
46
|
-
dayOfWeek() {
|
|
47
|
+
get dayOfWeek() {
|
|
47
48
|
return (this.toDate().getDay() || 7);
|
|
48
49
|
}
|
|
49
50
|
isSame(d) {
|
|
50
|
-
d = exports.localDate.
|
|
51
|
-
return this
|
|
51
|
+
d = exports.localDate.from(d);
|
|
52
|
+
return this.day === d.day && this.month === d.month && this.year === d.year;
|
|
52
53
|
}
|
|
53
54
|
isBefore(d, inclusive = false) {
|
|
54
|
-
const r = this.
|
|
55
|
+
const r = this.compare(d);
|
|
55
56
|
return r === -1 || (r === 0 && inclusive);
|
|
56
57
|
}
|
|
57
58
|
isSameOrBefore(d) {
|
|
58
|
-
return this.
|
|
59
|
+
return this.compare(d) <= 0;
|
|
59
60
|
}
|
|
60
61
|
isAfter(d, inclusive = false) {
|
|
61
|
-
const r = this.
|
|
62
|
+
const r = this.compare(d);
|
|
62
63
|
return r === 1 || (r === 0 && inclusive);
|
|
63
64
|
}
|
|
64
65
|
isSameOrAfter(d) {
|
|
65
|
-
return this.
|
|
66
|
+
return this.compare(d) >= 0;
|
|
66
67
|
}
|
|
67
68
|
isBetween(min, max, incl = '[)') {
|
|
68
|
-
let r = this.
|
|
69
|
+
let r = this.compare(min);
|
|
69
70
|
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
70
71
|
if (r < 0 || (r === 0 && incl[0] === '('))
|
|
71
72
|
return false;
|
|
72
|
-
r = this.
|
|
73
|
+
r = this.compare(max);
|
|
73
74
|
if (r > 0 || (r === 0 && incl[1] === ')'))
|
|
74
75
|
return false;
|
|
75
76
|
return true;
|
|
@@ -84,13 +85,13 @@ class LocalDate {
|
|
|
84
85
|
* Third argument allows to override "today".
|
|
85
86
|
*/
|
|
86
87
|
isOlderThan(n, unit, today) {
|
|
87
|
-
return this.isBefore(exports.localDate.
|
|
88
|
+
return this.isBefore(exports.localDate.from(today || new Date()).plus(-n, unit));
|
|
88
89
|
}
|
|
89
90
|
/**
|
|
90
91
|
* Checks if this localDate is same or older (<=) than "today" by X units.
|
|
91
92
|
*/
|
|
92
93
|
isSameOrOlderThan(n, unit, today) {
|
|
93
|
-
return this.isSameOrBefore(exports.localDate.
|
|
94
|
+
return this.isSameOrBefore(exports.localDate.from(today || new Date()).plus(-n, unit));
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
97
|
* Checks if this localDate is younger (>) than "today" by X units.
|
|
@@ -102,13 +103,13 @@ class LocalDate {
|
|
|
102
103
|
* Third argument allows to override "today".
|
|
103
104
|
*/
|
|
104
105
|
isYoungerThan(n, unit, today) {
|
|
105
|
-
return this.isAfter(exports.localDate.
|
|
106
|
+
return this.isAfter(exports.localDate.from(today || new Date()).plus(-n, unit));
|
|
106
107
|
}
|
|
107
108
|
/**
|
|
108
109
|
* Checks if this localDate is same or younger (>=) than "today" by X units.
|
|
109
110
|
*/
|
|
110
111
|
isSameOrYoungerThan(n, unit, today) {
|
|
111
|
-
return this.isSameOrAfter(exports.localDate.
|
|
112
|
+
return this.isSameOrAfter(exports.localDate.from(today || new Date()).plus(-n, unit));
|
|
112
113
|
}
|
|
113
114
|
getAgeInYears(today) {
|
|
114
115
|
return this.getAgeIn('year', today);
|
|
@@ -120,26 +121,26 @@ class LocalDate {
|
|
|
120
121
|
return this.getAgeIn('day', today);
|
|
121
122
|
}
|
|
122
123
|
getAgeIn(unit, today) {
|
|
123
|
-
return exports.localDate.
|
|
124
|
+
return exports.localDate.from(today || new Date()).diff(this, unit);
|
|
124
125
|
}
|
|
125
126
|
/**
|
|
126
127
|
* Returns 1 if this > d
|
|
127
128
|
* returns 0 if they are equal
|
|
128
129
|
* returns -1 if this < d
|
|
129
130
|
*/
|
|
130
|
-
|
|
131
|
-
d = exports.localDate.
|
|
132
|
-
if (this
|
|
131
|
+
compare(d) {
|
|
132
|
+
d = exports.localDate.from(d);
|
|
133
|
+
if (this.year < d.year)
|
|
133
134
|
return -1;
|
|
134
|
-
if (this
|
|
135
|
+
if (this.year > d.year)
|
|
135
136
|
return 1;
|
|
136
|
-
if (this
|
|
137
|
+
if (this.month < d.month)
|
|
137
138
|
return -1;
|
|
138
|
-
if (this
|
|
139
|
+
if (this.month > d.month)
|
|
139
140
|
return 1;
|
|
140
|
-
if (this
|
|
141
|
+
if (this.day < d.day)
|
|
141
142
|
return -1;
|
|
142
|
-
if (this
|
|
143
|
+
if (this.day > d.day)
|
|
143
144
|
return 1;
|
|
144
145
|
return 0;
|
|
145
146
|
}
|
|
@@ -155,48 +156,48 @@ class LocalDate {
|
|
|
155
156
|
* a.diff(b) means "a minus b"
|
|
156
157
|
*/
|
|
157
158
|
diff(d, unit) {
|
|
158
|
-
d = exports.localDate.
|
|
159
|
-
const sign = this.
|
|
159
|
+
d = exports.localDate.from(d);
|
|
160
|
+
const sign = this.compare(d);
|
|
160
161
|
if (!sign)
|
|
161
162
|
return 0;
|
|
162
163
|
// Put items in descending order: "big minus small"
|
|
163
164
|
const [big, small] = sign === 1 ? [this, d] : [d, this];
|
|
164
165
|
if (unit === 'year') {
|
|
165
|
-
let years = big
|
|
166
|
-
if (big
|
|
167
|
-
(big
|
|
168
|
-
big
|
|
169
|
-
!(big
|
|
170
|
-
small
|
|
166
|
+
let years = big.year - small.year;
|
|
167
|
+
if (big.month < small.month ||
|
|
168
|
+
(big.month === small.month &&
|
|
169
|
+
big.day < small.day &&
|
|
170
|
+
!(big.day === exports.localDate.getMonthLength(big.year, big.month) &&
|
|
171
|
+
small.day === exports.localDate.getMonthLength(small.year, small.month)))) {
|
|
171
172
|
years--;
|
|
172
173
|
}
|
|
173
174
|
return years * sign || 0;
|
|
174
175
|
}
|
|
175
176
|
if (unit === 'month') {
|
|
176
|
-
let months = (big
|
|
177
|
-
if (big
|
|
178
|
-
const bigMonthLen = exports.localDate.getMonthLength(big
|
|
179
|
-
if (big
|
|
177
|
+
let months = (big.year - small.year) * 12 + (big.month - small.month);
|
|
178
|
+
if (big.day < small.day) {
|
|
179
|
+
const bigMonthLen = exports.localDate.getMonthLength(big.year, big.month);
|
|
180
|
+
if (big.day !== bigMonthLen || small.day < bigMonthLen) {
|
|
180
181
|
months--;
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
return months * sign || 0;
|
|
184
185
|
}
|
|
185
186
|
// unit is 'day' or 'week'
|
|
186
|
-
let days = big
|
|
187
|
+
let days = big.day - small.day;
|
|
187
188
|
// If small date is after 1st of March - next year's "leapness" should be used
|
|
188
|
-
const offsetYear = small
|
|
189
|
-
for (let year = small
|
|
189
|
+
const offsetYear = small.month >= 3 ? 1 : 0;
|
|
190
|
+
for (let year = small.year; year < big.year; year++) {
|
|
190
191
|
days += exports.localDate.getYearLength(year + offsetYear);
|
|
191
192
|
}
|
|
192
|
-
if (small
|
|
193
|
-
for (let month = small
|
|
194
|
-
days += exports.localDate.getMonthLength(big
|
|
193
|
+
if (small.month < big.month) {
|
|
194
|
+
for (let month = small.month; month < big.month; month++) {
|
|
195
|
+
days += exports.localDate.getMonthLength(big.year, month);
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
|
-
else if (big
|
|
198
|
-
for (let month = big
|
|
199
|
-
days -= exports.localDate.getMonthLength(big
|
|
198
|
+
else if (big.month < small.month) {
|
|
199
|
+
for (let month = big.month; month < small.month; month++) {
|
|
200
|
+
days -= exports.localDate.getMonthLength(big.year, month);
|
|
200
201
|
}
|
|
201
202
|
}
|
|
202
203
|
if (unit === 'week') {
|
|
@@ -229,68 +230,68 @@ class LocalDate {
|
|
|
229
230
|
return this.plus(-num, 'year');
|
|
230
231
|
}
|
|
231
232
|
plus(num, unit, mutate = false) {
|
|
232
|
-
let {
|
|
233
|
+
let { day, month, year } = this;
|
|
233
234
|
if (unit === 'week') {
|
|
234
235
|
num *= 7;
|
|
235
236
|
unit = 'day';
|
|
236
237
|
}
|
|
237
238
|
if (unit === 'day') {
|
|
238
|
-
|
|
239
|
+
day += num;
|
|
239
240
|
}
|
|
240
241
|
else if (unit === 'month') {
|
|
241
|
-
|
|
242
|
+
month += num;
|
|
242
243
|
}
|
|
243
244
|
else if (unit === 'year') {
|
|
244
|
-
|
|
245
|
+
year += num;
|
|
245
246
|
}
|
|
246
247
|
// check month overflow
|
|
247
|
-
while (
|
|
248
|
-
|
|
249
|
-
|
|
248
|
+
while (month > 12) {
|
|
249
|
+
year += 1;
|
|
250
|
+
month -= 12;
|
|
250
251
|
}
|
|
251
|
-
while (
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
while (month < 1) {
|
|
253
|
+
year -= 1;
|
|
254
|
+
month += 12;
|
|
254
255
|
}
|
|
255
256
|
// check day overflow
|
|
256
257
|
// Applies not only for 'day' unit, but also e.g 2022-05-31 plus 1 month should be 2022-06-30 (not 31!)
|
|
257
|
-
if (
|
|
258
|
-
while (
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
if (day < 1) {
|
|
259
|
+
while (day < 1) {
|
|
260
|
+
month -= 1;
|
|
261
|
+
if (month < 1) {
|
|
262
|
+
year -= 1;
|
|
263
|
+
month += 12;
|
|
263
264
|
}
|
|
264
|
-
|
|
265
|
+
day += exports.localDate.getMonthLength(year, month);
|
|
265
266
|
}
|
|
266
267
|
}
|
|
267
268
|
else {
|
|
268
|
-
let monLen = exports.localDate.getMonthLength(
|
|
269
|
+
let monLen = exports.localDate.getMonthLength(year, month);
|
|
269
270
|
if (unit !== 'day') {
|
|
270
|
-
if (
|
|
271
|
+
if (day > monLen) {
|
|
271
272
|
// Case of 2022-05-31 plus 1 month should be 2022-06-30, not 31
|
|
272
|
-
|
|
273
|
+
day = monLen;
|
|
273
274
|
}
|
|
274
275
|
}
|
|
275
276
|
else {
|
|
276
|
-
while (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
while (day > monLen) {
|
|
278
|
+
day -= monLen;
|
|
279
|
+
month += 1;
|
|
280
|
+
if (month > 12) {
|
|
281
|
+
year += 1;
|
|
282
|
+
month -= 12;
|
|
282
283
|
}
|
|
283
|
-
monLen = exports.localDate.getMonthLength(
|
|
284
|
+
monLen = exports.localDate.getMonthLength(year, month);
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
287
|
}
|
|
287
288
|
if (mutate) {
|
|
288
|
-
this
|
|
289
|
-
this
|
|
290
|
-
this
|
|
289
|
+
this.year = year;
|
|
290
|
+
this.month = month;
|
|
291
|
+
this.day = day;
|
|
291
292
|
return this;
|
|
292
293
|
}
|
|
293
|
-
return new LocalDate(
|
|
294
|
+
return new LocalDate(year, month, day);
|
|
294
295
|
}
|
|
295
296
|
minus(num, unit, mutate = false) {
|
|
296
297
|
return this.plus(-num, unit, mutate);
|
|
@@ -299,27 +300,27 @@ class LocalDate {
|
|
|
299
300
|
if (unit === 'day')
|
|
300
301
|
return this;
|
|
301
302
|
if (unit === 'month')
|
|
302
|
-
return new LocalDate(this
|
|
303
|
+
return new LocalDate(this.year, this.month, 1);
|
|
303
304
|
// year
|
|
304
|
-
return new LocalDate(this
|
|
305
|
+
return new LocalDate(this.year, 1, 1);
|
|
305
306
|
}
|
|
306
307
|
endOf(unit) {
|
|
307
308
|
if (unit === 'day')
|
|
308
309
|
return this;
|
|
309
310
|
if (unit === 'month')
|
|
310
|
-
return new LocalDate(this
|
|
311
|
+
return new LocalDate(this.year, this.month, exports.localDate.getMonthLength(this.year, this.month));
|
|
311
312
|
// year
|
|
312
|
-
return new LocalDate(this
|
|
313
|
+
return new LocalDate(this.year, 12, 31);
|
|
313
314
|
}
|
|
314
315
|
/**
|
|
315
316
|
* Returns how many days are in the current month.
|
|
316
317
|
* E.g 31 for January.
|
|
317
318
|
*/
|
|
318
|
-
daysInMonth() {
|
|
319
|
-
return exports.localDate.getMonthLength(this
|
|
319
|
+
get daysInMonth() {
|
|
320
|
+
return exports.localDate.getMonthLength(this.year, this.month);
|
|
320
321
|
}
|
|
321
322
|
clone() {
|
|
322
|
-
return new LocalDate(this
|
|
323
|
+
return new LocalDate(this.year, this.month, this.day);
|
|
323
324
|
}
|
|
324
325
|
/**
|
|
325
326
|
* Converts LocalDate into instance of Date.
|
|
@@ -328,7 +329,7 @@ class LocalDate {
|
|
|
328
329
|
* Timezone will match local timezone.
|
|
329
330
|
*/
|
|
330
331
|
toDate() {
|
|
331
|
-
return new Date(this
|
|
332
|
+
return new Date(this.year, this.month - 1, this.day);
|
|
332
333
|
}
|
|
333
334
|
/**
|
|
334
335
|
* Converts LocalDate to Date in UTC timezone.
|
|
@@ -339,9 +340,9 @@ class LocalDate {
|
|
|
339
340
|
}
|
|
340
341
|
toDateObject() {
|
|
341
342
|
return {
|
|
342
|
-
year: this
|
|
343
|
-
month: this
|
|
344
|
-
day: this
|
|
343
|
+
year: this.year,
|
|
344
|
+
month: this.month,
|
|
345
|
+
day: this.day,
|
|
345
346
|
};
|
|
346
347
|
}
|
|
347
348
|
/**
|
|
@@ -349,16 +350,16 @@ class LocalDate {
|
|
|
349
350
|
* LocalTime's Date will be in local timezone.
|
|
350
351
|
*/
|
|
351
352
|
toLocalTime() {
|
|
352
|
-
return localTime_1.localTime.
|
|
353
|
+
return localTime_1.localTime.fromDate(this.toDate());
|
|
353
354
|
}
|
|
354
355
|
/**
|
|
355
356
|
* Returns e.g: `1984-06-21`
|
|
356
357
|
*/
|
|
357
358
|
toISODate() {
|
|
358
359
|
return [
|
|
359
|
-
String(this
|
|
360
|
-
String(this
|
|
361
|
-
String(this
|
|
360
|
+
String(this.year).padStart(4, '0'),
|
|
361
|
+
String(this.month).padStart(2, '0'),
|
|
362
|
+
String(this.day).padStart(2, '0'),
|
|
362
363
|
].join('-');
|
|
363
364
|
}
|
|
364
365
|
/**
|
|
@@ -383,9 +384,9 @@ class LocalDate {
|
|
|
383
384
|
*/
|
|
384
385
|
toStringCompact() {
|
|
385
386
|
return [
|
|
386
|
-
String(this
|
|
387
|
-
String(this
|
|
388
|
-
String(this
|
|
387
|
+
String(this.year).padStart(4, '0'),
|
|
388
|
+
String(this.month).padStart(2, '0'),
|
|
389
|
+
String(this.day).padStart(2, '0'),
|
|
389
390
|
].join('');
|
|
390
391
|
}
|
|
391
392
|
/**
|
|
@@ -397,13 +398,13 @@ class LocalDate {
|
|
|
397
398
|
/**
|
|
398
399
|
* Returns unix timestamp of 00:00:00 of that date (in UTC, because unix timestamp always reflects UTC).
|
|
399
400
|
*/
|
|
400
|
-
unix() {
|
|
401
|
+
get unix() {
|
|
401
402
|
return Math.floor(this.toDate().valueOf() / 1000);
|
|
402
403
|
}
|
|
403
404
|
/**
|
|
404
405
|
* Same as .unix(), but in milliseconds.
|
|
405
406
|
*/
|
|
406
|
-
unixMillis() {
|
|
407
|
+
get unixMillis() {
|
|
407
408
|
return this.toDate().valueOf();
|
|
408
409
|
}
|
|
409
410
|
toJSON() {
|
|
@@ -418,12 +419,6 @@ class LocalDate {
|
|
|
418
419
|
}
|
|
419
420
|
exports.LocalDate = LocalDate;
|
|
420
421
|
class LocalDateFactory {
|
|
421
|
-
/**
|
|
422
|
-
* Create LocalDate from year, month and day components.
|
|
423
|
-
*/
|
|
424
|
-
create(year, month, day) {
|
|
425
|
-
return new LocalDate(year, month, day);
|
|
426
|
-
}
|
|
427
422
|
/**
|
|
428
423
|
* Create LocalDate from LocalDateInput.
|
|
429
424
|
* Input can already be a LocalDate - it is returned as-is in that case.
|
|
@@ -433,18 +428,16 @@ class LocalDateFactory {
|
|
|
433
428
|
*
|
|
434
429
|
* Will throw if it fails to parse/construct LocalDate.
|
|
435
430
|
*/
|
|
436
|
-
|
|
437
|
-
const
|
|
438
|
-
(
|
|
439
|
-
|
|
440
|
-
});
|
|
441
|
-
return t;
|
|
431
|
+
from(input) {
|
|
432
|
+
const ld = this.fromOrNull(input);
|
|
433
|
+
this.assertNotNull(ld, input);
|
|
434
|
+
return ld;
|
|
442
435
|
}
|
|
443
436
|
/**
|
|
444
437
|
* Tries to construct LocalDate from LocalDateInput, returns null otherwise.
|
|
445
438
|
* Does not throw (returns null instead).
|
|
446
439
|
*/
|
|
447
|
-
|
|
440
|
+
fromOrNull(d) {
|
|
448
441
|
if (!d)
|
|
449
442
|
return null;
|
|
450
443
|
if (d instanceof LocalDate)
|
|
@@ -452,12 +445,25 @@ class LocalDateFactory {
|
|
|
452
445
|
if (d instanceof Date) {
|
|
453
446
|
return this.fromDate(d);
|
|
454
447
|
}
|
|
455
|
-
|
|
456
|
-
|
|
448
|
+
if (typeof d === 'string') {
|
|
449
|
+
return this.fromStringOrNull(d);
|
|
450
|
+
}
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
fromString(s) {
|
|
454
|
+
const ld = this.fromStringOrNull(s);
|
|
455
|
+
this.assertNotNull(ld, s);
|
|
456
|
+
return ld;
|
|
457
|
+
}
|
|
458
|
+
fromStringOrNull(s) {
|
|
459
|
+
if (!s)
|
|
460
|
+
return null;
|
|
461
|
+
const m = DATE_REGEX.exec(s);
|
|
462
|
+
if (!m)
|
|
457
463
|
return null;
|
|
458
|
-
const year = Number(
|
|
459
|
-
const month = Number(
|
|
460
|
-
const day = Number(
|
|
464
|
+
const year = Number(m[1]);
|
|
465
|
+
const month = Number(m[2]);
|
|
466
|
+
const day = Number(m[3]);
|
|
461
467
|
if (!year ||
|
|
462
468
|
!month ||
|
|
463
469
|
month < 1 ||
|
|
@@ -473,22 +479,11 @@ class LocalDateFactory {
|
|
|
473
479
|
* Parses "compact iso8601 format", e.g `19840621` into LocalDate.
|
|
474
480
|
* Throws if it fails to do so.
|
|
475
481
|
*/
|
|
476
|
-
|
|
477
|
-
const [year, month, day] = [
|
|
478
|
-
(0, assert_1._assert)(day && month && year, `Cannot parse "${
|
|
482
|
+
fromCompactString(s) {
|
|
483
|
+
const [year, month, day] = [s.slice(0, 4), s.slice(4, 6), s.slice(6, 8)].map(Number);
|
|
484
|
+
(0, assert_1._assert)(day && month && year, `Cannot parse compact string "${s}" into LocalDate`);
|
|
479
485
|
return new LocalDate(year, month, day);
|
|
480
486
|
}
|
|
481
|
-
getYearLength(year) {
|
|
482
|
-
return this.isLeapYear(year) ? 366 : 365;
|
|
483
|
-
}
|
|
484
|
-
getMonthLength(year, month) {
|
|
485
|
-
if (month === 2)
|
|
486
|
-
return this.isLeapYear(year) ? 29 : 28;
|
|
487
|
-
return MDAYS[month];
|
|
488
|
-
}
|
|
489
|
-
isLeapYear(year) {
|
|
490
|
-
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
491
|
-
}
|
|
492
487
|
/**
|
|
493
488
|
* Constructs LocalDate from Date.
|
|
494
489
|
* Takes Date as-is, in its timezone - local or UTC.
|
|
@@ -503,11 +498,43 @@ class LocalDateFactory {
|
|
|
503
498
|
fromDateInUTC(d) {
|
|
504
499
|
return new LocalDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
|
|
505
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* Create LocalDate from year, month and day components.
|
|
503
|
+
*/
|
|
504
|
+
fromComponents(year, month, day) {
|
|
505
|
+
return new LocalDate(year, month, day);
|
|
506
|
+
}
|
|
507
|
+
fromDateObject(o) {
|
|
508
|
+
const { year, month, day } = o;
|
|
509
|
+
return new LocalDate(year, month, day);
|
|
510
|
+
}
|
|
511
|
+
assertNotNull(ld, input) {
|
|
512
|
+
(0, assert_1._assert)(ld !== null, `Cannot parse "${input}" into LocalDate`, {
|
|
513
|
+
input,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
getYearLength(year) {
|
|
517
|
+
return this.isLeapYear(year) ? 366 : 365;
|
|
518
|
+
}
|
|
519
|
+
getMonthLength(year, month) {
|
|
520
|
+
if (month === 2)
|
|
521
|
+
return this.isLeapYear(year) ? 29 : 28;
|
|
522
|
+
return MDAYS[month];
|
|
523
|
+
}
|
|
524
|
+
isLeapYear(year) {
|
|
525
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Returns true if input is valid to create LocalDate.
|
|
529
|
+
*/
|
|
530
|
+
isValid(input) {
|
|
531
|
+
return this.fromOrNull(input) !== null;
|
|
532
|
+
}
|
|
506
533
|
/**
|
|
507
534
|
* Returns true if isoString is a valid iso8601 string like `yyyy-mm-dd`.
|
|
508
535
|
*/
|
|
509
|
-
|
|
510
|
-
return this.
|
|
536
|
+
isValidString(isoString) {
|
|
537
|
+
return this.fromStringOrNull(isoString) !== null;
|
|
511
538
|
}
|
|
512
539
|
/**
|
|
513
540
|
* Creates LocalDate that represents `today` (in local timezone).
|
|
@@ -526,7 +553,7 @@ class LocalDateFactory {
|
|
|
526
553
|
*/
|
|
527
554
|
sort(items, dir = 'asc', mutate = false) {
|
|
528
555
|
const mod = dir === 'desc' ? -1 : 1;
|
|
529
|
-
return (mutate ? items : [...items]).sort((a, b) => a.
|
|
556
|
+
return (mutate ? items : [...items]).sort((a, b) => a.compare(b) * mod);
|
|
530
557
|
}
|
|
531
558
|
/**
|
|
532
559
|
* Returns the earliest (min) LocalDate from the array, or undefined if the array is empty.
|
|
@@ -542,7 +569,7 @@ class LocalDateFactory {
|
|
|
542
569
|
const items2 = items.filter(is_util_1._isTruthy);
|
|
543
570
|
(0, assert_1._assert)(items2.length, 'localDate.min called on empty array');
|
|
544
571
|
return items2
|
|
545
|
-
.map(i => this.
|
|
572
|
+
.map(i => this.from(i))
|
|
546
573
|
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
|
|
547
574
|
}
|
|
548
575
|
/**
|
|
@@ -558,7 +585,9 @@ class LocalDateFactory {
|
|
|
558
585
|
max(items) {
|
|
559
586
|
const items2 = items.filter(is_util_1._isTruthy);
|
|
560
587
|
(0, assert_1._assert)(items2.length, 'localDate.max called on empty array');
|
|
561
|
-
return items2
|
|
588
|
+
return items2
|
|
589
|
+
.map(i => this.from(i))
|
|
590
|
+
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
|
|
562
591
|
}
|
|
563
592
|
/**
|
|
564
593
|
* Returns the range (array) of LocalDates between min and max.
|
|
@@ -576,8 +605,8 @@ class LocalDateFactory {
|
|
|
576
605
|
step *= 7;
|
|
577
606
|
stepUnit = 'day';
|
|
578
607
|
}
|
|
579
|
-
const $min = this.
|
|
580
|
-
const $max = this.
|
|
608
|
+
const $min = this.from(min).startOf(stepUnit);
|
|
609
|
+
const $max = this.from(max).startOf(stepUnit);
|
|
581
610
|
let value = $min;
|
|
582
611
|
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
583
612
|
if (value.isAfter($min, incl[0] === '[')) {
|
|
@@ -604,20 +633,17 @@ class LocalDateFactory {
|
|
|
604
633
|
* Similar to `localDate.orToday`, but that will instead return Today on falsy input.
|
|
605
634
|
*/
|
|
606
635
|
orUndefined(d) {
|
|
607
|
-
return d ? this.
|
|
636
|
+
return d ? this.from(d) : undefined;
|
|
608
637
|
}
|
|
609
638
|
/**
|
|
610
639
|
* Creates a LocalDate from the input, unless it's falsy - then returns localDate.today.
|
|
611
640
|
*/
|
|
612
641
|
orToday(d) {
|
|
613
|
-
return d ? this.
|
|
642
|
+
return d ? this.from(d) : this.today();
|
|
614
643
|
}
|
|
615
644
|
}
|
|
616
645
|
const localDateFactory = new LocalDateFactory();
|
|
617
|
-
|
|
618
|
-
// return localDateFactory.of(d)
|
|
619
|
-
// }, localDateFactory) as LocalDateFn
|
|
620
|
-
exports.localDate = localDateFactory.of.bind(localDateFactory);
|
|
646
|
+
exports.localDate = localDateFactory.from.bind(localDateFactory);
|
|
621
647
|
// The line below is the blackest of black magic I have ever written in 2024.
|
|
622
648
|
// And probably 2023 as well.
|
|
623
649
|
Object.setPrototypeOf(exports.localDate, localDateFactory);
|