@valkyriestudios/utils 12.23.0 → 12.25.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 CHANGED
@@ -30,7 +30,7 @@ isNotEmptyArray([]); // FALSE
30
30
  isNotEmptyArray([0, 1, 2]); // TRUE
31
31
  ```
32
32
 
33
- ### array/mapKey(val:Record[], key:string, opts:object={})
33
+ ### array/mapKey(val:Record[], key:string, opts?:{merge?:boolean;filter_fn?:(el:T) => boolean})
34
34
  Map a non-primitive object array into an object map by key
35
35
  ```typescript
36
36
  import mapKey from '@valkyriestudios/utils/array/mapKey';
@@ -39,9 +39,7 @@ mapKey([
39
39
  {uid: 15, name: 'Jonas'},
40
40
  {uid: 87, name: 'Josh'},
41
41
  ], 'uid');
42
-
43
- output:
44
-
42
+ /* Expected output: */
45
43
  {
46
44
  12: {uid: 12, name: 'Peter'},
47
45
  15: {uid: 15, name: 'Jonas'},
@@ -64,9 +62,7 @@ mapKey([
64
62
  new Date(),
65
63
  {uid: 87, name: 'Josh'},
66
64
  ], 'uid');
67
-
68
- output:
69
-
65
+ /* Expected output: */
70
66
  {
71
67
  12: {uid: 12, name: 'Peter'},
72
68
  15: {uid: 15, name: 'Jonas'},
@@ -92,9 +88,7 @@ mapKey([
92
88
  {uid: 87, name: 'Josh'},
93
89
  {uid: 12, name: 'Farah'},
94
90
  ], 'uid', {merge: true})
95
-
96
- output:
97
-
91
+ /* Expected output: */
98
92
  {
99
93
  12: {uid: 12, name: 'Farah'},
100
94
  15: {uid: 15, name: 'Bob', dob: '2022-02-07'},
@@ -102,6 +96,24 @@ output:
102
96
  }
103
97
  ```
104
98
 
99
+ allows filtering out objects with a custom filter_fn:
100
+ ```typescript
101
+ import mapKey from '@valkyriestudios/utils/array/mapKey';
102
+ mapKey([
103
+ {uid: 12, name: 'Peter', isActive: true},
104
+ {uid: 15, name: 'Jonas', dob: '2022-02-07', isActive: true},
105
+ {uid: 15, name: 'Bob', isActive: false},
106
+ {name: 'Alana', isActive: true},
107
+ {uid: 87, name: 'Josh', isActive: false},
108
+ {uid: 12, name: 'Farah', isActive: false},
109
+ ], 'uid', {merge: true})
110
+ /* Expected output: */
111
+ {
112
+ 12: {uid: 12, name: 'Peter', isActive: true},
113
+ 15: {uid: 15, name: 'Jonas', dob: '2022-02-07'},
114
+ }
115
+ ```
116
+
105
117
  ### array/mapFn(val:Record[], key:Function, opts:object={})
106
118
  Same behavior as mapKey but instead of a key, a function is passed to generate your own key. Eg:
107
119
 
@@ -112,9 +124,7 @@ mapFn([
112
124
  {uid: 15, name: 'Jonas'},
113
125
  {uid: 87, name: 'Josh'},
114
126
  ], el => el.uid)
115
-
116
- output:
117
-
127
+ /* Expected output: */
118
128
  {
119
129
  12: {uid: 12, name: 'Peter'},
120
130
  15: {uid: 15, name: 'Jonas'},
@@ -124,7 +134,7 @@ output:
124
134
 
125
135
  options are the same as the mapKey function
126
136
 
127
- ### array/mapPrimitive(val:any[], opts:object={valtrim:false,keyround:false,valround:false})
137
+ ### array/mapPrimitive(val:any[], opts?:{valtrim:false;keyround:false;valround:false;filter_fn:(el)=>boolean})
128
138
  Map an array of primitives (number/string)
129
139
  ```typescript
130
140
  import mapPrimitive from '@valkyriestudios/utils/array/mapPrimitive';
@@ -133,6 +143,12 @@ mapPrimitive(['hello', 'hello', 'foo', 'bar']); // {hello: 'hello', foo: 'foo',
133
143
  mapPrimitive(['hello', ' hello', 'foo', ' foo'], {valtrim: true}); // {hello: 'hello', foo: 'foo'}
134
144
  ```
135
145
 
146
+ Allows filtering out unwanted values:
147
+ ```typescript
148
+ import mapPrimitive from '@valkyriestudios/utils/array/mapPrimitive';
149
+ mapPrimitive([1,2,'bla', 3, false], {filter_fn: isNumber}); // {1: 1, 2: 2, 3: 3}
150
+ ```
151
+
136
152
  ### array/groupBy(val:Record[], handler:Function|string)
137
153
  Return a grouped object from an array. This function **will automatically filter out any non/empty objects**.
138
154
 
@@ -428,7 +444,15 @@ Available tokens for usage in spec:
428
444
  | `Z` | Zone, does not allow full zone names, only Z or offsets | `Z` `+02:00` |
429
445
  | `ISO` | Check for full iso date format, take note this enforces milliseconds as a requirement | 2024-02-03T10:28:30.000Z |
430
446
 
431
- Note: The `ISO` token is a shorthand for `YYYY-MM-DDTHH:mm:ss.SSSZ`
447
+ Allows for marking certain portions as optional by wrapping in `{...}`:
448
+ ```typescript
449
+ import isFormat from '@valkyriestudios/utils/date/isFormat';
450
+ isFormat('2024-02-07', 'YYYY-MM-DD{THH:mm:ss}'); // true
451
+ isFormat('2024-02-07T14:50', 'YYYY-MM-DD{THH:mm:ss}'); // false, optional part passed but invalid
452
+ isFormat('2024-02-07T14:50:30', 'YYYY-MM-DD{THH:mm:ss}'); // true
453
+ ```
454
+
455
+ Note: The `ISO` token is a shorthand for `YYYY-MM-DDTHH:mm:ss{.SSS}Z`
432
456
  Note: You can escape characters by surrounding them with `[...]` in your spec, eg: `YYYY-[Q]Q` would check for example `2024-Q1`
433
457
 
434
458
  ### date/diff(val_a:Date, val_b:Date, key:string)
@@ -787,7 +811,7 @@ isFormData(new FormData()); // TRUE
787
811
  isFormData({hi: 'there'}); // FALSE
788
812
  ```
789
813
 
790
- ### formdata/toObject(val:FormData, {raw?:string[]|true;single?:string[]} = {})
814
+ ### formdata/toObject(val:FormData, {raw?:string[]|true;single?:string[];normalize_bool?:boolean;normalize_date?:bool;normalize_number?:bool} = {})
791
815
  Converts an instance of FormData to an object
792
816
  ```typescript
793
817
  import toObject from '@valkyriestudios/utils/formdata/toObject';
@@ -800,7 +824,7 @@ form.append('emptyField', '');
800
824
  toObject(form); // {name: 'Alice', hobbies: ['reading', 'writing'], emptyField: ''}
801
825
  ```
802
826
 
803
- Automatically converts strings to numbers and booleans, and nests objects/arrays based on key structures:
827
+ Automatically converts strings to numbers, dates, booleans and nests objects/arrays based on key structures:
804
828
  ```typescript
805
829
  const form = new FormData();
806
830
  form.append('user[0].name', 'Alice');
@@ -853,6 +877,24 @@ formData.append('action', 'reset');
853
877
  toObject(formData, { single: ['status', 'action'] }) /* {status: 'inactive', action: 'reset'} */
854
878
  ```
855
879
 
880
+ Allows configuring what types of data to normalize:
881
+ ```typescript
882
+ const form = new FormData();
883
+ form.append('pincode', '0123');
884
+ form.append('enabled', 'false');
885
+ form.append('config.isGood', 'true');
886
+ form.append('config.amount', ' 50 ');
887
+
888
+ toObject(form, {raw: ['pincode'], normalize_bool: false}); /* {
889
+ pincode: '0123',
890
+ enabled: 'false',
891
+ config: {
892
+ isGood: 'true',
893
+ amount: 50,
894
+ },
895
+ } */
896
+ ```
897
+
856
898
  ### hash/guid()
857
899
  Generate a unique identifier (guid) according to RFC4122
858
900
  ```typescript
package/array/join.js CHANGED
@@ -4,7 +4,7 @@ exports.join = join;
4
4
  exports.default = join;
5
5
  const round_1 = require("../number/round");
6
6
  const isIntegerAboveOrEqual_1 = require("../number/isIntegerAboveOrEqual");
7
- const SPACE_RGX = /(\s){2,}/g;
7
+ const SPACE_RGX = /(\s)+/g;
8
8
  function join(val, opts) {
9
9
  if (!Array.isArray(val) || !val.length)
10
10
  return '';
@@ -17,9 +17,12 @@ function join(val, opts) {
17
17
  let hasVal = false;
18
18
  for (let i = 0; i < val.length; i++) {
19
19
  const el = val[i];
20
- if (typeof el === 'string' && el.trim().length) {
21
- const trimmed = VALTRIM ? el.trim() : el;
22
- result = result + (hasVal ? DELIM : '') + (INNERTRIM ? trimmed.replace(SPACE_RGX, ' ') : trimmed);
20
+ if (typeof el === 'string') {
21
+ const trimmed = el.trim();
22
+ if (!trimmed)
23
+ continue;
24
+ const n_el = VALTRIM ? trimmed : el;
25
+ result = result + (hasVal ? DELIM : '') + (INNERTRIM ? n_el.replace(SPACE_RGX, ' ') : n_el);
23
26
  hasVal = true;
24
27
  }
25
28
  else if (Number.isFinite(el)) {
package/array/mapFn.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- interface mapOptions {
1
+ type MapOptions = {
2
2
  /**
3
3
  * Allow merging existing keys or not, if not keys will be overriden if they exist
4
4
  * (default=false)
@@ -11,8 +11,8 @@ interface mapOptions {
11
11
  * {12: {uid: 12, b: 'ho'}}
12
12
  */
13
13
  merge?: boolean;
14
- }
15
- type mapFn<T extends Record<string, any>> = (entry: T) => (string | number | boolean);
14
+ };
15
+ type MapFn<T extends Record<string, any>> = (entry: T) => (string | number | boolean);
16
16
  /**
17
17
  * Map an object array into a kv-object through a function that generates a key. Returning a non-string,
18
18
  * non-numeric value from the function (eg: false) will filter out the object.
@@ -23,10 +23,10 @@ type mapFn<T extends Record<string, any>> = (entry: T) => (string | number | boo
23
23
  * {12: {uid: 12, name: 'Peter'}, 15: {uid: 15, name: 'Jonas'}}
24
24
  *
25
25
  * @param {Record<string, any>[]} val - Array to map
26
- * @param {mapFn} fn - Handler function which is run for each of the objects and should return a string or number
27
- * @param {mapOptions?} opts - Options object to override built-in defaults
26
+ * @param {MapFn} fn - Handler function which is run for each of the objects and should return a string or number
27
+ * @param {MapOptions?} opts - Options object to override built-in defaults
28
28
  *
29
29
  * @returns {Record<string, T>} KV-Map object
30
30
  */
31
- declare function mapFn<T extends Record<string, any>>(arr: T[], fn: mapFn<T>, opts?: mapOptions): Record<string, T>;
31
+ declare function mapFn<T extends Record<string, any>>(arr: T[], fn: MapFn<T>, opts?: MapOptions): Record<string, T>;
32
32
  export { mapFn, mapFn as default };
package/array/mapFn.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapFn = mapFn;
4
4
  exports.default = mapFn;
5
+ const merge_1 = require("../object/merge");
5
6
  function mapFn(arr, fn, opts) {
6
7
  if ((!Array.isArray(arr) || !arr.length) ||
7
8
  typeof fn !== 'function')
@@ -17,7 +18,7 @@ function mapFn(arr, fn, opts) {
17
18
  if (!Number.isFinite(hash) && !(typeof hash === 'string' && hash.trim().length))
18
19
  continue;
19
20
  hash = hash + '';
20
- map[hash] = MERGE && map[hash] !== undefined ? { ...map[hash], ...el } : el;
21
+ map[hash] = (MERGE && hash in map ? (0, merge_1.merge)(map[hash], el, { union: true }) : el);
21
22
  }
22
23
  return map;
23
24
  }
package/array/mapKey.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- interface mapOptions {
1
+ type MapOptions<T> = {
2
2
  /**
3
3
  * Allow merging existing keys or not, if not keys will be overriden if they exist
4
4
  * (default=false)
@@ -11,7 +11,11 @@ interface mapOptions {
11
11
  * {12: {uid: 12, b: 'ho'}}
12
12
  */
13
13
  merge?: boolean;
14
- }
14
+ /**
15
+ * Pass a custom filter function which will be run in O(n) while iterating
16
+ */
17
+ filter_fn?: (el: T) => boolean;
18
+ };
15
19
  /**
16
20
  * Map an object array into a kv-object by passing a common key that exists on the objects. Objects for
17
21
  * which the key doesn't exist will be filtered out automatically
@@ -23,9 +27,9 @@ interface mapOptions {
23
27
  *
24
28
  * @param {Record<string,any>[]} val - Array to map
25
29
  * @param {string} key - Key to map by
26
- * @param {mapOptions?} opts - Options object to override built-in defaults
30
+ * @param {MapOptions?} opts - Options object to override built-in defaults
27
31
  *
28
32
  * @returns {Record<string, T>} KV-Map object
29
33
  */
30
- declare function mapKey<T extends Record<string, any>>(arr: T[], key: string, opts?: mapOptions): Record<string, T>;
34
+ declare function mapKey<T extends Record<string, any>>(arr: T[], key: string, opts?: MapOptions<T>): Record<string, T>;
31
35
  export { mapKey, mapKey as default };
package/array/mapKey.js CHANGED
@@ -2,15 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapKey = mapKey;
4
4
  exports.default = mapKey;
5
+ const merge_1 = require("../object/merge");
5
6
  function mapKey(arr, key, opts) {
6
7
  if (!Array.isArray(arr) || typeof key !== 'string')
7
8
  return {};
8
- const key_s = key.trim();
9
- if (!key_s.length)
10
- return {};
11
9
  const len = arr.length;
12
10
  if (!len)
13
11
  return {};
12
+ const key_s = key.trim();
13
+ if (!key_s.length)
14
+ return {};
15
+ const FILTER_FN = opts?.filter_fn;
14
16
  const MERGE = opts?.merge === true;
15
17
  const map = {};
16
18
  for (let i = 0; i < len; i++) {
@@ -18,7 +20,9 @@ function mapKey(arr, key, opts) {
18
20
  const el_key = el?.[key_s];
19
21
  if (el_key === undefined)
20
22
  continue;
21
- map[el_key] = MERGE && el_key in map ? { ...map[el_key], ...el } : el;
23
+ if (FILTER_FN && !FILTER_FN(el))
24
+ continue;
25
+ map[el_key] = (MERGE && el_key in map ? (0, merge_1.merge)(map[el_key], el, { union: true }) : el);
22
26
  }
23
27
  return map;
24
28
  }
@@ -1,4 +1,4 @@
1
- interface mapOptions {
1
+ type MapOptions = {
2
2
  /**
3
3
  * Automatically trim all string values
4
4
  * (default=false)
@@ -18,7 +18,11 @@ interface mapOptions {
18
18
  * eg: mapPrimitive([5.432, 5.4, 5.43, 4.2, 4.1], {keyround: true}) -> {5: 5.43, 4: 4.1}
19
19
  */
20
20
  keyround?: boolean;
21
- }
21
+ /**
22
+ * Pass a custom filter function which will be run in O(n) while iterating
23
+ */
24
+ filter_fn?: (el: unknown) => boolean;
25
+ };
22
26
  type mapReturn = Record<string, string | number>;
23
27
  /**
24
28
  * Map an array of primitive values (numbers/strings) into a kv-object
@@ -30,7 +34,7 @@ type mapReturn = Record<string, string | number>;
30
34
  * {hello: 'hello', foo: 'foo', bar: 'bar'}
31
35
  *
32
36
  * @param {unknown[]} val - Array to map
33
- * @param {mapOptions?} opts - Options object to override built-in defaults
37
+ * @param {MapOptions?} opts - Options object to override built-in defaults
34
38
  */
35
- declare function mapPrimitive(arr: unknown[], opts?: mapOptions): mapReturn;
39
+ declare function mapPrimitive(arr: unknown[], opts?: MapOptions): mapReturn;
36
40
  export { mapPrimitive, mapPrimitive as default };
@@ -10,23 +10,26 @@ function mapPrimitive(arr, opts = {}) {
10
10
  const VALTRIM = opts?.valtrim === true;
11
11
  const VALROUND = (0, isIntegerAboveOrEqual_1.isIntegerAboveOrEqual)(opts?.valround, 0)
12
12
  ? opts?.valround
13
- : opts?.valround === true;
13
+ : opts?.valround === true
14
+ ? 0
15
+ : null;
14
16
  const KEYROUND = opts?.keyround === true;
17
+ const FILTER_FN = opts?.filter_fn;
15
18
  const map = {};
16
19
  for (let i = 0; i < arr.length; i++) {
17
20
  const el = arr[i];
21
+ if (FILTER_FN && !FILTER_FN(el))
22
+ continue;
18
23
  if (typeof el === 'string') {
19
24
  const trimmed = el.trim();
20
- if (!trimmed.length)
25
+ if (!trimmed)
21
26
  continue;
22
27
  map[trimmed] = VALTRIM ? trimmed : el;
23
28
  }
24
- else if (typeof el === 'number' && Number.isFinite(el)) {
25
- map[`${KEYROUND ? Math.round(el) : el}`] = VALROUND === false
29
+ else if (Number.isFinite(el)) {
30
+ map[`${KEYROUND ? Math.round(el) : el}`] = VALROUND === null
26
31
  ? el
27
- : VALROUND === true
28
- ? Math.round(el)
29
- : (0, round_1.round)(el, VALROUND);
32
+ : (0, round_1.round)(el, VALROUND);
30
33
  }
31
34
  }
32
35
  return map;
package/date/addUTC.d.ts CHANGED
@@ -2,9 +2,9 @@ export type AddUTCKey = 'years' | 'year' | 'months' | 'month' | 'days' | 'day' |
2
2
  /**
3
3
  * Adds the provided amount of a specific key to the provided date
4
4
  *
5
- * @param {Date} val - Date to set to end of
5
+ * @param {Date|string} val - Date to set to end of
6
6
  * @param {number} amount - (default=0) Amount of key to add
7
7
  * @param {AddUTCKey} key - (default='millisecond') Key to set
8
8
  */
9
- declare function addUTC(val: Date, amt?: number, key?: AddUTCKey): Date;
9
+ declare function addUTC(val: Date | string, amt?: number, key?: AddUTCKey): Date;
10
10
  export { addUTC, addUTC as default };
package/date/addUTC.js CHANGED
@@ -2,19 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addUTC = addUTC;
4
4
  exports.default = addUTC;
5
- const is_1 = require("./is");
5
+ const convertToDate_1 = require("./convertToDate");
6
6
  function addUTC(val, amt = 0, key = 'millisecond') {
7
- if (!(0, is_1.isDate)(val))
8
- throw new TypeError('addUTC requires a date object');
9
7
  if (!Number.isInteger(amt))
10
8
  throw new TypeError('Amount needs to be an integer');
11
- const year = val.getUTCFullYear();
12
- const month = val.getUTCMonth();
13
- const date = val.getUTCDate();
14
- const hour = val.getUTCHours();
15
- const min = val.getUTCMinutes();
16
- const sec = val.getUTCSeconds();
17
- const ms = val.getUTCMilliseconds();
9
+ const n_val = (0, convertToDate_1.convertToDate)(val);
10
+ if (n_val === null)
11
+ throw new TypeError('addUTC requires a date object');
12
+ const year = n_val.getUTCFullYear();
13
+ const month = n_val.getUTCMonth();
14
+ const date = n_val.getUTCDate();
15
+ const hour = n_val.getUTCHours();
16
+ const min = n_val.getUTCMinutes();
17
+ const sec = n_val.getUTCSeconds();
18
+ const ms = n_val.getUTCMilliseconds();
18
19
  switch (key) {
19
20
  case 'years':
20
21
  case 'year':
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Convert a value to a Date object if possible, handles Date objects and strings
3
+ *
4
+ * @param {Date|string} val - Value to convert
5
+ */
6
+ declare function convertToDate(val: Date | string | number): Date | null;
7
+ export { convertToDate, convertToDate as default };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToDate = convertToDate;
4
+ exports.default = convertToDate;
5
+ const is_1 = require("./is");
6
+ function convertToDate(val) {
7
+ if ((0, is_1.isDate)(val)) {
8
+ return val;
9
+ }
10
+ else if (typeof val === 'string') {
11
+ const date = new Date(val);
12
+ return Number.isNaN(date.getTime()) ? null : date;
13
+ }
14
+ return null;
15
+ }
package/date/diff.d.ts CHANGED
@@ -2,9 +2,9 @@ export type DiffKey = 'week' | 'weeks' | 'day' | 'days' | 'hour' | 'hours' | 'mi
2
2
  /**
3
3
  * Compute the diff between two dates in the provided key
4
4
  *
5
- * @param {Date} val_a - Date to diff against
6
- * @param {Date} val_b - Date to diff with
5
+ * @param {Date|string} val_a - Date to diff against
6
+ * @param {Date|string} val_b - Date to diff with
7
7
  * @param {DiffKey} key - (default='millisecond') Key to diff in
8
8
  */
9
- declare function diff(val_a: Date, val_b: Date, key?: DiffKey): number;
9
+ declare function diff(val_a: Date | string, val_b: Date | string, key?: DiffKey): number;
10
10
  export { diff, diff as default };
package/date/diff.js CHANGED
@@ -2,17 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.diff = diff;
4
4
  exports.default = diff;
5
- const is_1 = require("./is");
5
+ const convertToDate_1 = require("./convertToDate");
6
6
  const SECOND_IN_MILLISECONDS = 1000;
7
7
  const MINUTE_IN_MILLISECONDS = SECOND_IN_MILLISECONDS * 60;
8
8
  const HOUR_IN_MILLISECONDS = MINUTE_IN_MILLISECONDS * 60;
9
9
  const DAY_IN_MILLISECONDS = HOUR_IN_MILLISECONDS * 24;
10
10
  const WEEK_IN_MILLISECONDS = DAY_IN_MILLISECONDS * 7;
11
11
  function diff(val_a, val_b, key = 'millisecond') {
12
- if (!(0, is_1.isDate)(val_a) ||
13
- !(0, is_1.isDate)(val_b))
12
+ const n_val_a = (0, convertToDate_1.convertToDate)(val_a);
13
+ const n_val_b = (0, convertToDate_1.convertToDate)(val_b);
14
+ if (n_val_a === null ||
15
+ n_val_b === null)
14
16
  throw new TypeError('Diff requires date objects for both values');
15
- const diff_in_ms = val_a.valueOf() - val_b.valueOf();
17
+ const diff_in_ms = n_val_a.valueOf() - n_val_b.valueOf();
16
18
  switch (key) {
17
19
  case 'week':
18
20
  case 'weeks':
@@ -2,8 +2,8 @@ export type EndOfUTCKey = 'year' | 'quarter' | 'month' | 'week' | 'week_sun' | '
2
2
  /**
3
3
  * Sets the provided date to end of UTC of provided key
4
4
  *
5
- * @param {Date} val - Date to set to end of
5
+ * @param {Date|string} val - Date to set to end of
6
6
  * @param {EndOfUTCKey} key - (default='millisecond') Key to set
7
7
  */
8
- declare function endOfUTC(val: Date, key?: EndOfUTCKey): Date;
8
+ declare function endOfUTC(val: Date | string, key?: EndOfUTCKey): Date;
9
9
  export { endOfUTC, endOfUTC as default };
package/date/endOfUTC.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.endOfUTC = endOfUTC;
4
4
  exports.default = endOfUTC;
5
- const is_1 = require("./is");
5
+ const convertToDate_1 = require("./convertToDate");
6
6
  const WEEK_END = new Map([
7
7
  ['week', 0],
8
8
  ['week_sun', 6],
@@ -14,17 +14,19 @@ const WEEK_END = new Map([
14
14
  ['week_sat', 5],
15
15
  ]);
16
16
  function endOfUTC(val, key = 'millisecond') {
17
- if (!(0, is_1.isDate)(val))
17
+ const n_val = (0, convertToDate_1.convertToDate)(val);
18
+ if (n_val === null)
18
19
  throw new TypeError('endOfUTC requires a date object');
20
+ const year = n_val.getUTCFullYear();
19
21
  switch (key) {
20
22
  case 'year':
21
- return new Date(Date.UTC(val.getUTCFullYear(), 11, 31, 23, 59, 59, 999));
23
+ return new Date(Date.UTC(year, 11, 31, 23, 59, 59, 999));
22
24
  case 'quarter': {
23
- const UTC_MONTH = val.getUTCMonth();
24
- return new Date(Date.UTC(val.getUTCFullYear(), (UTC_MONTH - (UTC_MONTH % 3)) + 3, 0, 23, 59, 59, 999));
25
+ const UTC_MONTH = n_val.getUTCMonth();
26
+ return new Date(Date.UTC(year, (UTC_MONTH - (UTC_MONTH % 3)) + 3, 0, 23, 59, 59, 999));
25
27
  }
26
28
  case 'month':
27
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth() + 1, 0, 23, 59, 59, 999));
29
+ return new Date(Date.UTC(year, n_val.getUTCMonth() + 1, 0, 23, 59, 59, 999));
28
30
  case 'week':
29
31
  case 'week_sun':
30
32
  case 'week_mon':
@@ -33,19 +35,19 @@ function endOfUTC(val, key = 'millisecond') {
33
35
  case 'week_thu':
34
36
  case 'week_fri':
35
37
  case 'week_sat': {
36
- const UTC_DAY = val.getUTCDay();
38
+ const UTC_DAY = n_val.getUTCDay();
37
39
  const UTC_EOD = WEEK_END.get(key);
38
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate() + (UTC_DAY <= UTC_EOD ? UTC_EOD - UTC_DAY : (7 - UTC_DAY) + UTC_EOD), 23, 59, 59, 999));
40
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate() + (UTC_DAY <= UTC_EOD ? UTC_EOD - UTC_DAY : (7 - UTC_DAY) + UTC_EOD), 23, 59, 59, 999));
39
41
  }
40
42
  case 'day':
41
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), 23, 59, 59, 999));
43
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), 23, 59, 59, 999));
42
44
  case 'hour':
43
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), val.getUTCHours(), 59, 59, 999));
45
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), 59, 59, 999));
44
46
  case 'minute':
45
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), val.getUTCHours(), val.getUTCMinutes(), 59, 999));
47
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes(), 59, 999));
46
48
  case 'second':
47
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), val.getUTCHours(), val.getUTCMinutes(), val.getUTCSeconds(), 999));
49
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes(), n_val.getUTCSeconds(), 999));
48
50
  default:
49
- return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), val.getUTCHours(), val.getUTCMinutes(), val.getUTCSeconds(), val.getUTCMilliseconds()));
51
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes(), n_val.getUTCSeconds(), n_val.getUTCMilliseconds()));
50
52
  }
51
53
  }
package/date/format.d.ts CHANGED
@@ -7,14 +7,14 @@ export type WEEK_START = keyof typeof WEEK_STARTS;
7
7
  /**
8
8
  * Formats the provided date according to a specific spec
9
9
  *
10
- * @param {Date} val - Date to format
10
+ * @param {Date|string} val - Date to format
11
11
  * @param {string} spec - Spec to format the date to
12
12
  * @param {string} locale - Locale to format the date in (only used in certain tokens such as dddd and MMMM)
13
13
  * @param {string} zone - (default=current timezone) Pass the timezone to convert into. If not passed no conversion will happen
14
14
  * @param {string} sow - (default='mon') Start of week (only useful when working with the 'W' and 'w' tokens for week numbers
15
15
  * @throws {TypeError} When provided invalid payload
16
16
  */
17
- declare function format(val: Date, spec: string, locale?: string, zone?: string, sow?: WEEK_START): string;
17
+ declare function format(val: Date | string, spec: string, locale?: string, zone?: string, sow?: WEEK_START): string;
18
18
  declare namespace format {
19
19
  var getLocale: () => string;
20
20
  var setLocale: (locale: string) => void;
package/date/format.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.format = format;
4
4
  exports.default = format;
5
- const is_1 = require("./is");
5
+ const convertToDate_1 = require("./convertToDate");
6
6
  const WEEK_STARTS = {
7
7
  mon: 'mon',
8
8
  sun: 'sun',
@@ -14,7 +14,7 @@ let DEFAULT_SOW = 'mon';
14
14
  try {
15
15
  DEFAULT_TZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
16
16
  }
17
- catch (err) {
17
+ catch {
18
18
  }
19
19
  finally {
20
20
  if (typeof DEFAULT_TZ !== 'string')
@@ -25,17 +25,17 @@ const intl_formatters = Object.create(null);
25
25
  const spec_cache = Object.create(null);
26
26
  const zone_offset_cache = Object.create(null);
27
27
  function WeekNr(d, sow) {
28
- const date = new Date(d.valueOf());
29
28
  switch (sow) {
30
29
  case 'sun':
31
30
  case 'sat': {
32
31
  const OFFSET = sow === 'sat' ? 1 : 0;
33
- const jan1 = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
34
- const near = new Date(date.getTime() - (((date.getDay() + OFFSET) % 7) * 86400000));
32
+ const jan1 = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
33
+ const near = new Date(d.getTime() - (((d.getDay() + OFFSET) % 7) * 86400000));
35
34
  const first = new Date(jan1.getTime() - (((jan1.getDay() + OFFSET) % 7) * 86400000));
36
35
  return 1 + Math.floor((near.valueOf() - first.valueOf()) / 604800000);
37
36
  }
38
37
  default: {
38
+ const date = new Date(d.valueOf());
39
39
  date.setDate(date.getDate() - ((d.getDay() + 6) % 7) + 3);
40
40
  const date_thu = date.valueOf();
41
41
  date.setMonth(0, 1);
@@ -59,9 +59,9 @@ function toZone(d, zone) {
59
59
  return new Date(time + zone_offset_cache[ckey]);
60
60
  let zone_time = null;
61
61
  try {
62
- zone_time = new Date(d.toLocaleString(DEFAULT_LOCALE, { timeZone: zone })).getTime();
62
+ zone_time = new Date(d.toLocaleString(DEFAULT_LOCALE, { timeZone: zone })).getTime() + d.getMilliseconds();
63
63
  }
64
- catch (err) {
64
+ catch {
65
65
  throw new Error(`format: Invalid zone passed - ${zone}`);
66
66
  }
67
67
  const offset = zone_time - time;
@@ -76,7 +76,7 @@ function runIntl(loc, token, props, val) {
76
76
  formatter = new Intl.DateTimeFormat(loc, props);
77
77
  intl_formatters[hash] = formatter;
78
78
  }
79
- catch (err) {
79
+ catch {
80
80
  throw new Error(`format: Failed to run conversion for ${token} with locale ${loc}`);
81
81
  }
82
82
  }
@@ -149,7 +149,7 @@ function getSpecChain(spec) {
149
149
  let repl_len = 0;
150
150
  if (base.indexOf('[') >= 0) {
151
151
  base = base.replace(ESCAPE_RGX, match => {
152
- const escape_token = '$R' + repl_len++ + '$';
152
+ const escape_token = '$' + repl_len++ + '$';
153
153
  repl.push([escape_token, match.slice(1, -1)]);
154
154
  return escape_token;
155
155
  });
@@ -176,7 +176,8 @@ function getSpecChain(spec) {
176
176
  return result;
177
177
  }
178
178
  function format(val, spec, locale = DEFAULT_LOCALE, zone = DEFAULT_TZ, sow = DEFAULT_SOW) {
179
- if (!(0, is_1.isDate)(val))
179
+ const n_val = (0, convertToDate_1.convertToDate)(val);
180
+ if (n_val === null)
180
181
  throw new TypeError('format: val must be a Date');
181
182
  if (typeof spec !== 'string')
182
183
  throw new TypeError('format: spec must be a string');
@@ -186,8 +187,8 @@ function format(val, spec, locale = DEFAULT_LOCALE, zone = DEFAULT_TZ, sow = DEF
186
187
  throw new TypeError('format: zone must be a string');
187
188
  const n_spec = getSpecChain(spec);
188
189
  if (!n_spec)
189
- return val.toISOString();
190
- const d = toZone(val, zone);
190
+ return n_val.toISOString();
191
+ const d = toZone(n_val, zone);
191
192
  let base = n_spec.base;
192
193
  const { chain_len, chain, repl_len, repl } = n_spec;
193
194
  for (let i = 0; i < chain_len; i++) {