atomic-fns 0.3.3 → 0.3.5
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 +18 -4
- package/core/collections/LRUCache.d.ts +22 -1
- package/core/collections/LRUCache.js +22 -1
- package/core/collections/LRUCache.ts +22 -1
- package/core/collections/SortedMap.d.ts +1 -1
- package/core/collections/SortedMap.js +1 -1
- package/core/collections/SortedMap.ts +1 -1
- package/core/collections/SortedSet.d.ts +6 -0
- package/core/collections/SortedSet.js +6 -0
- package/core/collections/SortedSet.ts +6 -0
- package/core/collections/SortedTree.d.ts +3 -3
- package/core/collections/SortedTree.js +3 -3
- package/core/collections/SortedTree.ts +3 -3
- package/core/collections/abc.d.ts +1 -1
- package/core/collections/abc.ts +1 -1
- package/core/collections/deque.d.ts +55 -48
- package/core/collections/deque.js +61 -53
- package/core/collections/deque.ts +63 -54
- package/core/collections/index.d.ts +2 -0
- package/core/collections/index.js +7 -5
- package/core/collections/index.ts +7 -5
- package/core/functools/index.d.ts +3 -2
- package/core/functools/index.ts +8 -3
- package/core/globals/index.d.ts +23 -4
- package/core/globals/index.js +29 -6
- package/core/globals/index.ts +40 -7
- package/core/i18n/date/format.d.ts +16 -0
- package/core/i18n/date/format.js +307 -0
- package/core/i18n/date/format.ts +343 -0
- package/core/i18n/date/index.d.ts +224 -0
- package/core/i18n/date/index.js +387 -0
- package/core/i18n/date/index.ts +471 -0
- package/core/i18n/date/test.html +67 -0
- package/core/i18n/index.d.ts +7 -0
- package/core/i18n/index.js +7 -0
- package/core/i18n/index.ts +8 -0
- package/core/index.d.ts +1 -0
- package/core/index.js +1 -0
- package/core/index.ts +1 -0
- package/core/operators/index.d.ts +1 -1
- package/core/operators/index.js +35 -5
- package/core/operators/index.ts +34 -6
- package/package.json +11 -11
- package/tests/globals.spec.ts +12 -12
- package/tsconfig.json +2 -1
- package/core/datetime/index.d.ts +0 -45
- package/core/datetime/index.js +0 -71
- package/core/datetime/index.ts +0 -128
package/core/functools/index.ts
CHANGED
|
@@ -98,7 +98,10 @@ export const compose = (...args) => flow(args.reverse())
|
|
|
98
98
|
* @param {Function} [resolver] The function to resolve the cache key.
|
|
99
99
|
* @return {Function} Returns the new memoized function.
|
|
100
100
|
*/
|
|
101
|
-
export function memoize(
|
|
101
|
+
export function memoize<T>(
|
|
102
|
+
func: Function<T>,
|
|
103
|
+
resolver?: Function
|
|
104
|
+
): Function<ReturnType<typeof func>> {
|
|
102
105
|
const cache = new Map()
|
|
103
106
|
return (...args) => {
|
|
104
107
|
const key = resolver ? resolver(...args) : args[0]
|
|
@@ -188,14 +191,14 @@ single(3) // => 1
|
|
|
188
191
|
// => `func` is invoked only once.
|
|
189
192
|
```
|
|
190
193
|
*/
|
|
191
|
-
export function once(func: Function) {
|
|
194
|
+
export function once<T>(func: Function<T>) {
|
|
192
195
|
let result, isCalled
|
|
193
196
|
return (...args) => {
|
|
194
197
|
if (!isCalled) {
|
|
195
198
|
result = func(...args)
|
|
196
199
|
isCalled = true
|
|
197
200
|
}
|
|
198
|
-
return result
|
|
201
|
+
return result as T
|
|
199
202
|
}
|
|
200
203
|
}
|
|
201
204
|
|
|
@@ -203,6 +206,8 @@ export type Maybe<T> = T | undefined
|
|
|
203
206
|
|
|
204
207
|
export type Result<T, E = any> = [Maybe<T>, Maybe<E>]
|
|
205
208
|
|
|
209
|
+
export type Optional<T> = Maybe<T>
|
|
210
|
+
|
|
206
211
|
/**
|
|
207
212
|
* Wraps a function to catch any exceptions inside and return a `go` style error-return type {@link Result}.
|
|
208
213
|
*
|
package/core/globals/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module Globals
|
|
5
5
|
*/
|
|
6
6
|
/** This is just a noop function. */
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const noop: () => void;
|
|
8
8
|
/**
|
|
9
9
|
* A generic function type with arbitrary arguments and return.
|
|
10
10
|
*/
|
|
@@ -92,10 +92,15 @@ export declare function type(value: any): any;
|
|
|
92
92
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString | Object.toString }
|
|
93
93
|
*/
|
|
94
94
|
export declare const str: (obj: any) => any;
|
|
95
|
+
export declare function hasOwnProperty(obj: any, prop: any): boolean;
|
|
95
96
|
/** Check if value is a boolean type. */
|
|
96
97
|
export declare const isBool: (x: any) => x is boolean;
|
|
98
|
+
/** Check if value is an `Error` type. */
|
|
99
|
+
export declare const isError: (x: any) => x is Error;
|
|
97
100
|
/** Check if value is an iterable type. */
|
|
98
101
|
export declare const isIterable: (x: any) => x is IterableIterator<any>;
|
|
102
|
+
/** Check if value is a native `Date` type. */
|
|
103
|
+
export declare const isDate: (x: any) => x is Date;
|
|
99
104
|
/** Check if value is an object type. */
|
|
100
105
|
export declare const isObject: (x: any) => x is Object;
|
|
101
106
|
/** Check if value is a string type. */
|
|
@@ -107,28 +112,42 @@ export declare const isArray: (x: any) => x is any[];
|
|
|
107
112
|
* A value is considered array-like if it's not a function and has a `.length` number property.
|
|
108
113
|
*/
|
|
109
114
|
export declare const isArrayLike: (x: any) => boolean;
|
|
110
|
-
/** Check if value is a function type. */
|
|
111
|
-
export declare const isFunc: (x: any) => x is Function<any>;
|
|
112
115
|
/** Check if value is a number type. */
|
|
113
116
|
export declare const isNumber: (x: any) => x is number;
|
|
117
|
+
/** Check if value is an integer number type. */
|
|
118
|
+
export declare const isInteger: (x: any) => x is number;
|
|
114
119
|
/** Check if value is a bigint type. */
|
|
115
120
|
export declare const isBigint: (x: any) => x is BigInt;
|
|
116
121
|
/** Check if value is NaN based on `Number.isNaN`. */
|
|
117
122
|
export declare const isNaN: (x: any) => x is number;
|
|
118
123
|
/** Check if value is a Promise type. */
|
|
119
124
|
export declare const isPromise: (x: any) => x is Promise<any>;
|
|
125
|
+
/** Check if value is a function type. */
|
|
126
|
+
export declare const isFunction: (x: any) => x is Function<any>;
|
|
120
127
|
/** Check if value is an async function type. */
|
|
121
|
-
export declare const
|
|
128
|
+
export declare const isAsyncFunction: (x: any) => boolean;
|
|
122
129
|
/** Check if value is a generator function type. */
|
|
123
130
|
export declare const isGenerator: (x: any) => x is Generator<unknown, any, unknown>;
|
|
124
131
|
/** Check if value is `null` or `undefined`. */
|
|
125
132
|
export declare const isNull: (x: any) => x is null | undefined;
|
|
133
|
+
/** Check if value === `undefined`. */
|
|
134
|
+
export declare function isUndefined(o: any): boolean;
|
|
126
135
|
/** Check if value is not `null` or `undefined`. */
|
|
127
136
|
export declare const notNull: (x: any) => boolean;
|
|
128
137
|
/** Returns `true` for objects without length or falsy values. */
|
|
129
138
|
export declare const isEmpty: (x: any) => boolean;
|
|
139
|
+
/** Check if value is a `RegExp` type */
|
|
140
|
+
export declare const isRegExp: (x: any) => x is RegExp;
|
|
130
141
|
/** Check if value is a `Symbol` type */
|
|
131
142
|
export declare const isSymbol: (x: any) => x is symbol;
|
|
143
|
+
/** Check if value is a `Set` type. */
|
|
144
|
+
export declare const isSet: <T>(x: any) => x is Set<T>;
|
|
145
|
+
/** Check if value is a `Map` type. */
|
|
146
|
+
export declare const isMap: <K, V>(x: any) => x is Map<K, V>;
|
|
147
|
+
/** Check if value is a `WeakSet` type. */
|
|
148
|
+
export declare const isWeakSet: <T extends object>(x: any) => x is WeakSet<T>;
|
|
149
|
+
/** Check if value is a `WeakMap` type. */
|
|
150
|
+
export declare const isWeakMap: <K extends object, V>(x: any) => x is WeakMap<K, V>;
|
|
132
151
|
/**
|
|
133
152
|
* Returns the number of elements in a collection type.
|
|
134
153
|
*
|
package/core/globals/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module Globals
|
|
5
5
|
*/
|
|
6
6
|
/** This is just a noop function. */
|
|
7
|
-
export const
|
|
7
|
+
export const noop = () => { };
|
|
8
8
|
/** A function that always returns `true`. */
|
|
9
9
|
export const True = () => true;
|
|
10
10
|
/** A function that always returns `false`. */
|
|
@@ -122,14 +122,21 @@ export function type(value) {
|
|
|
122
122
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString | Object.toString }
|
|
123
123
|
*/
|
|
124
124
|
export const str = (obj) => (obj != null ? obj.toString() : '');
|
|
125
|
+
export function hasOwnProperty(obj, prop) {
|
|
126
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
127
|
+
}
|
|
125
128
|
/** Check if value is a boolean type. */
|
|
126
129
|
export const isBool = (x) => type(x) === 'boolean';
|
|
130
|
+
/** Check if value is an `Error` type. */
|
|
131
|
+
export const isError = (x) => x instanceof Error;
|
|
127
132
|
/** Check if value is an iterable type. */
|
|
128
133
|
export const isIterable = (x) => {
|
|
129
134
|
if (x == null)
|
|
130
135
|
return false;
|
|
131
136
|
return typeof x[Symbol.iterator] === 'function';
|
|
132
137
|
};
|
|
138
|
+
/** Check if value is a native `Date` type. */
|
|
139
|
+
export const isDate = (x) => x instanceof Date;
|
|
133
140
|
/** Check if value is an object type. */
|
|
134
141
|
export const isObject = (x) => typeof x === 'object' && type(x) === 'object';
|
|
135
142
|
/** Check if value is a string type. */
|
|
@@ -144,30 +151,46 @@ export const isArrayLike = (x) => {
|
|
|
144
151
|
const T = type(x);
|
|
145
152
|
return T === 'array' || (T === 'object' && isNumber(x.length));
|
|
146
153
|
};
|
|
147
|
-
/** Check if value is a function type. */
|
|
148
|
-
export const isFunc = (x) => x?.constructor === Function;
|
|
149
154
|
/** Check if value is a number type. */
|
|
150
155
|
export const isNumber = (x) => type(x) === 'number';
|
|
156
|
+
/** Check if value is an integer number type. */
|
|
157
|
+
export const isInteger = (x) => type(x) === 'number' && Math.floor(x) === x;
|
|
151
158
|
/** Check if value is a bigint type. */
|
|
152
159
|
export const isBigint = (x) => type(x) === 'bigint';
|
|
153
160
|
/** Check if value is NaN based on `Number.isNaN`. */
|
|
154
161
|
export const isNaN = (x) => Number.isNaN(x);
|
|
155
162
|
/** Check if value is a Promise type. */
|
|
156
163
|
export const isPromise = (x) => type(x) === 'Promise';
|
|
164
|
+
/** Check if value is a function type. */
|
|
165
|
+
export const isFunction = (x) => x?.constructor === Function;
|
|
157
166
|
/** Check if value is an async function type. */
|
|
158
|
-
export const
|
|
167
|
+
export const isAsyncFunction = (x) => x?.constructor.name === 'AsyncFunction';
|
|
159
168
|
/** Check if value is a generator function type. */
|
|
160
169
|
export const isGenerator = (x) => {
|
|
161
170
|
return x?.constructor.constructor?.name === 'GeneratorFunction';
|
|
162
171
|
};
|
|
163
172
|
/** Check if value is `null` or `undefined`. */
|
|
164
173
|
export const isNull = (x) => x == null;
|
|
174
|
+
/** Check if value === `undefined`. */
|
|
175
|
+
export function isUndefined(o) {
|
|
176
|
+
return typeof o === 'undefined';
|
|
177
|
+
}
|
|
165
178
|
/** Check if value is not `null` or `undefined`. */
|
|
166
179
|
export const notNull = (x) => x != null;
|
|
167
180
|
/** Returns `true` for objects without length or falsy values. */
|
|
168
181
|
export const isEmpty = (x) => (len(x) === 0 ? true : !x);
|
|
182
|
+
/** Check if value is a `RegExp` type */
|
|
183
|
+
export const isRegExp = (x) => x instanceof RegExp;
|
|
169
184
|
/** Check if value is a `Symbol` type */
|
|
170
185
|
export const isSymbol = (x) => type(x) === 'symbol';
|
|
186
|
+
/** Check if value is a `Set` type. */
|
|
187
|
+
export const isSet = (x) => x instanceof Set;
|
|
188
|
+
/** Check if value is a `Map` type. */
|
|
189
|
+
export const isMap = (x) => x instanceof Map;
|
|
190
|
+
/** Check if value is a `WeakSet` type. */
|
|
191
|
+
export const isWeakSet = (x) => x instanceof WeakSet;
|
|
192
|
+
/** Check if value is a `WeakMap` type. */
|
|
193
|
+
export const isWeakMap = (x) => x instanceof WeakMap;
|
|
171
194
|
/**
|
|
172
195
|
* Returns the number of elements in a collection type.
|
|
173
196
|
*
|
|
@@ -182,7 +205,7 @@ export function len(value) {
|
|
|
182
205
|
if (isNumber(value.length)) {
|
|
183
206
|
return value.length;
|
|
184
207
|
}
|
|
185
|
-
if (
|
|
208
|
+
if (isFunction(value.size)) {
|
|
186
209
|
return value.size();
|
|
187
210
|
}
|
|
188
211
|
if (isNumber(value.size)) {
|
|
@@ -229,7 +252,7 @@ export const uuid = () => {
|
|
|
229
252
|
* @return `obj.key(...args)` or `undefined`.
|
|
230
253
|
*/
|
|
231
254
|
export function call(obj, key, ...args) {
|
|
232
|
-
if (
|
|
255
|
+
if (isFunction(get(key, obj))) {
|
|
233
256
|
return obj[key](...args);
|
|
234
257
|
}
|
|
235
258
|
}
|
package/core/globals/index.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/** This is just a noop function. */
|
|
8
|
-
export const
|
|
8
|
+
export const noop = () => {}
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A generic function type with arbitrary arguments and return.
|
|
@@ -142,15 +142,25 @@ export function type(value) {
|
|
|
142
142
|
*/
|
|
143
143
|
export const str = (obj) => (obj != null ? obj.toString() : '')
|
|
144
144
|
|
|
145
|
+
export function hasOwnProperty(obj, prop) {
|
|
146
|
+
return Object.prototype.hasOwnProperty.call(obj, prop)
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
/** Check if value is a boolean type. */
|
|
146
150
|
export const isBool = (x): x is boolean => type(x) === 'boolean'
|
|
147
151
|
|
|
152
|
+
/** Check if value is an `Error` type. */
|
|
153
|
+
export const isError = (x): x is Error => x instanceof Error
|
|
154
|
+
|
|
148
155
|
/** Check if value is an iterable type. */
|
|
149
156
|
export const isIterable = (x): x is IterableIterator<any> => {
|
|
150
157
|
if (x == null) return false
|
|
151
158
|
return typeof x[Symbol.iterator] === 'function'
|
|
152
159
|
}
|
|
153
160
|
|
|
161
|
+
/** Check if value is a native `Date` type. */
|
|
162
|
+
export const isDate = (x): x is Date => x instanceof Date
|
|
163
|
+
|
|
154
164
|
/** Check if value is an object type. */
|
|
155
165
|
export const isObject = (x): x is Object => typeof x === 'object' && type(x) === 'object'
|
|
156
166
|
|
|
@@ -169,12 +179,12 @@ export const isArrayLike = (x) => {
|
|
|
169
179
|
return T === 'array' || (T === 'object' && isNumber(x.length))
|
|
170
180
|
}
|
|
171
181
|
|
|
172
|
-
/** Check if value is a function type. */
|
|
173
|
-
export const isFunc = (x): x is Function => x?.constructor === Function
|
|
174
|
-
|
|
175
182
|
/** Check if value is a number type. */
|
|
176
183
|
export const isNumber = (x): x is number => type(x) === 'number'
|
|
177
184
|
|
|
185
|
+
/** Check if value is an integer number type. */
|
|
186
|
+
export const isInteger = (x): x is number => type(x) === 'number' && Math.floor(x) === x
|
|
187
|
+
|
|
178
188
|
/** Check if value is a bigint type. */
|
|
179
189
|
export const isBigint = (x): x is BigInt => type(x) === 'bigint'
|
|
180
190
|
|
|
@@ -184,8 +194,11 @@ export const isNaN = (x): x is typeof NaN => Number.isNaN(x)
|
|
|
184
194
|
/** Check if value is a Promise type. */
|
|
185
195
|
export const isPromise = (x): x is Promise<any> => type(x) === 'Promise'
|
|
186
196
|
|
|
197
|
+
/** Check if value is a function type. */
|
|
198
|
+
export const isFunction = (x): x is Function => x?.constructor === Function
|
|
199
|
+
|
|
187
200
|
/** Check if value is an async function type. */
|
|
188
|
-
export const
|
|
201
|
+
export const isAsyncFunction = (x) => x?.constructor.name === 'AsyncFunction'
|
|
189
202
|
|
|
190
203
|
/** Check if value is a generator function type. */
|
|
191
204
|
export const isGenerator = (x): x is Generator => {
|
|
@@ -195,15 +208,35 @@ export const isGenerator = (x): x is Generator => {
|
|
|
195
208
|
/** Check if value is `null` or `undefined`. */
|
|
196
209
|
export const isNull = (x): x is null | undefined => x == null
|
|
197
210
|
|
|
211
|
+
/** Check if value === `undefined`. */
|
|
212
|
+
export function isUndefined(o) {
|
|
213
|
+
return typeof o === 'undefined'
|
|
214
|
+
}
|
|
215
|
+
|
|
198
216
|
/** Check if value is not `null` or `undefined`. */
|
|
199
217
|
export const notNull = (x) => x != null
|
|
200
218
|
|
|
201
219
|
/** Returns `true` for objects without length or falsy values. */
|
|
202
220
|
export const isEmpty = (x) => (len(x) === 0 ? true : !x)
|
|
203
221
|
|
|
222
|
+
/** Check if value is a `RegExp` type */
|
|
223
|
+
export const isRegExp = (x): x is RegExp => x instanceof RegExp
|
|
224
|
+
|
|
204
225
|
/** Check if value is a `Symbol` type */
|
|
205
226
|
export const isSymbol = (x): x is symbol => type(x) === 'symbol'
|
|
206
227
|
|
|
228
|
+
/** Check if value is a `Set` type. */
|
|
229
|
+
export const isSet = <T>(x): x is Set<T> => x instanceof Set
|
|
230
|
+
|
|
231
|
+
/** Check if value is a `Map` type. */
|
|
232
|
+
export const isMap = <K, V>(x): x is Map<K, V> => x instanceof Map
|
|
233
|
+
|
|
234
|
+
/** Check if value is a `WeakSet` type. */
|
|
235
|
+
export const isWeakSet = <T extends object>(x): x is WeakSet<T> => x instanceof WeakSet
|
|
236
|
+
|
|
237
|
+
/** Check if value is a `WeakMap` type. */
|
|
238
|
+
export const isWeakMap = <K extends object, V>(x): x is WeakMap<K, V> => x instanceof WeakMap
|
|
239
|
+
|
|
207
240
|
/**
|
|
208
241
|
* Returns the number of elements in a collection type.
|
|
209
242
|
*
|
|
@@ -217,7 +250,7 @@ export function len(value) {
|
|
|
217
250
|
if (isNumber(value.length)) {
|
|
218
251
|
return value.length
|
|
219
252
|
}
|
|
220
|
-
if (
|
|
253
|
+
if (isFunction(value.size)) {
|
|
221
254
|
return value.size()
|
|
222
255
|
}
|
|
223
256
|
if (isNumber(value.size)) {
|
|
@@ -267,7 +300,7 @@ export const uuid = () => {
|
|
|
267
300
|
* @return `obj.key(...args)` or `undefined`.
|
|
268
301
|
*/
|
|
269
302
|
export function call(obj: any, key: PropertyKey, ...args: any[]) {
|
|
270
|
-
if (
|
|
303
|
+
if (isFunction(get(key, obj))) {
|
|
271
304
|
return obj[key](...args)
|
|
272
305
|
}
|
|
273
306
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a new Date from the given arguments.
|
|
3
|
+
* @param {string | number | Date} date The date value
|
|
4
|
+
* @param {?boolean} [utc=false] Interprets the given value as a UTC date
|
|
5
|
+
* @returns {Date} The new date object
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDate(date: string | number | Date, utc?: boolean): Date;
|
|
8
|
+
/**
|
|
9
|
+
* Formats a date using a formatting string in the {@link https://strftime.org/ strftime} format, in any given locale.
|
|
10
|
+
* @param {string} fmt The format string to apply
|
|
11
|
+
* @param {number | Date} date The date value
|
|
12
|
+
* @param {?string} locale The locale to use when formatting (default is system locale).
|
|
13
|
+
* @returns {string} The string representation of date
|
|
14
|
+
* @see {@link https://strftime.org/ strftime format}
|
|
15
|
+
*/
|
|
16
|
+
export declare function format(fmt: string, date: number | Date, locale?: any): string;
|
|
@@ -0,0 +1,307 @@
|
|
|
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
|
+
/**
|
|
3
|
+
* Returns a new Date from the given arguments.
|
|
4
|
+
* @param {string | number | Date} date The date value
|
|
5
|
+
* @param {?boolean} [utc=false] Interprets the given value as a UTC date
|
|
6
|
+
* @returns {Date} The new date object
|
|
7
|
+
*/
|
|
8
|
+
export function getDate(date, utc = false) {
|
|
9
|
+
if (date === null)
|
|
10
|
+
return new Date(NaN);
|
|
11
|
+
if (!date)
|
|
12
|
+
return new Date();
|
|
13
|
+
if (date instanceof Date)
|
|
14
|
+
return new Date(date);
|
|
15
|
+
if (typeof date === 'string' && !/Z$/i.test(date)) {
|
|
16
|
+
const d = date.match(NATIVE_DATE);
|
|
17
|
+
if (d) {
|
|
18
|
+
const m = d[2] - 1 || 0;
|
|
19
|
+
const ms = (d[7] || '0').slice(0, 3);
|
|
20
|
+
if (utc) {
|
|
21
|
+
return new Date(Date.UTC(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms));
|
|
22
|
+
}
|
|
23
|
+
return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return new Date(date);
|
|
27
|
+
}
|
|
28
|
+
const n = 'numeric', s = 'short', l = 'long', dd = '2-digit', TOKEN_MAP = {
|
|
29
|
+
// weekday
|
|
30
|
+
'%A': { weekday: l },
|
|
31
|
+
'%a': { weekday: s },
|
|
32
|
+
'%aa': { weekday: n },
|
|
33
|
+
// day
|
|
34
|
+
'%d': { day: dd },
|
|
35
|
+
'%-d': { day: n },
|
|
36
|
+
// month
|
|
37
|
+
'%m': { month: dd },
|
|
38
|
+
'%-m': { month: n },
|
|
39
|
+
'%B': { month: l },
|
|
40
|
+
'%b': { month: s },
|
|
41
|
+
'%bb': { month: n },
|
|
42
|
+
// year
|
|
43
|
+
'%y': { year: n },
|
|
44
|
+
'%Y': { year: dd },
|
|
45
|
+
// hour
|
|
46
|
+
'%K': { hourCycle: 'h11', hour: dd },
|
|
47
|
+
'%I': { hourCycle: 'h12', hour: dd },
|
|
48
|
+
'%-I': { hourCycle: 'h12', hour: n },
|
|
49
|
+
'%H': { hourCycle: 'h23', hour: dd },
|
|
50
|
+
'%-H': { hourCycle: 'h23', hour: n },
|
|
51
|
+
'%k': { hourCycle: 'h24', hour: n },
|
|
52
|
+
// minutes
|
|
53
|
+
'%M': { minute: dd },
|
|
54
|
+
'%-M': { minute: n },
|
|
55
|
+
// seconds
|
|
56
|
+
'%S': { second: dd },
|
|
57
|
+
'%-S': { second: n },
|
|
58
|
+
// day period
|
|
59
|
+
'%P': { dayPeriod: l },
|
|
60
|
+
'%p': { dayPeriod: s },
|
|
61
|
+
'%pp': { dayPeriod: 'narrow' },
|
|
62
|
+
// era
|
|
63
|
+
'%N': { era: l, year: dd },
|
|
64
|
+
'%n': { era: s, year: dd },
|
|
65
|
+
'%nn': { era: n, year: 'narrow' },
|
|
66
|
+
// timeZoneName
|
|
67
|
+
'%Z': { timeZoneName: 'longGeneric', year: dd },
|
|
68
|
+
'%-Z': { timeZoneName: 'shortGeneric', year: dd },
|
|
69
|
+
'%z': { timeZoneName: 'longOffset', year: dd },
|
|
70
|
+
'%-z': { timeZoneName: 'shortOffset', year: dd },
|
|
71
|
+
'%ZZ': { timeZoneName: l, year: dd },
|
|
72
|
+
'%-ZZ': { timeZoneName: s, year: dd }
|
|
73
|
+
};
|
|
74
|
+
const HOUR_PARTS = { '%I': 1, '%-I': 1, '%K': 1, '%k': 1 };
|
|
75
|
+
const ERA_PARTS = { '%n': 1, '%N': 1, '%nn': 1 };
|
|
76
|
+
const TZ_PARTS = { '%ZZ': 1, '%-ZZ': 1, '%-z': 1, '%z': 1, '%-Z': 1, '%Z': 1 };
|
|
77
|
+
const formatter = (locale, opts) => new Intl.DateTimeFormat(locale, opts);
|
|
78
|
+
/**
|
|
79
|
+
* Formats a date using a formatting string in the {@link https://strftime.org/ strftime} format, in any given locale.
|
|
80
|
+
* @param {string} fmt The format string to apply
|
|
81
|
+
* @param {number | Date} date The date value
|
|
82
|
+
* @param {?string} locale The locale to use when formatting (default is system locale).
|
|
83
|
+
* @returns {string} The string representation of date
|
|
84
|
+
* @see {@link https://strftime.org/ strftime format}
|
|
85
|
+
*/
|
|
86
|
+
export function format(fmt, date, locale) {
|
|
87
|
+
let results = [], dayPeriod = '', dayPeriodIndex = -1;
|
|
88
|
+
for (let i = 0; i < fmt.length; i++) {
|
|
89
|
+
let part = fmt[i];
|
|
90
|
+
if (part === '%') {
|
|
91
|
+
// check for escaped '%'
|
|
92
|
+
if (fmt[++i] == '%') {
|
|
93
|
+
results.push('%');
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (fmt[i] === '-') {
|
|
97
|
+
part += fmt[i++];
|
|
98
|
+
}
|
|
99
|
+
part += fmt[i];
|
|
100
|
+
// add any repeated characters that come after
|
|
101
|
+
while (i < fmt.length - 1 && fmt[i + 1] === fmt[i])
|
|
102
|
+
part += fmt[++i];
|
|
103
|
+
if (HOUR_PARTS[part]) {
|
|
104
|
+
let res = formatter(locale, TOKEN_MAP[part]).format(date).split(' ');
|
|
105
|
+
// save the AM/PM for the correct spot
|
|
106
|
+
results.push(res[0]);
|
|
107
|
+
dayPeriod = res[1];
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (part === '%P' || part === '%p') {
|
|
111
|
+
// leave this flag in place for later
|
|
112
|
+
dayPeriodIndex = results.length;
|
|
113
|
+
results.push(part);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (ERA_PARTS[part] || TZ_PARTS[part]) {
|
|
117
|
+
// the formatting includes the date/year so we take what comes after
|
|
118
|
+
let res = formatter(locale, TOKEN_MAP[part]).format(date).split(' ');
|
|
119
|
+
results.push(res.slice(1).join(' '));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
// format any other parts
|
|
123
|
+
let res = formatter(locale, TOKEN_MAP[part]).format(date);
|
|
124
|
+
if (part === '%S' && res.length === 1)
|
|
125
|
+
res = '0' + res;
|
|
126
|
+
results.push(res);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// output as literal
|
|
130
|
+
results.push(part);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// insert the AM/PM at the correct spot
|
|
134
|
+
if (dayPeriodIndex >= 0)
|
|
135
|
+
results[dayPeriodIndex] = dayPeriod || '';
|
|
136
|
+
return results.join('');
|
|
137
|
+
}
|
|
138
|
+
const DATETIME_DEFAULT = {};
|
|
139
|
+
/** 10/14/1983 */
|
|
140
|
+
const DATE_SHORT = {
|
|
141
|
+
year: n,
|
|
142
|
+
month: n,
|
|
143
|
+
day: n
|
|
144
|
+
};
|
|
145
|
+
/** Oct 14, 1983 */
|
|
146
|
+
const DATE_MED = {
|
|
147
|
+
year: n,
|
|
148
|
+
month: s,
|
|
149
|
+
day: n
|
|
150
|
+
};
|
|
151
|
+
/** Fri, Oct 14, 1983 */
|
|
152
|
+
const DATE_MED_WITH_WEEKDAY = {
|
|
153
|
+
year: n,
|
|
154
|
+
month: s,
|
|
155
|
+
day: n,
|
|
156
|
+
weekday: s
|
|
157
|
+
};
|
|
158
|
+
/** October 14, 1983 */
|
|
159
|
+
const DATE_FULL = {
|
|
160
|
+
year: n,
|
|
161
|
+
month: l,
|
|
162
|
+
day: n
|
|
163
|
+
};
|
|
164
|
+
/** Tuesday, October 14, 1983 */
|
|
165
|
+
const DATE_HUGE = {
|
|
166
|
+
year: n,
|
|
167
|
+
month: l,
|
|
168
|
+
day: n,
|
|
169
|
+
weekday: l
|
|
170
|
+
};
|
|
171
|
+
/** 09:30 AM */
|
|
172
|
+
const TIME_SIMPLE = {
|
|
173
|
+
hour: n,
|
|
174
|
+
minute: n
|
|
175
|
+
};
|
|
176
|
+
/** 09:30:23 AM */
|
|
177
|
+
const TIME_WITH_SECONDS = {
|
|
178
|
+
hour: n,
|
|
179
|
+
minute: n,
|
|
180
|
+
second: n
|
|
181
|
+
};
|
|
182
|
+
/** 09:30:23 AM EDT */
|
|
183
|
+
const TIME_WITH_SHORT_OFFSET = {
|
|
184
|
+
hour: n,
|
|
185
|
+
minute: n,
|
|
186
|
+
second: n,
|
|
187
|
+
timeZoneName: s
|
|
188
|
+
};
|
|
189
|
+
/** 09:30:23 AM Eastern Daylight Time */
|
|
190
|
+
const TIME_WITH_LONG_OFFSET = {
|
|
191
|
+
hour: n,
|
|
192
|
+
minute: n,
|
|
193
|
+
second: n,
|
|
194
|
+
timeZoneName: l
|
|
195
|
+
};
|
|
196
|
+
/** 09:30 */
|
|
197
|
+
const TIME_24_SIMPLE = {
|
|
198
|
+
hour: n,
|
|
199
|
+
minute: n,
|
|
200
|
+
hourCycle: 'h23'
|
|
201
|
+
};
|
|
202
|
+
/** 09:30:23 */
|
|
203
|
+
const TIME_24_WITH_SECONDS = {
|
|
204
|
+
hour: n,
|
|
205
|
+
minute: n,
|
|
206
|
+
second: n,
|
|
207
|
+
hourCycle: 'h23'
|
|
208
|
+
};
|
|
209
|
+
/** 09:30:23 EDT */
|
|
210
|
+
const TIME_24_WITH_SHORT_OFFSET = {
|
|
211
|
+
hour: n,
|
|
212
|
+
minute: n,
|
|
213
|
+
second: n,
|
|
214
|
+
hourCycle: 'h23',
|
|
215
|
+
timeZoneName: s
|
|
216
|
+
};
|
|
217
|
+
/** 09:30:23 Eastern Daylight Time */
|
|
218
|
+
const TIME_24_WITH_LONG_OFFSET = {
|
|
219
|
+
hour: n,
|
|
220
|
+
minute: n,
|
|
221
|
+
second: n,
|
|
222
|
+
hourCycle: 'h23',
|
|
223
|
+
timeZoneName: l
|
|
224
|
+
};
|
|
225
|
+
/** 10/14/1983, 9:30 AM */
|
|
226
|
+
const DATETIME_SHORT = {
|
|
227
|
+
year: n,
|
|
228
|
+
month: n,
|
|
229
|
+
day: n,
|
|
230
|
+
hour: n,
|
|
231
|
+
minute: n
|
|
232
|
+
};
|
|
233
|
+
/** 10/14/1983, 9:30:33 AM */
|
|
234
|
+
const DATETIME_SHORT_WITH_SECONDS = {
|
|
235
|
+
year: n,
|
|
236
|
+
month: n,
|
|
237
|
+
day: n,
|
|
238
|
+
hour: n,
|
|
239
|
+
minute: n,
|
|
240
|
+
second: n
|
|
241
|
+
};
|
|
242
|
+
/** Oct 14, 1983, 9:30 AM */
|
|
243
|
+
const DATETIME_MED = {
|
|
244
|
+
year: n,
|
|
245
|
+
month: s,
|
|
246
|
+
day: n,
|
|
247
|
+
hour: n,
|
|
248
|
+
minute: n
|
|
249
|
+
};
|
|
250
|
+
/** Oct 14, 1983, 9:30:33 AM */
|
|
251
|
+
const DATETIME_MED_WITH_SECONDS = {
|
|
252
|
+
year: n,
|
|
253
|
+
month: s,
|
|
254
|
+
day: n,
|
|
255
|
+
hour: n,
|
|
256
|
+
minute: n,
|
|
257
|
+
second: n
|
|
258
|
+
};
|
|
259
|
+
/** Fri, 14 Oct 1983, 9:30 AM */
|
|
260
|
+
const DATETIME_MED_WITH_WEEKDAY = {
|
|
261
|
+
year: n,
|
|
262
|
+
month: s,
|
|
263
|
+
day: n,
|
|
264
|
+
weekday: s,
|
|
265
|
+
hour: n,
|
|
266
|
+
minute: n
|
|
267
|
+
};
|
|
268
|
+
/** October 14, 1983, 9:30 AM EDT */
|
|
269
|
+
const DATETIME_FULL = {
|
|
270
|
+
year: n,
|
|
271
|
+
month: l,
|
|
272
|
+
day: n,
|
|
273
|
+
hour: n,
|
|
274
|
+
minute: n,
|
|
275
|
+
timeZoneName: s
|
|
276
|
+
};
|
|
277
|
+
/** October 14, 1983, 9:30:33 AM EDT */
|
|
278
|
+
const DATETIME_FULL_WITH_SECONDS = {
|
|
279
|
+
year: n,
|
|
280
|
+
month: l,
|
|
281
|
+
day: n,
|
|
282
|
+
hour: n,
|
|
283
|
+
minute: n,
|
|
284
|
+
second: n,
|
|
285
|
+
timeZoneName: s
|
|
286
|
+
};
|
|
287
|
+
/** Friday, October 14, 1983, 9:30 AM Eastern Daylight Time */
|
|
288
|
+
const DATETIME_HUGE = {
|
|
289
|
+
year: n,
|
|
290
|
+
month: l,
|
|
291
|
+
day: n,
|
|
292
|
+
weekday: l,
|
|
293
|
+
hour: n,
|
|
294
|
+
minute: n,
|
|
295
|
+
timeZoneName: l
|
|
296
|
+
};
|
|
297
|
+
/** Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time */
|
|
298
|
+
const DATETIME_HUGE_WITH_SECONDS = {
|
|
299
|
+
year: n,
|
|
300
|
+
month: l,
|
|
301
|
+
day: n,
|
|
302
|
+
weekday: l,
|
|
303
|
+
hour: n,
|
|
304
|
+
minute: n,
|
|
305
|
+
second: n,
|
|
306
|
+
timeZoneName: l
|
|
307
|
+
};
|