UNPKG

topkat-utils

Version:

A comprehensive collection of TypeScript/JavaScript utility functions for common programming tasks. Includes validation, object manipulation, date handling, string formatting, and more. Zero dependencies, fully typed, and optimized for performance.

357 lines 17.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isDateIsoOrObjectValid = exports.isDateIntOrStringValid = exports.getDateAs = exports.differenceInWeeks = exports.differenceInDays = exports.differenceInHours = exports.differenceInMinutes = exports.differenceInSeconds = exports.differenceInMilliseconds = exports.firstDayOfMonth = exports.lastDayOfMonth = exports.getMinutes = exports.getHours = exports.getYear = exports.getDayOfMonth = exports.addYears = exports.addMonths = exports.addHours = exports.addMinutes = exports.addDays = exports.nextWeekDay = exports.doDateOverlap = exports.getDuration = exports.isTimeStringValid = exports.getIntAsTime = exports.getTimeAsInt = exports.dateOffset = exports.dateFormatted = exports.dateArrayInt = exports.dateArray = exports.dateStringToArray = exports.getDateAsObject = exports.getMonthAsInt = exports.getDateAsInt = exports.humanReadableTimestamp = exports.getDateAsInt12 = void 0; //---------------------------------------- // DATE UTILS //---------------------------------------- const isset_1 = require("./isset"); const math_utils_1 = require("./math-utils"); const error_utils_1 = require("./error-utils"); const error_utils_2 = require("./error-utils"); const int = parseInt; function getDateAsInt12(dateAllFormat, errIfNotValid) { return getDateAsInt(dateAllFormat, errIfNotValid, true); } // alias exports.getDateAsInt12 = getDateAsInt12; function humanReadableTimestamp(dateAllFormat) { if ((0, isset_1.isset)(dateAllFormat)) dateAllFormat = getDateAsObject(dateAllFormat); return parseInt(getDateAsInt12(dateAllFormat) + (0, math_utils_1.pad)((dateAllFormat || new Date()).getUTCSeconds()) + (0, math_utils_1.pad)((dateAllFormat || new Date()).getUTCMilliseconds(), 3)); } exports.humanReadableTimestamp = humanReadableTimestamp; /** format for 6/8/2018 => 20180806 * @param dateAllFormat multiple format allowed 2012, 20120101, 201201011200, new Date(), "2019-12-08T16:19:10.341Z" and all string that new Date() can parse */ function getDateAsInt(dateAllFormat = new Date(), errIfNotValid$ = false, withHoursAndMinutes$ = false) { let dateInt; if (typeof dateAllFormat === 'string' && dateAllFormat.includes('/')) { // 01/01/2020 format const [d, m, y] = dateAllFormat.split('/'); return y + m.toString().padStart(2, '0') + d.toString().padStart(2, '0'); } else if (isDateIntOrStringValid(dateAllFormat)) { // we can pass an int or string format (20180106) dateInt = (dateAllFormat + '00000000').substr(0, 12); // add default 000000 for "month days minutes:sec" if not set } else { let date = dateAllFormat; if (typeof date === 'string') date = new Date(date); const realDate = date; //let dateArr = dateAllFormat.toString().split(); // we cannot use ISOString dateInt = '' + realDate.getUTCFullYear() + (0, math_utils_1.pad)(realDate.getUTCMonth() + 1) + (0, math_utils_1.pad)(realDate.getUTCDate()) + (0, math_utils_1.pad)(realDate.getUTCHours()) + (0, math_utils_1.pad)(realDate.getUTCMinutes()); } isDateIntOrStringValid(dateInt, errIfNotValid$); return (withHoursAndMinutes$ ? dateInt : dateInt.substr(0, 8)); } exports.getDateAsInt = getDateAsInt; function getMonthAsInt(dateAllFormat = new Date()) { let dateInt; if (isDateIntOrStringValid(dateAllFormat)) { // we can pass an int or string format (20180106) dateInt = (dateAllFormat + '').substr(0, 6); } else { let date = dateAllFormat; if (typeof date === 'string') date = new Date(date); //let dateArr = dateAllFormat.toString().split(); // we cannot use ISOString dateInt = '' + date.getUTCFullYear() + (0, math_utils_1.pad)(date.getUTCMonth() + 1); } return int(dateInt); } exports.getMonthAsInt = getMonthAsInt; /** * @param dateAllFormat multiple format allowed 2012, 20120101, 201201011200, new Date(), "2019-12-08T16:19:10.341Z" and all string that new Date() can parse */ function getDateAsObject(dateAllFormat = new Date(), errIfNotValid$ = true) { let dateObj = dateAllFormat; if (isDateIntOrStringValid(dateAllFormat)) { const [y, M, d, h, m] = dateStringToArray(dateAllFormat); dateObj = new Date(`${y}-${M}-${d}T${h}:${m}`); } else if (typeof dateAllFormat === 'string') { dateObj = new Date(dateAllFormat); } else { dateObj = new Date(dateAllFormat.getTime()); // clone } isDateIsoOrObjectValid(dateObj, errIfNotValid$); return dateObj; } exports.getDateAsObject = getDateAsObject; /** [2018,01,06] */ function dateStringToArray(strOrInt) { (0, error_utils_2.err422IfNotSet)({ strOrInt }); const dateStr = strOrInt.toString(); return [ dateStr.substr(0, 4), dateStr.substr(4, 2) || '01', dateStr.substr(6, 2) || '01', dateStr.substr(8, 2) || '12', dateStr.substr(10, 2) || '00', dateStr.substr(12, 2) || '00', dateStr.substr(14, 3) || '000', // MS ]; } exports.dateStringToArray = dateStringToArray; /** * @param dateAllFormat default: actualDate * @returns ['01', '01', '2019'] OR **string** if separator is provided */ function dateArray(dateAllFormat = getDateAsInt()) { const dateStr = getDateAsInt(dateAllFormat).toString(); return [ dateStr.substr(6, 2), dateStr.substr(4, 2), dateStr.substr(0, 4), // Y ]; } exports.dateArray = dateArray; /** * @param dateAllFormat default: actualDate * @returns ['01', '01', '2019'] OR **string** if separator is provided */ function dateArrayInt(dateAllFormat = getDateAsInt()) { const dateStr = getDateAsInt(dateAllFormat).toString(); return [ int(dateStr.substr(6, 2)), int(dateStr.substr(4, 2)), int(dateStr.substr(0, 4)), // Y ]; } exports.dateArrayInt = dateArrayInt; /** * @return 01/01/2012 (alias of dateArrayFormatted(date, '/')) */ function dateFormatted(dateAllFormat, separator = '/') { return dateArray(dateAllFormat).join(separator); } exports.dateFormatted = dateFormatted; /** Date with custom offset (Ex: +2 for France) */ function dateOffset(offsetHours, dateObj = new Date()) { const utc = Date.UTC(dateObj.getUTCFullYear(), dateObj.getUTCMonth(), dateObj.getUTCDate(), dateObj.getUTCHours(), dateObj.getUTCMinutes(), dateObj.getUTCSeconds()); return new Date(utc + (3600000 * offsetHours)); } exports.dateOffset = dateOffset; //---------------------------------------- // TIME UTILS //---------------------------------------- /** */ function getTimeAsInt(timeOrDateInt = getDateAsInt12()) { if (isDateIntOrStringValid(timeOrDateInt)) { const tl = timeOrDateInt.toString().length; return int(timeOrDateInt.toString().substring(tl - 4, tl)); } else if (typeof timeOrDateInt === 'string' && timeOrDateInt.length === 5 && timeOrDateInt.includes(':')) return int(timeOrDateInt.replace(':', '')); else return 'dateInvalid'; } exports.getTimeAsInt = getTimeAsInt; /** * @param {timeInt|dateInt12} Eg: 2222 OR 201201012222. Default, actual dateInt12 * @param {String} separator default: ":" */ function getIntAsTime(intOrDateTimeInt = getDateAsInt12(), separator = ':') { const time = intOrDateTimeInt.toString().padStart(4, '0'); const tl = time.length; return time.substring(tl - 4, tl - 2) + separator + time.substring(tl - 2, tl); } exports.getIntAsTime = getIntAsTime; function isTimeStringValid(timeStr, outputAnError$ = false) { const timeArr = timeStr.split(':'); const h = int(timeArr[0]); const m = int(timeArr[1]); const test1 = h >= 0 && h < 24; const test2 = m >= 0 && m < 60; if (outputAnError$ && !(test1 && test2)) throw new error_utils_1.DescriptiveError('timeStringOutOfRange', { code: 422, origin: 'Time validator' }); else return test1 && test2; } exports.isTimeStringValid = isTimeStringValid; //---------------------------------------- // DURATIONS //---------------------------------------- function getDuration(startDate, endDate, inMinutes = false) { const startDateO = getDateAsObject(startDate); const endDateO = getDateAsObject(endDate); const diffInSec = Math.floor(endDateO.getTime() / 1000) - Math.floor(startDateO.getTime() / 1000); if (inMinutes) return Math.floor(diffInSec / 60); else return [ Math.floor(diffInSec / (24 * 3600)), Math.floor((diffInSec % (24 * 3600)) / 3600), Math.floor(((diffInSec % (24 * 3600)) % 3600) / 60), // M ]; } exports.getDuration = getDuration; /** compare two object with DATE INT, if they overlap return true * @param {Object} event1 {startDate, endDate} * @param {Object} event2 {startDate, endDate} * @param {String} fieldNameForStartDate$ replace startDate with this string * @param {String} fieldNameForEndDate$ replace endDate with this string * @param {Boolean} allowNull$ if false, retrun false if any of the startdates or enddates are not set * @param {Boolean} strict$ if true, */ function doDateOverlap(event1, event2, fieldNameForStartDate$ = 'startDate', fieldNameForEndDate$ = 'endDate', allowNull$ = true, strict$ = false) { if (!allowNull$ && !(0, isset_1.isset)(event1[fieldNameForStartDate$], event1[fieldNameForEndDate$], event2[fieldNameForStartDate$], event2[fieldNameForEndDate$])) return false; if (strict$) return (!event2[fieldNameForEndDate$] || event1[fieldNameForStartDate$] < event2[fieldNameForEndDate$]) && (!event1[fieldNameForEndDate$] || event1[fieldNameForEndDate$] > event2[fieldNameForStartDate$]); return (!event2[fieldNameForEndDate$] || event1[fieldNameForStartDate$] <= event2[fieldNameForEndDate$]) && (!event1[fieldNameForEndDate$] || event1[fieldNameForEndDate$] >= event2[fieldNameForStartDate$]); } exports.doDateOverlap = doDateOverlap; function nextWeekDay(fromDate, weekDayInt, outputFormat = 'date', sameDayAllowed = false) { const date = getDateAsObject(fromDate); if (typeof weekDayInt === 'undefined') weekDayInt = date.getDay(); const toAdd = !sameDayAllowed && date.getDay() === weekDayInt ? 7 : 0; date.setUTCDate(date.getUTCDate() + toAdd + (7 + weekDayInt - date.getUTCDay()) % 7); return getDateAs(date, outputFormat); } exports.nextWeekDay = nextWeekDay; function addDays(dateAllFormat = getDateAsInt(), numberOfDays = 1, outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); date.setTime(date.getTime() + numberOfDays * 24 * 60 * 60 * 1000); return getDateAs(date, outputFormat); } exports.addDays = addDays; function addMinutes(dateAllFormat = getDateAsInt(), numberOfMinutes = 1, outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); date.setTime(date.getTime() + 1 * numberOfMinutes * 60 * 1000); return getDateAs(date, outputFormat); } exports.addMinutes = addMinutes; function addHours(dateAllFormat = getDateAsInt(), numberOfHours = 1, outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); date.setTime(date.getTime() + 1 * numberOfHours * 60 * 60 * 1000); return getDateAs(date, outputFormat); } exports.addHours = addHours; function addMonths(dateAllFormat = getDateAsInt(), numberOfMonths = 1, outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); date.setUTCMonth(date.getUTCMonth() + numberOfMonths); return getDateAs(date, outputFormat); } exports.addMonths = addMonths; /** * @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8) */ function addYears(dateAllFormat = getDateAsInt(), numberOfYears = 1, outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); date.setUTCFullYear(date.getUTCFullYear() + numberOfYears); return getDateAs(date, outputFormat); } exports.addYears = addYears; function getDayOfMonth(dateAllFormat = getDateAsInt()) { const dateAsInt = getDateAsInt(dateAllFormat); const [, , d] = dateStringToArray(dateAsInt); return d; } exports.getDayOfMonth = getDayOfMonth; function getYear(dateAllFormat = getDateAsInt()) { const dateAsInt = getDateAsInt(dateAllFormat); const [y] = dateStringToArray(dateAsInt); return y; } exports.getYear = getYear; function getHours(dateAllFormat = getDateAsInt()) { const dateAsInt = getDateAsInt(dateAllFormat); const [, , , h] = dateStringToArray(dateAsInt); return h; } exports.getHours = getHours; function getMinutes(dateAllFormat = getDateAsInt()) { const dateAsInt = getDateAsInt(dateAllFormat); const [, , , , m] = dateStringToArray(dateAsInt); return m; } exports.getMinutes = getMinutes; /** * @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8) */ function lastDayOfMonth(dateAllFormat = getDateAsInt(), outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); const lastDay = new Date(date.getUTCFullYear(), date.getUTCMonth() + 1, 0); lastDay.setUTCHours(date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds()); return getDateAs(lastDay, outputFormat); } exports.lastDayOfMonth = lastDayOfMonth; /** * @param {String} outputFormat dateInt, dateInt8, dateInt12, date, humanReadableTimestamp, int (dateInt8) */ function firstDayOfMonth(dateAllFormat = getDateAsInt(), outputFormat = 'date') { const date = getDateAsObject(dateAllFormat); const firstDay = new Date(date.getUTCFullYear(), date.getUTCMonth(), 1); firstDay.setUTCHours(date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds()); return getDateAs(firstDay, outputFormat); } exports.firstDayOfMonth = firstDayOfMonth; function differenceInMilliseconds(startDateAllFormat, endDateAllFormat) { const startDate = getDateAsObject(startDateAllFormat); const endDate = getDateAsObject(endDateAllFormat); return endDate.getTime() - startDate.getTime(); } exports.differenceInMilliseconds = differenceInMilliseconds; function differenceInSeconds(startDateAllFormat, endDateAllFormat) { return differenceInMilliseconds(startDateAllFormat, endDateAllFormat) / 1000; } exports.differenceInSeconds = differenceInSeconds; function differenceInMinutes(startDateAllFormat, endDateAllFormat) { return differenceInSeconds(startDateAllFormat, endDateAllFormat) / 60; } exports.differenceInMinutes = differenceInMinutes; function differenceInHours(startDateAllFormat, endDateAllFormat) { return differenceInMinutes(startDateAllFormat, endDateAllFormat) / 60; } exports.differenceInHours = differenceInHours; function differenceInDays(startDateAllFormat, endDateAllFormat) { return differenceInHours(startDateAllFormat, endDateAllFormat) / 24; } exports.differenceInDays = differenceInDays; function differenceInWeeks(startDateAllFormat, endDateAllFormat) { return differenceInDays(startDateAllFormat, endDateAllFormat) / 7; } exports.differenceInWeeks = differenceInWeeks; function getDateAs(dateAllFormat = new Date(), outputDateFormat = 'date') { switch (outputDateFormat) { case 'dateInt8': return getDateAsInt(dateAllFormat); case 'dateInt12': return getDateAsInt12(dateAllFormat); case 'humanReadableTimestamp': return humanReadableTimestamp(dateAllFormat); case 'date': default: return getDateAsObject(dateAllFormat); } } exports.getDateAs = getDateAs; function isDateIntOrStringValid(dateStringOrInt, outputAnError = false, length) { if (!(0, isset_1.isset)(dateStringOrInt)) return false; const dateStr = dateStringOrInt.toString(); if (length && dateStr.length !== length) throw new error_utils_1.DescriptiveError(`wrongLengthForDateInt`, { code: 422, origin: 'Date Int validator', dateStringOrInt: dateStringOrInt, extraInfo: `${dateStringOrInt} length !== ${length}` }); if ((typeof dateStringOrInt === 'object' && isNaN(int(dateStr))) || ![4, 6, 8, 10, 12, 17].includes(dateStr.length)) return false; const dateArr = dateStringToArray(dateStringOrInt); const [y, M, d, h, m] = dateArr; const test1 = dateArr.length >= 3 && int(y) >= 1000; // Y const test2 = int(M) <= 12 && int(M) > 0; // M const test3 = !(0, isset_1.isset)(d) || int(d) <= 31 && int(d) > 0; // D const test4 = !(0, isset_1.isset)(h) || (int(h) <= 23 && int(h) >= 0); // H const test5 = !(0, isset_1.isset)(m) || (int(m) <= 59 && int(m) >= 0); // M if (outputAnError && !(test1 && test2 && test3 && test4 && test5)) throw new error_utils_1.DescriptiveError(`dateStringOrIntFormatInvalid`, { code: 422, origin: 'Date Int validator', dateStringOrInt: dateStringOrInt, extraInfo: 'Needs YYYYMMDD[HHMM] between 100001010000 and 999912312359', dateArr, isYearValid: test1, isMonthValid: test2, isDayValid: test3, isHourValid: test4, isMinutesValid: test5 }); return true; } exports.isDateIntOrStringValid = isDateIntOrStringValid; function isDateIsoOrObjectValid(dateIsoOrObj, outputAnError = false) { let dateObj = dateIsoOrObj; if (typeof dateIsoOrObj === 'string') dateObj = new Date(dateIsoOrObj); const valid = dateObj instanceof Date; if (outputAnError && !valid) throw new error_utils_1.DescriptiveError('dateIsoStringOrObjectIsNotValid', { code: 422, origin: 'Date Object validator', isoDate: dateIsoOrObj }); return valid; } exports.isDateIsoOrObjectValid = isDateIsoOrObjectValid; //# sourceMappingURL=date-utils.js.map