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
JavaScript
"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