atomic-fns 1.1.7 → 1.2.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/README.md +51 -12
- package/dist/collections/BTree.d.ts +11 -10
- package/dist/collections/BTree.js +58 -80
- package/dist/collections/Heap.js +1 -1
- package/dist/collections/LRUCache.d.ts +6 -3
- package/dist/collections/LRUCache.js +24 -11
- package/dist/collections/SortedMap.js +2 -2
- package/dist/collections/SortedTree.d.ts +2 -2
- package/dist/collections/SortedTree.js +3 -2
- package/dist/collections/SplayTree.d.ts +7 -5
- package/dist/collections/SplayTree.js +39 -26
- package/dist/collections/Trie.d.ts +1 -1
- package/dist/collections/Trie.js +26 -26
- package/dist/collections/deque.d.ts +1 -1
- package/dist/collections/deque.js +17 -10
- package/dist/collections/frozenset.js +4 -1
- package/dist/collections/index.d.ts +13 -32
- package/dist/collections/index.js +210 -82
- package/dist/decimal/index.d.ts +5 -2
- package/dist/decimal/index.js +63 -27
- package/dist/functools/index.d.ts +6 -30
- package/dist/functools/index.js +24 -56
- package/dist/globals/index.d.ts +3 -20
- package/dist/globals/index.js +23 -39
- package/dist/i18n/currency.d.ts +3 -0
- package/dist/i18n/currency.js +22 -7
- package/dist/i18n/date/index.d.ts +17 -10
- package/dist/i18n/date/index.js +79 -58
- package/dist/i18n/date/utils.d.ts +4 -5
- package/dist/i18n/date/utils.js +15 -113
- package/dist/i18n/duration.d.ts +11 -10
- package/dist/i18n/duration.js +38 -32
- package/dist/i18n/format.d.ts +5 -2
- package/dist/i18n/format.js +81 -209
- package/dist/i18n/index.d.ts +2 -1
- package/dist/itertools/index.d.ts +9 -13
- package/dist/itertools/index.js +38 -41
- package/dist/math/index.d.ts +10 -27
- package/dist/math/index.js +16 -33
- package/dist/operators/index.d.ts +1 -5
- package/dist/operators/index.js +60 -40
- package/dist/random/index.js +9 -6
- package/dist/string/index.d.ts +1 -1
- package/dist/string/index.js +2 -4
- package/dist/types.d.ts +3 -3
- package/package.json +16 -21
package/dist/i18n/duration.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type DurationUnit = 'year' | 'years' | 'quarter' | 'quarters' | 'month' | 'months' | 'week' | 'weeks' | 'day' | 'days' | 'hour' | 'hours' | 'minute' | 'minutes' | 'second' | 'seconds' | 'millisecond' | 'milliseconds';
|
|
2
2
|
export interface TDuration {
|
|
3
3
|
years?: number;
|
|
4
4
|
months?: number;
|
|
@@ -14,6 +14,7 @@ export declare class Duration {
|
|
|
14
14
|
values: TDuration;
|
|
15
15
|
private matrix;
|
|
16
16
|
constructor(dur?: number | TDuration | Duration, exact?: boolean);
|
|
17
|
+
private withValues;
|
|
17
18
|
/** Get the years. */
|
|
18
19
|
get years(): number;
|
|
19
20
|
/** Get the months. */
|
|
@@ -24,7 +25,7 @@ export declare class Duration {
|
|
|
24
25
|
get days(): number;
|
|
25
26
|
/** Get the hours. */
|
|
26
27
|
get hours(): number;
|
|
27
|
-
/**
|
|
28
|
+
/** Get the minutes. */
|
|
28
29
|
get minutes(): number;
|
|
29
30
|
/** Get the seconds. */
|
|
30
31
|
get seconds(): number;
|
|
@@ -33,9 +34,9 @@ export declare class Duration {
|
|
|
33
34
|
/**
|
|
34
35
|
* Get the value of unit.
|
|
35
36
|
* @param {string} unit - a unit such as 'minute' or 'day'
|
|
36
|
-
* @example Duration
|
|
37
|
-
* @example Duration
|
|
38
|
-
* @example Duration
|
|
37
|
+
* @example new Duration({years: 2, days: 3}).get('years') // 2
|
|
38
|
+
* @example new Duration({years: 2, days: 3}).get('months') // 0
|
|
39
|
+
* @example new Duration({years: 2, days: 3}).get('days') // 3
|
|
39
40
|
* @return {number}
|
|
40
41
|
*/
|
|
41
42
|
get(unit: string): number;
|
|
@@ -85,11 +86,11 @@ export declare class Duration {
|
|
|
85
86
|
/**
|
|
86
87
|
* Returns an ISO 8601-compliant string representation of this Duration.
|
|
87
88
|
* @see https://en.wikipedia.org/wiki/ISO_8601#Durations
|
|
88
|
-
* @example Duration
|
|
89
|
-
* @example Duration
|
|
90
|
-
* @example Duration
|
|
91
|
-
* @example Duration
|
|
92
|
-
* @example Duration
|
|
89
|
+
* @example new Duration({ years: 3, seconds: 45 }).toString() // 'P3YT45S'
|
|
90
|
+
* @example new Duration({ months: 4, seconds: 45 }).toString() // 'P4MT45S'
|
|
91
|
+
* @example new Duration({ months: 5 }).toString() // 'P5M'
|
|
92
|
+
* @example new Duration({ minutes: 5 }).toString() // 'PT5M'
|
|
93
|
+
* @example new Duration({ milliseconds: 6 }).toString() // 'PT0.006S'
|
|
93
94
|
* @return {string}
|
|
94
95
|
*/
|
|
95
96
|
toISOString(): string;
|
package/dist/i18n/duration.js
CHANGED
|
@@ -115,23 +115,26 @@ const orderedUnits = [
|
|
|
115
115
|
];
|
|
116
116
|
const reverseUnits = orderedUnits.slice(0).reverse();
|
|
117
117
|
export class Duration {
|
|
118
|
-
values;
|
|
118
|
+
values = {};
|
|
119
119
|
matrix = casualMatrix;
|
|
120
120
|
constructor(dur = {}, exact = false) {
|
|
121
121
|
if (dur instanceof Duration) {
|
|
122
122
|
this.values = { ...dur.values };
|
|
123
123
|
}
|
|
124
|
-
else if (
|
|
124
|
+
else if (typeof dur === 'number') {
|
|
125
125
|
this.values = { milliseconds: dur };
|
|
126
126
|
}
|
|
127
127
|
else if (isObject(dur)) {
|
|
128
128
|
this.values = normalizeUnits(dur);
|
|
129
129
|
}
|
|
130
|
-
if (exact) {
|
|
130
|
+
if (exact || (dur instanceof Duration && dur.matrix === exactMatrix)) {
|
|
131
131
|
// Set the conversion matrix to use
|
|
132
132
|
this.matrix = exactMatrix;
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
+
withValues(values) {
|
|
136
|
+
return new Duration(values, this.matrix === exactMatrix);
|
|
137
|
+
}
|
|
135
138
|
/** Get the years. */
|
|
136
139
|
get years() {
|
|
137
140
|
return this.values.years || 0;
|
|
@@ -152,7 +155,7 @@ export class Duration {
|
|
|
152
155
|
get hours() {
|
|
153
156
|
return this.values.hours || 0;
|
|
154
157
|
}
|
|
155
|
-
/**
|
|
158
|
+
/** Get the minutes. */
|
|
156
159
|
get minutes() {
|
|
157
160
|
return this.values.minutes || 0;
|
|
158
161
|
}
|
|
@@ -167,13 +170,13 @@ export class Duration {
|
|
|
167
170
|
/**
|
|
168
171
|
* Get the value of unit.
|
|
169
172
|
* @param {string} unit - a unit such as 'minute' or 'day'
|
|
170
|
-
* @example Duration
|
|
171
|
-
* @example Duration
|
|
172
|
-
* @example Duration
|
|
173
|
+
* @example new Duration({years: 2, days: 3}).get('years') // 2
|
|
174
|
+
* @example new Duration({years: 2, days: 3}).get('months') // 0
|
|
175
|
+
* @example new Duration({years: 2, days: 3}).get('days') // 3
|
|
173
176
|
* @return {number}
|
|
174
177
|
*/
|
|
175
178
|
get(unit) {
|
|
176
|
-
return this[UNITS_PLURAL[unit.toLowerCase()]];
|
|
179
|
+
return this.values[UNITS_PLURAL[unit.toLowerCase()]] ?? 0;
|
|
177
180
|
}
|
|
178
181
|
add(duration) {
|
|
179
182
|
const dur = new Duration(duration);
|
|
@@ -183,7 +186,7 @@ export class Duration {
|
|
|
183
186
|
result[k] = dur.get(k) + this.get(k);
|
|
184
187
|
}
|
|
185
188
|
}
|
|
186
|
-
return
|
|
189
|
+
return this.withValues(result);
|
|
187
190
|
}
|
|
188
191
|
/**
|
|
189
192
|
* Make this Duration shorter by the specified amount. Return a newly-constructed Duration.
|
|
@@ -208,7 +211,7 @@ export class Duration {
|
|
|
208
211
|
for (const k of Object.keys(this.values)) {
|
|
209
212
|
negated[k] = this.values[k] === 0 ? 0 : -this.values[k];
|
|
210
213
|
}
|
|
211
|
-
return
|
|
214
|
+
return this.withValues(negated);
|
|
212
215
|
}
|
|
213
216
|
/**
|
|
214
217
|
* Return the absolute values of this Duration.
|
|
@@ -224,7 +227,7 @@ export class Duration {
|
|
|
224
227
|
for (const k of Object.keys(this.values)) {
|
|
225
228
|
parts[k] = Math.abs(this.values[k]);
|
|
226
229
|
}
|
|
227
|
-
return
|
|
230
|
+
return this.withValues(parts);
|
|
228
231
|
}
|
|
229
232
|
shiftToAll() {
|
|
230
233
|
return this.shiftTo('years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds');
|
|
@@ -273,59 +276,61 @@ export class Duration {
|
|
|
273
276
|
key === lastUnit ? accumulated[key] : accumulated[key] / this.matrix[lastUnit][key];
|
|
274
277
|
}
|
|
275
278
|
}
|
|
276
|
-
return
|
|
279
|
+
return this.withValues(built);
|
|
277
280
|
}
|
|
278
281
|
total(unit) {
|
|
279
282
|
return this.shiftTo(unit).get(unit);
|
|
280
283
|
}
|
|
281
284
|
exact(unit) {
|
|
285
|
+
if (unit)
|
|
286
|
+
return new Duration(this, true).total(unit);
|
|
282
287
|
this.matrix = exactMatrix;
|
|
283
|
-
|
|
284
|
-
return this;
|
|
285
|
-
return this.total(unit);
|
|
288
|
+
return this;
|
|
286
289
|
}
|
|
287
290
|
toObject() {
|
|
288
291
|
return { ...this.values };
|
|
289
292
|
}
|
|
290
293
|
normalize() {
|
|
291
|
-
|
|
292
|
-
|
|
294
|
+
const values = this.toObject();
|
|
295
|
+
normalizeValues(this.matrix, values);
|
|
296
|
+
return this.withValues(values);
|
|
293
297
|
}
|
|
294
298
|
rescale() {
|
|
295
299
|
const dur = this.normalize().shiftToAll();
|
|
296
300
|
const vals = removeZeroes(dur.values);
|
|
297
|
-
return
|
|
301
|
+
return this.withValues(vals);
|
|
298
302
|
}
|
|
299
303
|
/**
|
|
300
304
|
* Returns an ISO 8601-compliant string representation of this Duration.
|
|
301
305
|
* @see https://en.wikipedia.org/wiki/ISO_8601#Durations
|
|
302
|
-
* @example Duration
|
|
303
|
-
* @example Duration
|
|
304
|
-
* @example Duration
|
|
305
|
-
* @example Duration
|
|
306
|
-
* @example Duration
|
|
306
|
+
* @example new Duration({ years: 3, seconds: 45 }).toString() // 'P3YT45S'
|
|
307
|
+
* @example new Duration({ months: 4, seconds: 45 }).toString() // 'P4MT45S'
|
|
308
|
+
* @example new Duration({ months: 5 }).toString() // 'P5M'
|
|
309
|
+
* @example new Duration({ minutes: 5 }).toString() // 'PT5M'
|
|
310
|
+
* @example new Duration({ milliseconds: 6 }).toString() // 'PT0.006S'
|
|
307
311
|
* @return {string}
|
|
308
312
|
*/
|
|
309
313
|
toISOString() {
|
|
310
314
|
let s = 'P';
|
|
315
|
+
const months = this.get('quarters') * 3 + this.months;
|
|
311
316
|
if (this.years !== 0)
|
|
312
|
-
s += this.years
|
|
313
|
-
if (
|
|
314
|
-
s +=
|
|
317
|
+
s += `${this.years}Y`;
|
|
318
|
+
if (months !== 0)
|
|
319
|
+
s += `${months}M`;
|
|
315
320
|
if (this.weeks !== 0)
|
|
316
|
-
s += this.weeks
|
|
321
|
+
s += `${this.weeks}W`;
|
|
317
322
|
if (this.days !== 0)
|
|
318
|
-
s += this.days
|
|
323
|
+
s += `${this.days}D`;
|
|
319
324
|
if (this.hours !== 0 || this.minutes !== 0 || this.seconds !== 0 || this.milliseconds !== 0)
|
|
320
325
|
s += 'T';
|
|
321
326
|
if (this.hours !== 0)
|
|
322
|
-
s += this.hours
|
|
327
|
+
s += `${this.hours}H`;
|
|
323
328
|
if (this.minutes !== 0)
|
|
324
|
-
s += this.minutes
|
|
329
|
+
s += `${this.minutes}M`;
|
|
325
330
|
if (this.seconds !== 0 || this.milliseconds !== 0)
|
|
326
331
|
// this will handle "floating point madness" by removing extra decimal places
|
|
327
332
|
// https://stackoverflow.com/questions/588004/is-floating-point-math-broken
|
|
328
|
-
s += round(this.seconds + this.milliseconds / 1000, 3)
|
|
333
|
+
s += `${round(this.seconds + this.milliseconds / 1000, 3)}S`;
|
|
329
334
|
if (s === 'P')
|
|
330
335
|
s += 'T0S';
|
|
331
336
|
return s;
|
|
@@ -357,7 +362,8 @@ export class Duration {
|
|
|
357
362
|
function normalizeUnits(obj) {
|
|
358
363
|
const vals = {};
|
|
359
364
|
for (const unit of Object.keys(obj)) {
|
|
360
|
-
|
|
365
|
+
if (obj[unit] != null)
|
|
366
|
+
vals[UNITS_PLURAL[unit]] = obj[unit];
|
|
361
367
|
}
|
|
362
368
|
return vals;
|
|
363
369
|
}
|
package/dist/i18n/format.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function fromFields(utc: boolean, year: number, month: any, day: any, hour: any, minute: any, second: any, ms: any): Date;
|
|
1
2
|
/**
|
|
2
3
|
* Returns a new Date from the given arguments.
|
|
3
4
|
* @param {string | number | Date} date The date value
|
|
@@ -7,11 +8,13 @@
|
|
|
7
8
|
export declare function asDate(date: string | number | Date, utc?: boolean): Date;
|
|
8
9
|
/**
|
|
9
10
|
* Returns a localized string representation of this date, according to the given format string. Format codes use the same specification as {@link https://momentjs.com/docs/#/displaying/format/ moment}.
|
|
10
|
-
* @param {string}
|
|
11
|
+
* @param {string} formatStr The format string to use
|
|
12
|
+
* @param {Date} date The date value
|
|
13
|
+
* @param {?string} locale The locale to use when formatting (default is system locale).
|
|
11
14
|
* @see {@link https://momentjs.com/docs/#/displaying/format/ List of formats}
|
|
12
15
|
* @example
|
|
13
16
|
```js
|
|
14
|
-
formatDate(
|
|
17
|
+
formatDate('MM/DD/YYYY', new Date()) // '10/31/2022'
|
|
15
18
|
```
|
|
16
19
|
*/
|
|
17
20
|
export declare function formatDate(formatStr: string, date: Date, locale?: string): string;
|
package/dist/i18n/format.js
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
const NATIVE_DATE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/;
|
|
2
|
-
const
|
|
3
|
-
const REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|Q|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|N{1,4}|LTS?|L{1,4}|l{1,4}|x|X|SSS/g;
|
|
2
|
+
const REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|Q|Do|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|N{1,4}|LTS?|L{1,4}|l{1,4}|x|X|SSS/g;
|
|
4
3
|
const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ';
|
|
4
|
+
const INVALID_DATE_STRING = 'Invalid Date';
|
|
5
|
+
const ORDINAL_SUFFIXES = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
|
|
5
6
|
function padStart(string, length, pad) {
|
|
6
7
|
return String(string).padStart(length, pad);
|
|
7
8
|
}
|
|
9
|
+
function padYear(year) {
|
|
10
|
+
return `${year < 0 ? '-' : ''}${padStart(Math.abs(year), 4, '0')}`;
|
|
11
|
+
}
|
|
8
12
|
function padZoneStr(instance) {
|
|
9
13
|
const negMinutes = -instance.getTimezoneOffset();
|
|
10
14
|
const minutes = Math.abs(negMinutes);
|
|
11
15
|
const hourOffset = Math.floor(minutes / 60);
|
|
12
16
|
const minuteOffset = minutes % 60;
|
|
13
|
-
return `${negMinutes
|
|
17
|
+
return `${negMinutes >= 0 ? '+' : '-'}${padStart(hourOffset, 2, '0')}:${padStart(minuteOffset, 2, '0')}`;
|
|
18
|
+
}
|
|
19
|
+
export function fromFields(utc, year, month, day, hour, minute, second, ms) {
|
|
20
|
+
// Date reads the years 0 to 99 as 1900 to 1999, 400 years later the leap years still match
|
|
21
|
+
const shift = year >= 0 && year < 100 ? 400 : 0;
|
|
22
|
+
if (utc) {
|
|
23
|
+
const date = new Date(Date.UTC(year + shift, month, day, hour, minute, second, ms));
|
|
24
|
+
date.setUTCFullYear(date.getUTCFullYear() - shift);
|
|
25
|
+
return date;
|
|
26
|
+
}
|
|
27
|
+
const date = new Date(year + shift, month, day, hour, minute, second, ms);
|
|
28
|
+
date.setFullYear(date.getFullYear() - shift);
|
|
29
|
+
return date;
|
|
14
30
|
}
|
|
15
31
|
/**
|
|
16
32
|
* Returns a new Date from the given arguments.
|
|
@@ -29,22 +45,13 @@ export function asDate(date, utc = false) {
|
|
|
29
45
|
const d = date.match(NATIVE_DATE);
|
|
30
46
|
if (d) {
|
|
31
47
|
const m = d[2] - 1 || 0;
|
|
32
|
-
const ms = (d[7] || '0').slice(0, 3);
|
|
33
|
-
|
|
34
|
-
return new Date(Date.UTC(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms));
|
|
35
|
-
}
|
|
36
|
-
return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);
|
|
48
|
+
const ms = (d[7] || '').padEnd(3, '0').slice(0, 3);
|
|
49
|
+
return fromFields(utc, Number(d[1]), m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
52
|
const fromDate = new Date(date);
|
|
40
53
|
if (utc) {
|
|
41
|
-
fromDate.
|
|
42
|
-
fromDate.setMonth(fromDate.getUTCMonth());
|
|
43
|
-
fromDate.setDate(fromDate.getUTCDate());
|
|
44
|
-
fromDate.setHours(fromDate.getUTCHours());
|
|
45
|
-
fromDate.setMinutes(fromDate.getUTCMinutes());
|
|
46
|
-
fromDate.setSeconds(fromDate.getUTCSeconds());
|
|
47
|
-
fromDate.setMilliseconds(fromDate.getUTCMilliseconds());
|
|
54
|
+
return fromFields(false, fromDate.getUTCFullYear(), fromDate.getUTCMonth(), fromDate.getUTCDate(), fromDate.getUTCHours(), fromDate.getUTCMinutes(), fromDate.getUTCSeconds(), fromDate.getUTCMilliseconds());
|
|
48
55
|
}
|
|
49
56
|
return fromDate;
|
|
50
57
|
}
|
|
@@ -56,7 +63,6 @@ const STRFTIME = {
|
|
|
56
63
|
// weekday
|
|
57
64
|
'%A': { weekday: l },
|
|
58
65
|
'%a': { weekday: s },
|
|
59
|
-
'%aa': { weekday: n },
|
|
60
66
|
// day
|
|
61
67
|
'%d': { day: dd },
|
|
62
68
|
'%-d': { day: n },
|
|
@@ -89,7 +95,6 @@ const STRFTIME = {
|
|
|
89
95
|
// era
|
|
90
96
|
'%N': { era: l, year: dd },
|
|
91
97
|
'%n': { era: s, year: dd },
|
|
92
|
-
'%nn': { era: n, year: 'narrow' },
|
|
93
98
|
// timeZoneName
|
|
94
99
|
// '%Z': { timeZoneName: 'longGeneric', year: dd },
|
|
95
100
|
// '%-Z': { timeZoneName: 'shortGeneric', year: dd },
|
|
@@ -136,14 +141,12 @@ const TOKENS = {
|
|
|
136
141
|
NNN: { era: s, year: dd },
|
|
137
142
|
NNNN: { era: l, year: dd },
|
|
138
143
|
// timeZoneName
|
|
139
|
-
ZZ: { timeZoneName: 'longOffset', year: dd },
|
|
140
|
-
Z: { timeZoneName: 'shortOffset', year: dd },
|
|
141
144
|
zzz: { timeZoneName: l, year: dd },
|
|
142
145
|
z: { timeZoneName: s, year: dd }
|
|
143
146
|
};
|
|
144
147
|
const HOUR_PARTS = { '%I': 1, '%-I': 1, '%K': 1, '%k': 1 };
|
|
145
|
-
const ERA_PARTS = { '%n': 1, '%N': 1
|
|
146
|
-
const TZ_PARTS = { '
|
|
148
|
+
const ERA_PARTS = { '%n': 1, '%N': 1 };
|
|
149
|
+
const TZ_PARTS = { '%-z': 1, '%z': 1, '%-Z': 1, '%Z': 1 };
|
|
147
150
|
function formatter(locale, opts) {
|
|
148
151
|
return new Intl.DateTimeFormat(locale, opts);
|
|
149
152
|
}
|
|
@@ -154,20 +157,30 @@ function formatMeridiem(hour, isLowercase) {
|
|
|
154
157
|
const m = hour < 12 ? 'AM' : 'PM';
|
|
155
158
|
return isLowercase ? m.toLowerCase() : m;
|
|
156
159
|
}
|
|
157
|
-
function
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
+
function formatOrdinal(day, locale) {
|
|
161
|
+
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
|
|
162
|
+
const isEnglish = rules.resolvedOptions().locale.split('-')[0] === 'en';
|
|
163
|
+
return isEnglish ? `${day}${ORDINAL_SUFFIXES[rules.select(day)]}` : String(day);
|
|
164
|
+
}
|
|
165
|
+
function formatPart(locale, opts, date, type) {
|
|
166
|
+
return (formatter(locale, opts)
|
|
167
|
+
.formatToParts(date)
|
|
168
|
+
.find((part) => part.type === type)?.value ?? '');
|
|
160
169
|
}
|
|
161
170
|
/**
|
|
162
171
|
* Returns a localized string representation of this date, according to the given format string. Format codes use the same specification as {@link https://momentjs.com/docs/#/displaying/format/ moment}.
|
|
163
|
-
* @param {string}
|
|
172
|
+
* @param {string} formatStr The format string to use
|
|
173
|
+
* @param {Date} date The date value
|
|
174
|
+
* @param {?string} locale The locale to use when formatting (default is system locale).
|
|
164
175
|
* @see {@link https://momentjs.com/docs/#/displaying/format/ List of formats}
|
|
165
176
|
* @example
|
|
166
177
|
```js
|
|
167
|
-
formatDate(
|
|
178
|
+
formatDate('MM/DD/YYYY', new Date()) // '10/31/2022'
|
|
168
179
|
```
|
|
169
180
|
*/
|
|
170
181
|
export function formatDate(formatStr, date, locale) {
|
|
182
|
+
if (Number.isNaN(date.getTime()))
|
|
183
|
+
return INVALID_DATE_STRING;
|
|
171
184
|
const str = formatStr || FORMAT_DEFAULT;
|
|
172
185
|
const zoneStr = padZoneStr(date);
|
|
173
186
|
const time = {
|
|
@@ -187,12 +200,12 @@ export function formatDate(formatStr, date, locale) {
|
|
|
187
200
|
};
|
|
188
201
|
const matches = {
|
|
189
202
|
...time,
|
|
190
|
-
N: formatPart(locale,
|
|
191
|
-
NN: formatPart(locale,
|
|
192
|
-
NNN: formatPart(locale,
|
|
193
|
-
NNNN: formatPart(locale,
|
|
194
|
-
YY:
|
|
195
|
-
YYYY: date.getFullYear(),
|
|
203
|
+
N: formatPart(locale, TOKENS.N, date, 'era'),
|
|
204
|
+
NN: formatPart(locale, TOKENS.NN, date, 'era'),
|
|
205
|
+
NNN: formatPart(locale, TOKENS.NNN, date, 'era'),
|
|
206
|
+
NNNN: formatPart(locale, TOKENS.NNNN, date, 'era'),
|
|
207
|
+
YY: padStart(Math.abs(date.getFullYear()) % 100, 2, '0'),
|
|
208
|
+
YYYY: padYear(date.getFullYear()),
|
|
196
209
|
M: date.getMonth() + 1,
|
|
197
210
|
MM: padStart(date.getMonth() + 1, 2, '0'),
|
|
198
211
|
MMM: formatter(locale, TOKENS.MMM).format(date),
|
|
@@ -200,13 +213,14 @@ export function formatDate(formatStr, date, locale) {
|
|
|
200
213
|
Q: Math.ceil((date.getMonth() + 1) / 3),
|
|
201
214
|
D: date.getDate(),
|
|
202
215
|
DD: padStart(date.getDate(), 2, '0'),
|
|
216
|
+
Do: formatOrdinal(date.getDate(), locale),
|
|
203
217
|
d: date.getDay(),
|
|
204
218
|
ddd: formatter(locale, TOKENS.ddd).format(date),
|
|
205
219
|
dddd: formatter(locale, TOKENS.dddd).format(date),
|
|
206
|
-
Z:
|
|
207
|
-
ZZ:
|
|
208
|
-
z: formatPart(locale,
|
|
209
|
-
zzz: formatPart(locale,
|
|
220
|
+
Z: zoneStr,
|
|
221
|
+
ZZ: zoneStr.replace(':', ''),
|
|
222
|
+
z: formatPart(locale, TOKENS.z, date, 'timeZoneName'),
|
|
223
|
+
zzz: formatPart(locale, TOKENS.zzz, date, 'timeZoneName'),
|
|
210
224
|
LT: `${time.h}:${time.mm} ${time.A}`,
|
|
211
225
|
LTS: `${time.h}:${time.mm}:${time.ss} ${time.A}`,
|
|
212
226
|
L: formatter(locale, DATE_SHORT_DD).format(date),
|
|
@@ -218,7 +232,7 @@ export function formatDate(formatStr, date, locale) {
|
|
|
218
232
|
lll: formatter(locale, DATE_MED_TIME).format(date),
|
|
219
233
|
llll: formatter(locale, DATE_MED_WITH_WEEKDAY).format(date)
|
|
220
234
|
};
|
|
221
|
-
return str.replace(REGEX_FORMAT, (match, $1) => $1
|
|
235
|
+
return str.replace(REGEX_FORMAT, (match, $1) => $1 ?? matches[match] ?? match);
|
|
222
236
|
}
|
|
223
237
|
/**
|
|
224
238
|
* Formats a date using a formatting string in the {@link https://strftime.org/ strftime} format, in any given locale.
|
|
@@ -234,9 +248,11 @@ strftime('%A, %d/%m/%y', new Date())
|
|
|
234
248
|
```
|
|
235
249
|
*/
|
|
236
250
|
export function strftime(fmt, date, locale) {
|
|
251
|
+
if (date != null && Number.isNaN(+date))
|
|
252
|
+
return INVALID_DATE_STRING;
|
|
237
253
|
const results = [];
|
|
238
254
|
let dayPeriod = '';
|
|
239
|
-
|
|
255
|
+
const dayPeriodIndexes = [];
|
|
240
256
|
for (let i = 0; i < fmt.length; i++) {
|
|
241
257
|
let part = fmt[i];
|
|
242
258
|
if (part === '%') {
|
|
@@ -248,37 +264,43 @@ export function strftime(fmt, date, locale) {
|
|
|
248
264
|
if (fmt[i] === '-') {
|
|
249
265
|
part += fmt[i++];
|
|
250
266
|
}
|
|
251
|
-
part += fmt[i];
|
|
252
|
-
//
|
|
253
|
-
|
|
267
|
+
part += fmt[i] ?? '';
|
|
268
|
+
// a doubled letter is a directive of its own only when the table lists it
|
|
269
|
+
if (fmt[i + 1] === fmt[i] && STRFTIME[part + fmt[i]])
|
|
254
270
|
part += fmt[++i];
|
|
271
|
+
if (!STRFTIME[part]) {
|
|
272
|
+
results.push(part);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
255
275
|
if (HOUR_PARTS[part]) {
|
|
256
|
-
|
|
276
|
+
results.push(formatPart(locale, STRFTIME[part], date, 'hour'));
|
|
257
277
|
// save the AM/PM for the correct spot
|
|
258
|
-
|
|
259
|
-
dayPeriod = res[1];
|
|
278
|
+
dayPeriod = formatPart(locale, STRFTIME[part], date, 'dayPeriod');
|
|
260
279
|
continue;
|
|
261
280
|
}
|
|
262
281
|
if (part === '%P' || part === '%p') {
|
|
263
282
|
// leave this flag in place for later
|
|
264
|
-
|
|
265
|
-
if (part === '%p' && dayPeriod) {
|
|
266
|
-
dayPeriod = dayPeriod.toLowerCase();
|
|
267
|
-
}
|
|
283
|
+
dayPeriodIndexes.push(results.length);
|
|
268
284
|
results.push(part);
|
|
269
285
|
continue;
|
|
270
286
|
}
|
|
271
287
|
if (ERA_PARTS[part] || TZ_PARTS[part]) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
results.push(res.slice(1).join(' '));
|
|
288
|
+
const type = ERA_PARTS[part] ? 'era' : 'timeZoneName';
|
|
289
|
+
results.push(formatPart(locale, STRFTIME[part], date, type));
|
|
275
290
|
continue;
|
|
276
291
|
}
|
|
277
|
-
// format any other parts
|
|
278
|
-
|
|
292
|
+
// format any other parts, numbers without the unit text of the locale
|
|
293
|
+
const [type, style] = Object.entries(STRFTIME[part]).at(-1);
|
|
294
|
+
let res = style === n || style === dd
|
|
295
|
+
? formatPart(locale, STRFTIME[part], date, type)
|
|
296
|
+
: formatter(locale, STRFTIME[part]).format(date);
|
|
279
297
|
// fix bugs in time formatter
|
|
280
298
|
if ((part === '%S' || part === '%M') && res.length === 1)
|
|
281
|
-
res =
|
|
299
|
+
res = `0${res}`;
|
|
300
|
+
if (part === '%-H') {
|
|
301
|
+
const hours = (date === undefined ? new Date() : new Date(date)).getHours();
|
|
302
|
+
res = new Intl.NumberFormat(locale).format(hours);
|
|
303
|
+
}
|
|
282
304
|
results.push(res);
|
|
283
305
|
}
|
|
284
306
|
else {
|
|
@@ -286,12 +308,12 @@ export function strftime(fmt, date, locale) {
|
|
|
286
308
|
results.push(part);
|
|
287
309
|
}
|
|
288
310
|
}
|
|
289
|
-
// insert the AM/PM at the correct
|
|
290
|
-
|
|
291
|
-
results[
|
|
311
|
+
// insert the AM/PM at the correct spots
|
|
312
|
+
for (const index of dayPeriodIndexes) {
|
|
313
|
+
results[index] = results[index] === '%p' ? dayPeriod.toLowerCase() : dayPeriod;
|
|
314
|
+
}
|
|
292
315
|
return results.join('').trim();
|
|
293
316
|
}
|
|
294
|
-
const DATETIME_DEFAULT = {};
|
|
295
317
|
/** L: 09/04/1983 */
|
|
296
318
|
const DATE_SHORT_DD = {
|
|
297
319
|
year: n,
|
|
@@ -344,7 +366,7 @@ const DATE_MED_WITH_WEEKDAY = {
|
|
|
344
366
|
minute: n,
|
|
345
367
|
hourCycle: 'h12'
|
|
346
368
|
};
|
|
347
|
-
/** LLLL:
|
|
369
|
+
/** LLLL: Friday, October 14, 1983, 8:30 PM */
|
|
348
370
|
const DATE_HUGE = {
|
|
349
371
|
year: n,
|
|
350
372
|
month: l,
|
|
@@ -354,153 +376,3 @@ const DATE_HUGE = {
|
|
|
354
376
|
minute: n,
|
|
355
377
|
hourCycle: 'h12'
|
|
356
378
|
};
|
|
357
|
-
/** LT: 09:30 AM */
|
|
358
|
-
const TIME_SIMPLE = {
|
|
359
|
-
hour: n,
|
|
360
|
-
minute: n,
|
|
361
|
-
hourCycle: 'h12'
|
|
362
|
-
};
|
|
363
|
-
/** LTS: 09:30:23 AM */
|
|
364
|
-
const TIME_WITH_SECONDS = {
|
|
365
|
-
hour: n,
|
|
366
|
-
minute: n,
|
|
367
|
-
second: n,
|
|
368
|
-
hourCycle: 'h12'
|
|
369
|
-
};
|
|
370
|
-
/** 09:30:23 AM EDT */
|
|
371
|
-
const TIME_WITH_SHORT_OFFSET = {
|
|
372
|
-
hour: n,
|
|
373
|
-
minute: n,
|
|
374
|
-
second: n,
|
|
375
|
-
timeZoneName: s,
|
|
376
|
-
hourCycle: 'h12'
|
|
377
|
-
};
|
|
378
|
-
/** 09:30:23 AM Eastern Daylight Time */
|
|
379
|
-
const TIME_WITH_LONG_OFFSET = {
|
|
380
|
-
hour: n,
|
|
381
|
-
minute: n,
|
|
382
|
-
second: n,
|
|
383
|
-
timeZoneName: l,
|
|
384
|
-
hourCycle: 'h12'
|
|
385
|
-
};
|
|
386
|
-
/** 09:30 */
|
|
387
|
-
const TIME_24_SIMPLE = {
|
|
388
|
-
hour: n,
|
|
389
|
-
minute: n,
|
|
390
|
-
hourCycle: 'h23'
|
|
391
|
-
};
|
|
392
|
-
/** 09:30:23 */
|
|
393
|
-
const TIME_24_WITH_SECONDS = {
|
|
394
|
-
hour: n,
|
|
395
|
-
minute: n,
|
|
396
|
-
second: n,
|
|
397
|
-
hourCycle: 'h23'
|
|
398
|
-
};
|
|
399
|
-
/** 09:30:23 EDT */
|
|
400
|
-
const TIME_24_WITH_SHORT_OFFSET = {
|
|
401
|
-
hour: n,
|
|
402
|
-
minute: n,
|
|
403
|
-
second: n,
|
|
404
|
-
hourCycle: 'h23',
|
|
405
|
-
timeZoneName: s
|
|
406
|
-
};
|
|
407
|
-
/** 09:30:23 Eastern Daylight Time */
|
|
408
|
-
const TIME_24_WITH_LONG_OFFSET = {
|
|
409
|
-
hour: n,
|
|
410
|
-
minute: n,
|
|
411
|
-
second: n,
|
|
412
|
-
hourCycle: 'h23',
|
|
413
|
-
timeZoneName: l
|
|
414
|
-
};
|
|
415
|
-
/** 10/14/1983, 9:30 AM */
|
|
416
|
-
const DATETIME_SHORT = {
|
|
417
|
-
year: n,
|
|
418
|
-
month: n,
|
|
419
|
-
day: n,
|
|
420
|
-
hour: n,
|
|
421
|
-
minute: n,
|
|
422
|
-
hourCycle: 'h12'
|
|
423
|
-
};
|
|
424
|
-
/** 10/14/1983, 9:30:33 AM */
|
|
425
|
-
const DATETIME_SHORT_WITH_SECONDS = {
|
|
426
|
-
year: n,
|
|
427
|
-
month: n,
|
|
428
|
-
day: n,
|
|
429
|
-
hour: n,
|
|
430
|
-
minute: n,
|
|
431
|
-
second: n,
|
|
432
|
-
hourCycle: 'h12'
|
|
433
|
-
};
|
|
434
|
-
/** Oct 14, 1983, 9:30 AM */
|
|
435
|
-
const DATETIME_MED = {
|
|
436
|
-
year: n,
|
|
437
|
-
month: s,
|
|
438
|
-
day: n,
|
|
439
|
-
hour: n,
|
|
440
|
-
minute: n,
|
|
441
|
-
hourCycle: 'h12'
|
|
442
|
-
};
|
|
443
|
-
/** Oct 14, 1983, 9:30:33 AM */
|
|
444
|
-
const DATETIME_MED_WITH_SECONDS = {
|
|
445
|
-
year: n,
|
|
446
|
-
month: s,
|
|
447
|
-
day: n,
|
|
448
|
-
hour: n,
|
|
449
|
-
minute: n,
|
|
450
|
-
second: n,
|
|
451
|
-
hourCycle: 'h12'
|
|
452
|
-
};
|
|
453
|
-
/** Fri, 14 Oct 1983, 9:30 AM */
|
|
454
|
-
const DATETIME_MED_WITH_WEEKDAY = {
|
|
455
|
-
year: n,
|
|
456
|
-
month: s,
|
|
457
|
-
day: n,
|
|
458
|
-
weekday: s,
|
|
459
|
-
hour: n,
|
|
460
|
-
minute: n,
|
|
461
|
-
hourCycle: 'h12'
|
|
462
|
-
};
|
|
463
|
-
/** October 14, 1983, 9:30 AM EDT */
|
|
464
|
-
const DATETIME_FULL = {
|
|
465
|
-
year: n,
|
|
466
|
-
month: l,
|
|
467
|
-
day: n,
|
|
468
|
-
hour: n,
|
|
469
|
-
minute: n,
|
|
470
|
-
timeZoneName: s,
|
|
471
|
-
hourCycle: 'h12'
|
|
472
|
-
};
|
|
473
|
-
/** October 14, 1983, 9:30:33 AM EDT */
|
|
474
|
-
const DATETIME_FULL_WITH_SECONDS = {
|
|
475
|
-
year: n,
|
|
476
|
-
month: l,
|
|
477
|
-
day: n,
|
|
478
|
-
hour: n,
|
|
479
|
-
minute: n,
|
|
480
|
-
second: n,
|
|
481
|
-
timeZoneName: s,
|
|
482
|
-
hourCycle: 'h12'
|
|
483
|
-
};
|
|
484
|
-
/** Friday, October 14, 1983, 9:30 AM Eastern Daylight Time */
|
|
485
|
-
const DATETIME_HUGE = {
|
|
486
|
-
year: n,
|
|
487
|
-
month: l,
|
|
488
|
-
day: n,
|
|
489
|
-
weekday: l,
|
|
490
|
-
hour: n,
|
|
491
|
-
minute: n,
|
|
492
|
-
timeZoneName: l,
|
|
493
|
-
hourCycle: 'h12'
|
|
494
|
-
};
|
|
495
|
-
/** Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time */
|
|
496
|
-
const DATETIME_HUGE_WITH_SECONDS = {
|
|
497
|
-
year: n,
|
|
498
|
-
month: l,
|
|
499
|
-
day: n,
|
|
500
|
-
weekday: l,
|
|
501
|
-
hour: n,
|
|
502
|
-
minute: n,
|
|
503
|
-
second: n,
|
|
504
|
-
timeZoneName: l,
|
|
505
|
-
hourCycle: 'h12'
|
|
506
|
-
};
|