topkat-utils 1.0.34 → 1.0.37
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/utils.d.ts +34 -91
- package/utils.js +20 -215
- package/utils.js.map +1 -1
- package/utils.ts +36 -258
package/utils.ts
CHANGED
|
@@ -6,6 +6,7 @@ const JSONstringyParse = o => JSON.parse(removeCircularJSONstringify(o));
|
|
|
6
6
|
const removeUndefinedKeys = objFilterUndefinedRecursive;
|
|
7
7
|
|
|
8
8
|
type Color = [number, number, number]
|
|
9
|
+
type ObjectGeneric = { [k: string]: any }
|
|
9
10
|
|
|
10
11
|
type BaseTypes = 'objectId' | 'dateInt6' | 'dateInt' | 'dateInt8' | 'dateInt12' | 'time' | 'humanReadableTimestamp' | 'date' | 'dateObject' | 'array' | 'object' | 'buffer' | 'string' | 'function' | 'boolean' | 'number' | 'bigint' | 'year' | 'email'
|
|
11
12
|
|
|
@@ -36,7 +37,7 @@ function moyenne(array: number[], nbOfDecimals = 2) {
|
|
|
36
37
|
function cln(val, replacerInCaseItIsUndefinNaN = '-') { return ['undefined', undefined, 'indéfini', 'NaN', NaN, Infinity, null].includes(val) ? replacerInCaseItIsUndefinNaN : val; }
|
|
37
38
|
|
|
38
39
|
/** length default 2, shortcut for 1 to 01 */
|
|
39
|
-
function pad(numberOrStr, length = 2) { return ('' + numberOrStr).padStart(length, '0'); }
|
|
40
|
+
function pad(numberOrStr: number | string, length = 2) { return ('' + numberOrStr).padStart(length, '0'); }
|
|
40
41
|
|
|
41
42
|
/** return the number or the closest number of the range
|
|
42
43
|
* * nb min max => returns
|
|
@@ -46,7 +47,7 @@ function pad(numberOrStr, length = 2) { return ('' + numberOrStr).padStart(lengt
|
|
|
46
47
|
*/
|
|
47
48
|
function minMax(nb: number, min: number, max: number) { return Math.max(min, Math.min(nb, max)); }
|
|
48
49
|
|
|
49
|
-
async function tryCatch(callback, onErr: Function = () => { }) {
|
|
50
|
+
async function tryCatch(callback: Function, onErr: Function = () => { }) {
|
|
50
51
|
try {
|
|
51
52
|
return await callback()
|
|
52
53
|
} catch (err) {
|
|
@@ -63,7 +64,7 @@ let lastTs = new Date().getTime();
|
|
|
63
64
|
* @param {string} mode one of ['alphanumeric', 'hexadecimal']
|
|
64
65
|
* NOTE: to generate a mongoDB Random Id, use the params: 24, true, 'hexadecimal'
|
|
65
66
|
*/
|
|
66
|
-
function generateToken(length = 20, unique = true, mode = 'alphanumeric') {
|
|
67
|
+
function generateToken(length = 20, unique = true, mode: 'alphanumeric' | 'hexadecimal' = 'alphanumeric') {
|
|
67
68
|
let charConvNumeric = mode === 'alphanumeric' ? 36 : 16;
|
|
68
69
|
if (unique && length < 8) length = 8;
|
|
69
70
|
let token
|
|
@@ -73,19 +74,21 @@ function generateToken(length = 20, unique = true, mode = 'alphanumeric') {
|
|
|
73
74
|
token = unique ? tokenTs.toString(charConvNumeric) : '';
|
|
74
75
|
while (token.length < length) token += Math.random().toString(charConvNumeric).substr(2, 1); // char alphaNumeric aléatoire
|
|
75
76
|
} while (generatedTokens.includes(token))
|
|
76
|
-
if (lastTs < tokenTs)
|
|
77
|
-
generatedTokens = [] // reset generated token on new timestamp because cannot collide
|
|
78
|
-
}
|
|
77
|
+
if (lastTs < tokenTs) generatedTokens = [] // reset generated token on new timestamp because cannot collide
|
|
79
78
|
generatedTokens.push(token)
|
|
80
79
|
return token;
|
|
81
80
|
}
|
|
82
81
|
|
|
82
|
+
function generateObjectId() {
|
|
83
|
+
return generateToken(24, true, 'hexadecimal')
|
|
84
|
+
}
|
|
85
|
+
|
|
83
86
|
|
|
84
87
|
/** Useful to join differents bits of url with normalizing slashes
|
|
85
88
|
* * urlPathJoin('https://', 'www.kikou.lol/', '/user', '//2//') => https://www.kikou.lol/user/2/
|
|
86
89
|
* * urlPathJoin('http:/', 'kikou.lol') => https://www.kikou.lol
|
|
87
90
|
*/
|
|
88
|
-
function urlPathJoin(...bits) {
|
|
91
|
+
function urlPathJoin(...bits: string[]) {
|
|
89
92
|
return bits.join('/').replace(/\/+/g, '/').replace(/(https?:)\/\/?/, '$1//');
|
|
90
93
|
}
|
|
91
94
|
|
|
@@ -118,15 +121,19 @@ function sortUrlsByDeepnessInArrayOrObject(urlObjOrArr, propInObjectOrIndexInArr
|
|
|
118
121
|
});
|
|
119
122
|
}
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
|
|
125
|
+
type MiniTemplaterOptions = {
|
|
126
|
+
valueWhenNotSet?: string
|
|
127
|
+
regexp?: RegExp
|
|
128
|
+
}
|
|
129
|
+
/** Replace variables in a string like: `Hello {{userName}}!`
|
|
123
130
|
* @param {String} content
|
|
124
131
|
* @param {Object} varz object with key => value === toReplace => replacer
|
|
125
132
|
* @param {Object} options
|
|
126
133
|
* * valueWhenNotSet => replacer for undefined values. Default: ''
|
|
127
134
|
* * regexp => must be 'g' and first capturing group matching the value to replace. Default: /{{\s*([^}]*)\s*}}/g
|
|
128
135
|
*/
|
|
129
|
-
function miniTemplater(content, varz, options) {
|
|
136
|
+
function miniTemplater(content: string, varz: ObjectGeneric, options: MiniTemplaterOptions = {}) {
|
|
130
137
|
options = {
|
|
131
138
|
valueWhenNotSet: '',
|
|
132
139
|
regexp: /{{\s*([^}]*)\s*}}/g,
|
|
@@ -142,7 +149,7 @@ function miniTemplater(content, varz, options) {
|
|
|
142
149
|
* @param {Boolean} isMask default: true; determine the behavior of the function. If is mask, selected fields will not appear in the resulting object. If it's a select, only selected fields will appear.
|
|
143
150
|
* @param {Boolean} deleteKeysInsteadOfReturningAnewObject default:false; modify the existing object instead of creating a new instance
|
|
144
151
|
*/
|
|
145
|
-
function simpleObjectMaskOrSelect(object, maskedOrSelectedFields, isMask = true, deleteKeysInsteadOfReturningAnewObject = false) {
|
|
152
|
+
function simpleObjectMaskOrSelect(object: ObjectGeneric, maskedOrSelectedFields: string[], isMask = true, deleteKeysInsteadOfReturningAnewObject = false) {
|
|
146
153
|
const allKeys = Object.keys(object);
|
|
147
154
|
const keysToMask = allKeys.filter(keyName => {
|
|
148
155
|
if (isMask) return maskedOrSelectedFields.includes(keyName);
|
|
@@ -317,7 +324,7 @@ class dataValidationUtilErrorHandler extends Error {
|
|
|
317
324
|
* @param {Object} obj object to test against
|
|
318
325
|
* @param {string} addr `a.b.c.0.1` will test if myObject has props a that has prop b. Work wit arrays as well (like `arr.0`)
|
|
319
326
|
*/
|
|
320
|
-
function has(obj:
|
|
327
|
+
function has(obj: ObjectGeneric, addr: string) {
|
|
321
328
|
if (!isset(obj) || typeof obj !== 'object') return;
|
|
322
329
|
let propsArr = addr.replace(/\.?\[(\d+)\]/g, '.$1').split('.'); // replace a[3] => a.3;
|
|
323
330
|
let objChain = obj;
|
|
@@ -332,7 +339,7 @@ function has(obj: object, addr: string) {
|
|
|
332
339
|
* @param {string} addr accept syntax like "obj.subItem.[0].sub2" OR "obj.subItem.0.sub2" OR "obj.subItem[0].sub2"
|
|
333
340
|
* @returns {any} the last item of the chain OR undefined if not found
|
|
334
341
|
*/
|
|
335
|
-
function findByAddress(obj:
|
|
342
|
+
function findByAddress(obj: ObjectGeneric, addr: string) {
|
|
336
343
|
if (addr === '') return obj;
|
|
337
344
|
if (!isset(obj) || typeof obj !== 'object') return console.warn('Main object in `findByAddress` function is undefined or has the wrong type');
|
|
338
345
|
const propsArr = addr.replace(/\.?\[(\d+)\]/g, '.$1').split('.'); // replace .[4] AND [4] TO .4
|
|
@@ -346,7 +353,7 @@ function findByAddress(obj: object, addr: string) {
|
|
|
346
353
|
/** Enforce writing subItems. Eg: user.name.blah will ensure all are set until the writing of the last item
|
|
347
354
|
* NOTE: doesn't work with arrays
|
|
348
355
|
*/
|
|
349
|
-
function objForceWrite(obj:
|
|
356
|
+
function objForceWrite(obj: ObjectGeneric, addr: string, item) {
|
|
350
357
|
const chunks = addr.replace(/\.?\[(\d+)\]/g, '.[$1').split('.');
|
|
351
358
|
let lastItem = obj;
|
|
352
359
|
chunks.forEach((chunkRaw, i) => {
|
|
@@ -366,7 +373,7 @@ function objForceWrite(obj: object, addr: string, item) {
|
|
|
366
373
|
* if user.name.blah has a value it will not change it.
|
|
367
374
|
* NOTE: doesn't work with arrays
|
|
368
375
|
*/
|
|
369
|
-
function objForceWriteIfNotSet(obj:
|
|
376
|
+
function objForceWriteIfNotSet(obj: ObjectGeneric, addr: string, item) {
|
|
370
377
|
if (!isset(findByAddress(obj, addr))) return objForceWrite(obj, addr, item);
|
|
371
378
|
}
|
|
372
379
|
|
|
@@ -390,16 +397,14 @@ function strAsArray(arrOrStr) {
|
|
|
390
397
|
/** If not an array provided, return the array with the value
|
|
391
398
|
* /!\ NOTE /!\ In case the value is null or undefined, it will return that value
|
|
392
399
|
*/
|
|
393
|
-
function asArray<T extends
|
|
394
|
-
|
|
395
|
-
function asArray<T>(item: T): any {
|
|
396
|
-
return typeof item === 'undefined' ? item : Array.isArray(item) ? item : [item]
|
|
400
|
+
function asArray<T extends any[] | any>(item: T): T extends undefined ? undefined : T extends any[] ? T : T[] {
|
|
401
|
+
return ((typeof item === 'undefined' ? item : Array.isArray(item) ? item : [item]) as T extends undefined ? undefined : T extends any[] ? T : T[])
|
|
397
402
|
}
|
|
398
403
|
|
|
399
404
|
/** Array comparison
|
|
400
405
|
* @return {object} { inCommon, notInB, notInA }
|
|
401
406
|
*/
|
|
402
|
-
function compareArrays(arrayA
|
|
407
|
+
function compareArrays(arrayA: any[], arrayB: any[], compare = (a, b) => a === b) {
|
|
403
408
|
return {
|
|
404
409
|
inCommon: getArrayInCommon(arrayA, arrayB, compare),
|
|
405
410
|
notInB: getNotInArrayA(arrayB, arrayA, compare),
|
|
@@ -1166,9 +1171,6 @@ function validator(...paramsToValidate: ValidatorObject[]) {
|
|
|
1166
1171
|
|
|
1167
1172
|
const restTestMini = {
|
|
1168
1173
|
reset() {
|
|
1169
|
-
restTestMini.nbSuccess = 0
|
|
1170
|
-
restTestMini.nbError = 0
|
|
1171
|
-
restTestMini.lastErrors = []
|
|
1172
1174
|
},
|
|
1173
1175
|
printStats() {
|
|
1174
1176
|
// TODO print last errz
|
|
@@ -1371,7 +1373,7 @@ function err422IfNotSet(o) {
|
|
|
1371
1373
|
if (m.length) throw new dataValidationUtilErrorHandler(`requiredVariableEmptyOrNotSet`, 422, { origin: 'Validator', varNames: m.join(', ') })
|
|
1372
1374
|
}
|
|
1373
1375
|
|
|
1374
|
-
function getDateAsInt12(dateAllFormat?: Date | string | number, errIfNotValid?):
|
|
1376
|
+
function getDateAsInt12(dateAllFormat?: Date | string | number, errIfNotValid?): string { return getDateAsInt(dateAllFormat, errIfNotValid, true); } // alias
|
|
1375
1377
|
|
|
1376
1378
|
function humanReadableTimestamp(dateAllFormat: any): number {
|
|
1377
1379
|
if (isset(dateAllFormat)) dateAllFormat = getDateAsObject(dateAllFormat);
|
|
@@ -1381,9 +1383,13 @@ function humanReadableTimestamp(dateAllFormat: any): number {
|
|
|
1381
1383
|
/** format for 6/8/2018 => 20180806
|
|
1382
1384
|
* @param dateAllFormat multiple format allowed 2012, 20120101, 201201011200, new Date(), "2019-12-08T16:19:10.341Z" and all string that new Date() can parse
|
|
1383
1385
|
*/
|
|
1384
|
-
function getDateAsInt(dateAllFormat: Date | string | number = new Date(), errIfNotValid$ = false, withHoursAndMinutes$ = false):
|
|
1386
|
+
function getDateAsInt(dateAllFormat: Date | string | number = new Date(), errIfNotValid$ = false, withHoursAndMinutes$ = false): string { // optional
|
|
1385
1387
|
let dateInt;
|
|
1386
|
-
if (
|
|
1388
|
+
if (typeof dateAllFormat === 'string' && dateAllFormat.includes('/')) {
|
|
1389
|
+
// 01/01/2020 format
|
|
1390
|
+
const [d, m, y] = dateAllFormat.split('/')
|
|
1391
|
+
return y + m.toString().padStart(2, '0') + d.toString().padStart(2, '0')
|
|
1392
|
+
} else if (isDateIntOrStringValid(dateAllFormat)) {
|
|
1387
1393
|
// we can pass an int or string format (20180106)
|
|
1388
1394
|
dateInt = (dateAllFormat + '00000000').substr(0, 12); // add default 000000 for "month days minutes:sec" if not set
|
|
1389
1395
|
} else {
|
|
@@ -1580,106 +1586,6 @@ function doDateOverlap(event1, event2, fieldNameForStartDate$ = 'startDate', fie
|
|
|
1580
1586
|
return (!event2[fieldNameForEndDate$] || event1[fieldNameForStartDate$] <= event2[fieldNameForEndDate$]) && (!event1[fieldNameForEndDate$] || event1[fieldNameForEndDate$] >= event2[fieldNameForStartDate$]);
|
|
1581
1587
|
}
|
|
1582
1588
|
|
|
1583
|
-
|
|
1584
|
-
/** Get all dates at specified days between two dates
|
|
1585
|
-
* @param daysArray [0,1,2,3,4,5,6]
|
|
1586
|
-
* @param {*} startDate all format
|
|
1587
|
-
* @param {*} endDate all format
|
|
1588
|
-
* @param {'int'|'object'} outputFormat default: int
|
|
1589
|
-
*/
|
|
1590
|
-
function getDatesForDaysArrayBetweenTwoDates(daysArray, startDate, endDate, outputFormat = 'int') {
|
|
1591
|
-
const dateArr = [];
|
|
1592
|
-
let actualDate = getDateAsObject(startDate);
|
|
1593
|
-
endDate = getDateAsObject(endDate);
|
|
1594
|
-
while (actualDate <= endDate) {
|
|
1595
|
-
if (daysArray.includes(actualDate.getUTCDay())) dateArr.push(getDateAsObject(actualDate)); // cloned
|
|
1596
|
-
actualDate.setUTCDate(actualDate.getUTCDate() + 1);
|
|
1597
|
-
}
|
|
1598
|
-
return dateArr.map(d => getDateAs(d, outputFormat));
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
function getEndTimeFromDurationAndStartTime(startTime, duration) {
|
|
1602
|
-
const timeArr = startTime.split(':').map(n => parseInt(n));
|
|
1603
|
-
let endTime = (timeArr[0] * 60 + timeArr[1]) + duration;
|
|
1604
|
-
|
|
1605
|
-
return {
|
|
1606
|
-
days: Math.floor(endTime / 1440),
|
|
1607
|
-
time: pad(Math.floor((endTime % 1440) / 60)) + ':' + pad(endTime % 60)
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
function getDate12FromDateAndTime(dateAllFormat: Date | string | number, timeAllFormat) {
|
|
1612
|
-
if (typeof dateAllFormat !== 'number' || dateAllFormat > 99991231 || dateAllFormat < 0) dateAllFormat = getDateAsInt(dateAllFormat);
|
|
1613
|
-
|
|
1614
|
-
if (typeof timeAllFormat !== 'number' || timeAllFormat > 2359 || timeAllFormat < 0) timeAllFormat = getTimeAsInt(timeAllFormat);
|
|
1615
|
-
|
|
1616
|
-
return dateAllFormat * 10000 + timeAllFormat;
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
function eachDayOfInterval(startDateAllFormat, endDateAllFormat, outputFormat = 'int') {
|
|
1620
|
-
const start = getDateAsObject(startDateAllFormat);
|
|
1621
|
-
const end = getDateAsObject(endDateAllFormat);
|
|
1622
|
-
let days = [];
|
|
1623
|
-
let current = new Date();
|
|
1624
|
-
current.setTime(start.getTime());
|
|
1625
|
-
while (current <= end) {
|
|
1626
|
-
days.push(new Date(current.getTime()));
|
|
1627
|
-
current.setTime(current.getTime() + 1000 * 60 * 60 * 24);
|
|
1628
|
-
}
|
|
1629
|
-
return days.map(d => getDateAs(d, outputFormat));
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
function eachMonthOfInterval(startDateAllFormat, endDateAllFormat) {
|
|
1633
|
-
const months = [];
|
|
1634
|
-
const current: any = firstDayOfMonth(startDateAllFormat, 'Object');
|
|
1635
|
-
const end = firstDayOfMonth(endDateAllFormat, 'Object');
|
|
1636
|
-
while (current <= end) {
|
|
1637
|
-
months.push(getMonthAsInt(current));
|
|
1638
|
-
current.setUTCMonth(current.getUTCMonth() + 1);
|
|
1639
|
-
}
|
|
1640
|
-
return months;
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
function isSunday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1644
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1645
|
-
return date.getUTCDay() === 0;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
function isMonday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1649
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1650
|
-
return date.getUTCDay() === 1;
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
function isTuesday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1654
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1655
|
-
return date.getUTCDay() === 2;
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
function isWednesday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1659
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1660
|
-
return date.getUTCDay() === 3;
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
function isThursday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1664
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1665
|
-
return date.getUTCDay() === 4;
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
|
-
function isFriday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1669
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1670
|
-
return date.getUTCDay() === 5;
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
function isSaturday(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1674
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1675
|
-
return date.getUTCDay() === 6;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
function isWeekend(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1679
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1680
|
-
return date.getUTCDay() === 6 || date.getUTCDay() === 0;
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
1589
|
type DateAllFormat = 'dateInt8' | 'dateInt12' | 'date' | 'humanReadableTimestamp'
|
|
1684
1590
|
|
|
1685
1591
|
function nextWeekDay(fromDate, weekDayInt?: 0 | 1 | 2 | 3 | 4 | 5 | 6, outputFormat?: 'dateInt8' | 'dateInt12' | 'humanReadableTimestamp', sameDayAllowed?: boolean): number
|
|
@@ -1764,6 +1670,7 @@ function getMinutes(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
|
1764
1670
|
const [, , , , m] = dateStringToArray(dateAsInt);
|
|
1765
1671
|
return m;
|
|
1766
1672
|
}
|
|
1673
|
+
|
|
1767
1674
|
/**
|
|
1768
1675
|
* @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8)
|
|
1769
1676
|
*/
|
|
@@ -1773,6 +1680,7 @@ function lastDayOfMonth(dateAllFormat: Date | string | number = getDateAsInt(),
|
|
|
1773
1680
|
lastDay.setUTCHours(date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
|
|
1774
1681
|
return getDateAs(lastDay, outputFormat);
|
|
1775
1682
|
}
|
|
1683
|
+
|
|
1776
1684
|
/**
|
|
1777
1685
|
* @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8)
|
|
1778
1686
|
*/
|
|
@@ -1809,100 +1717,6 @@ function differenceInWeeks(startDateAllFormat, endDateAllFormat) {
|
|
|
1809
1717
|
return differenceInDays(startDateAllFormat, endDateAllFormat) / 7;
|
|
1810
1718
|
}
|
|
1811
1719
|
|
|
1812
|
-
function differenceInMonths(startDateAllFormat, endDateAllFormat) {
|
|
1813
|
-
const startDate = getDateAsInt(startDateAllFormat);
|
|
1814
|
-
const endDate = getDateAsInt(endDateAllFormat);
|
|
1815
|
-
const monthesForStart = parseInt(getYear(startDate)) * 12 + parseInt(getMonthForHuman(startDate));
|
|
1816
|
-
const monthesForEnd = parseInt(getYear(endDate)) * 12 + parseInt(getMonthForHuman(endDate));
|
|
1817
|
-
if (monthesForStart === monthesForEnd) {
|
|
1818
|
-
const firstDay = firstDayOfMonth(startDate);
|
|
1819
|
-
const lastDay = lastDayOfMonth(endDate);
|
|
1820
|
-
const differenceBetweenStartAndEnd = differenceInDays(startDate, endDate);
|
|
1821
|
-
const numberOfDaysInMonth = differenceInDays(firstDay, lastDay);
|
|
1822
|
-
return round(differenceBetweenStartAndEnd / numberOfDaysInMonth, 2);
|
|
1823
|
-
}
|
|
1824
|
-
const firstDayOfStartDateMonth = firstDayOfMonth(startDate);
|
|
1825
|
-
const lastDayOfStartDateMonth = lastDayOfMonth(startDate);
|
|
1826
|
-
const firstDayOfEndDateMonth = firstDayOfMonth(endDate);
|
|
1827
|
-
const lastDayOfEndDateMonth = lastDayOfMonth(endDate);
|
|
1828
|
-
const differenceBetweenStartDateAndEndOfStartMonth = differenceInDays(startDate, lastDayOfStartDateMonth);
|
|
1829
|
-
const differenceBetweenStartOfEndMonthAndEndDate = differenceInDays(firstDayOfEndDateMonth, endDate);
|
|
1830
|
-
const numberOfDaysInStartMonth = differenceInDays(firstDayOfStartDateMonth, lastDayOfStartDateMonth);
|
|
1831
|
-
const numberOfDaysInEndMonth = differenceInDays(firstDayOfEndDateMonth, lastDayOfEndDateMonth);
|
|
1832
|
-
return round(monthesForEnd - monthesForStart - 1 + differenceBetweenStartDateAndEndOfStartMonth / numberOfDaysInStartMonth + differenceBetweenStartOfEndMonthAndEndDate / numberOfDaysInEndMonth, 2);
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
/** Will check if that date exists, and if not, this will
|
|
1837
|
-
* Usefull for monthly subscription or reccuring month dates
|
|
1838
|
-
* @param {any} dateAllFormat default: new Date()
|
|
1839
|
-
* @returns {Date} Date object
|
|
1840
|
-
*/
|
|
1841
|
-
function getClosestExistingDateOfMonth(dateAllFormat: Date | string | number = getDateAsInt()) {
|
|
1842
|
-
let [day, month, year] = dateArrayInt(dateAllFormat);
|
|
1843
|
-
const zeroBasedMonth = minMax(month - 1, 0, 11);
|
|
1844
|
-
if (!isBetween(month, 1, 12)) console.error('Wrong month provided for getClosestExistingDateOfMonth: ' + month + ' Shall be between 1-12. Converted to ' + zeroBasedMonth);
|
|
1845
|
-
let dayNb = minMax(day, 1, 31);
|
|
1846
|
-
let date;
|
|
1847
|
-
let increment = dayNb < 1;
|
|
1848
|
-
let tooMuchRecursionCount = 0;
|
|
1849
|
-
do date = new Date(year, zeroBasedMonth, (increment ? dayNb++ : dayNb--), 12);
|
|
1850
|
-
while (date.getUTCMonth() !== zeroBasedMonth && tooMuchRecursionCount < 99);
|
|
1851
|
-
if (tooMuchRecursionCount) throw new dataValidationUtilErrorHandler(`tooMuchRecursionCount`, 500, { origin: 'getClosestExistingDateOfMonth', day, month, year });
|
|
1852
|
-
return date;
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
/** Compute the best possible date for next month same day
|
|
1856
|
-
* Usefull for monthly subscription or reccuring month dates
|
|
1857
|
-
* @param {any} dateAllFormat default: new Date()
|
|
1858
|
-
* @param {Boolean} onlyFuture if true return the future date relative to any date in the past, else, it return the next month date possible relative to the dateAllFormat
|
|
1859
|
-
* @returns {Date} Date object
|
|
1860
|
-
*/
|
|
1861
|
-
function getNextMonthlyDate(dateAllFormat: Date | string | number = getDateAsInt(), onlyFuture = false) {
|
|
1862
|
-
let [day, month, year] = dateArrayInt(dateAllFormat);
|
|
1863
|
-
day = minMax(day, 1, 31);
|
|
1864
|
-
month = minMax(month, 1, 12);
|
|
1865
|
-
err422IfNotSet({ year, month, day });
|
|
1866
|
-
const isDatePast = getDateAsInt(dateAllFormat) <= getDateAsInt();
|
|
1867
|
-
if (onlyFuture && isDatePast) {
|
|
1868
|
-
let [, todayMonth, todayYear] = dateArrayInt();
|
|
1869
|
-
month = todayMonth
|
|
1870
|
-
year = todayYear
|
|
1871
|
-
}
|
|
1872
|
-
let nextMonth;
|
|
1873
|
-
if (month === 12) {
|
|
1874
|
-
nextMonth = 1;
|
|
1875
|
-
year++;
|
|
1876
|
-
} else nextMonth = month + 1;
|
|
1877
|
-
return getClosestExistingDateOfMonth(new Date(year, nextMonth - 1, day));
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
function getHolidayReferenceYear(dateAllFormat: Date | string | number) {
|
|
1881
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1882
|
-
if (date.getUTCMonth() > 4) return date.getUTCFullYear();
|
|
1883
|
-
return date.getUTCFullYear() - 1;
|
|
1884
|
-
}
|
|
1885
|
-
/**
|
|
1886
|
-
* @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8)
|
|
1887
|
-
*/
|
|
1888
|
-
function getFirstDayOfHolidayReferenceYear(dateAllFormat: Date | string | number, outputFormat = 'int') {
|
|
1889
|
-
const date = getDateAsObject(dateAllFormat);
|
|
1890
|
-
let year = date.getUTCFullYear();
|
|
1891
|
-
if (date.getUTCMonth() < 4) year = date.getUTCFullYear() - 1;
|
|
1892
|
-
const firstDayAsInt = year + '0601';
|
|
1893
|
-
return getDateAs(firstDayAsInt, outputFormat);
|
|
1894
|
-
}
|
|
1895
|
-
/**
|
|
1896
|
-
* @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8)
|
|
1897
|
-
*/
|
|
1898
|
-
function getLastDayOfHolidayReferenceYear(dateAllFormat: Date | string | number, outputFormat = 'int') {
|
|
1899
|
-
let date = getDateAsObject(dateAllFormat);
|
|
1900
|
-
let year = date.getUTCFullYear() + 1;
|
|
1901
|
-
if (date.getUTCMonth() < 4) year = date.getUTCFullYear();
|
|
1902
|
-
const firstDayAsInt = year + '0531';
|
|
1903
|
-
return getDateAs(firstDayAsInt, outputFormat);
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
1720
|
/**
|
|
1907
1721
|
* @param {String} outputDateFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8)
|
|
1908
1722
|
*/
|
|
@@ -2451,6 +2265,7 @@ const _ = {
|
|
|
2451
2265
|
sortUrlsByDeepnessInArrayOrObject,
|
|
2452
2266
|
urlPathJoin,
|
|
2453
2267
|
miniTemplater,
|
|
2268
|
+
generateObjectId,
|
|
2454
2269
|
isBetween,
|
|
2455
2270
|
simpleObjectMaskOrSelect,
|
|
2456
2271
|
ENV,
|
|
@@ -2568,18 +2383,7 @@ const _ = {
|
|
|
2568
2383
|
isTimeStringValid,
|
|
2569
2384
|
getDuration,
|
|
2570
2385
|
doDateOverlap,
|
|
2571
|
-
getDatesForDaysArrayBetweenTwoDates,
|
|
2572
|
-
getEndTimeFromDurationAndStartTime,
|
|
2573
|
-
getDate12FromDateAndTime,
|
|
2574
2386
|
getMonthAsInt,
|
|
2575
|
-
isSunday,
|
|
2576
|
-
isMonday,
|
|
2577
|
-
isTuesday,
|
|
2578
|
-
isWednesday,
|
|
2579
|
-
isThursday,
|
|
2580
|
-
isFriday,
|
|
2581
|
-
isSaturday,
|
|
2582
|
-
isWeekend,
|
|
2583
2387
|
nextWeekDay,
|
|
2584
2388
|
addMinutes,
|
|
2585
2389
|
addHours,
|
|
@@ -2592,20 +2396,12 @@ const _ = {
|
|
|
2592
2396
|
getMinutes,
|
|
2593
2397
|
firstDayOfMonth,
|
|
2594
2398
|
lastDayOfMonth,
|
|
2595
|
-
eachDayOfInterval,
|
|
2596
|
-
eachMonthOfInterval,
|
|
2597
2399
|
differenceInMilliseconds,
|
|
2598
2400
|
differenceInSeconds,
|
|
2599
2401
|
differenceInMinutes,
|
|
2600
2402
|
differenceInHours,
|
|
2601
2403
|
differenceInDays,
|
|
2602
2404
|
differenceInWeeks,
|
|
2603
|
-
differenceInMonths,
|
|
2604
|
-
getClosestExistingDateOfMonth,
|
|
2605
|
-
getNextMonthlyDate,
|
|
2606
|
-
getHolidayReferenceYear,
|
|
2607
|
-
getFirstDayOfHolidayReferenceYear,
|
|
2608
|
-
getLastDayOfHolidayReferenceYear,
|
|
2609
2405
|
// ALIASES
|
|
2610
2406
|
getDateAsArrayFormatted: dateArray,
|
|
2611
2407
|
getDateAsArray: dateStringToArray,
|
|
@@ -2655,6 +2451,7 @@ export {
|
|
|
2655
2451
|
sortUrlsByDeepnessInArrayOrObject,
|
|
2656
2452
|
urlPathJoin,
|
|
2657
2453
|
miniTemplater,
|
|
2454
|
+
generateObjectId,
|
|
2658
2455
|
isBetween,
|
|
2659
2456
|
simpleObjectMaskOrSelect,
|
|
2660
2457
|
ENV,
|
|
@@ -2774,18 +2571,7 @@ export {
|
|
|
2774
2571
|
// isDateObject <= see validator.js
|
|
2775
2572
|
getDuration,
|
|
2776
2573
|
doDateOverlap,
|
|
2777
|
-
getDatesForDaysArrayBetweenTwoDates,
|
|
2778
|
-
getEndTimeFromDurationAndStartTime,
|
|
2779
|
-
getDate12FromDateAndTime,
|
|
2780
2574
|
getMonthAsInt,
|
|
2781
|
-
isSunday,
|
|
2782
|
-
isMonday,
|
|
2783
|
-
isTuesday,
|
|
2784
|
-
isWednesday,
|
|
2785
|
-
isThursday,
|
|
2786
|
-
isFriday,
|
|
2787
|
-
isSaturday,
|
|
2788
|
-
isWeekend,
|
|
2789
2575
|
nextWeekDay,
|
|
2790
2576
|
addMinutes,
|
|
2791
2577
|
addHours,
|
|
@@ -2798,20 +2584,12 @@ export {
|
|
|
2798
2584
|
getMinutes,
|
|
2799
2585
|
firstDayOfMonth,
|
|
2800
2586
|
lastDayOfMonth,
|
|
2801
|
-
eachDayOfInterval,
|
|
2802
|
-
eachMonthOfInterval,
|
|
2803
2587
|
differenceInMilliseconds,
|
|
2804
2588
|
differenceInSeconds,
|
|
2805
2589
|
differenceInMinutes,
|
|
2806
2590
|
differenceInHours,
|
|
2807
2591
|
differenceInDays,
|
|
2808
2592
|
differenceInWeeks,
|
|
2809
|
-
differenceInMonths,
|
|
2810
|
-
getClosestExistingDateOfMonth,
|
|
2811
|
-
getNextMonthlyDate,
|
|
2812
|
-
getHolidayReferenceYear,
|
|
2813
|
-
getFirstDayOfHolidayReferenceYear,
|
|
2814
|
-
getLastDayOfHolidayReferenceYear,
|
|
2815
2593
|
// ALIASES
|
|
2816
2594
|
getDateAsInt as convertDateAsInt,
|
|
2817
2595
|
getDateAsObject as convertDateAsObject,
|