@rzl-zone/utils-js
Version:
A modern, lightweight set of JavaScript utility functions with TypeScript support for everyday development, crafted to enhance code readability and maintainability.
588 lines (575 loc) • 25.5 kB
JavaScript
/*!
* ====================================================
* Rzl Utils-JS.
* ----------------------------------------------------
* Version: 3.11.0.
* Author: Rizalvin Dwiky.
* Repository: https://github.com/rzl-zone/utils-js.
* ====================================================
*/
import { normalizeSpaces } from './chunk-ZVWZEGQP.js';
import { parseCurrencyString } from './chunk-2XSZ2ANI.js';
import { isFinite } from './chunk-CCJ2MSN7.js';
import { isInteger } from './chunk-WVSPXFTY.js';
import { isEmptyString } from './chunk-ULQPCIA2.js';
import { assertIsString } from './chunk-3T6VSWYX.js';
import { safeStableStringify, isDate } from './chunk-AXDYWO67.js';
import { isString, getPreciseType, assertIsPlainObject, hasOwnProp, isBoolean, isPlainObject, isNaN, isUndefined, isFunction, assertIsBoolean, isNil, isNumber, isNonEmptyString } from './chunk-MSUW5VHZ.js';
import { isSupportedCountry, AsYouType } from 'libphonenumber-js/max';
import { id, enUS } from 'date-fns/locale';
import { parse, format } from 'date-fns';
var formatIndianNumber = (numStr, separator) => {
const lastThree = numStr.slice(-3);
const rest = numStr.slice(0, -3);
if (!rest) return lastThree;
return rest.replace(/\B(?=(\d{2})+(?!\d))/g, separator) + separator + lastThree;
};
var formatCurrency = (value, options = {}) => {
if (!isString(value) && !isFinite(value)) {
throw new TypeError(
`First parameter (\`value\`) must be of type \`string\` or \`primitive-number\`, but received: \`${getPreciseType(
value
)}\`, with value: \`${safeStableStringify(value, {
keepUndefined: true
})}\`.`
);
}
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const decimal = hasOwnProp(options, "decimal") ? options.decimal : false;
const totalDecimal = hasOwnProp(options, "totalDecimal") ? options.totalDecimal : 2;
const endDecimal = hasOwnProp(options, "endDecimal") ? options.endDecimal : true;
const indianFormat = hasOwnProp(options, "indianFormat") ? options.indianFormat : false;
const suffixCurrency = hasOwnProp(options, "suffixCurrency") ? options.suffixCurrency : "";
const suffixDecimal = hasOwnProp(options, "suffixDecimal") ? options.suffixDecimal : "";
const roundedDecimal = hasOwnProp(options, "roundedDecimal") ? options.roundedDecimal : "round";
const negativeFormat = hasOwnProp(options, "negativeFormat") ? options.negativeFormat : "dash";
let separatorDecimals = hasOwnProp(options, "separatorDecimals") ? options.separatorDecimals : ",";
let separator = hasOwnProp(options, "separator") ? options.separator : ".";
if (!isString(separator) || !isString(separatorDecimals) || !isString(suffixCurrency) || !isString(suffixDecimal)) {
throw new TypeError(
`Parameter \`separator\`, \`separatorDecimals\`, \`suffixCurrency\` and \`suffixDecimal\` property of the \`options\` (second parameter) must be of type \`string\`, but received: ['separator': \`${getPreciseType(
separator
)}\`, 'separatorDecimals': \`${getPreciseType(
separatorDecimals
)}\`, 'suffixCurrency': \`${getPreciseType(
suffixCurrency
)}\`, 'suffixDecimal': \`${getPreciseType(suffixDecimal)}\`].`
);
}
if (!isBoolean(decimal) || !isBoolean(endDecimal) || !isBoolean(indianFormat)) {
throw new TypeError(
`Parameter \`decimal\`, \`endDecimal\` and \`indianFormat\` property of the \`options\` (second parameter) must be of type \`boolean\`, but received: ['decimal': \`${getPreciseType(
decimal
)}\`, 'endDecimal': \`${getPreciseType(
endDecimal
)}\`, 'indianFormat': \`${getPreciseType(indianFormat)}\`].`
);
}
if (!isInteger(totalDecimal)) {
throw new TypeError(
`Parameter \`totalDecimal\` property of the \`options\` (second parameter) must be of type \`integer-number\`, but received: \`${getPreciseType(
totalDecimal
)}\`, with value: \`${safeStableStringify(length, {
keepUndefined: true
})}\`.`
);
}
if (!(roundedDecimal === false || roundedDecimal === "round" || roundedDecimal === "ceil" || roundedDecimal === "floor")) {
throw new TypeError(
`Parameter \`roundedDecimal\` property of the \`options\` (second parameter) must be of type \`false\` or \`string\` must be one of "round" | "ceil" | "floor", but received: \`${getPreciseType(
roundedDecimal
)}\`, with value: \`${safeStableStringify(roundedDecimal, {
keepUndefined: true
})}\`.`
);
}
if (!(negativeFormat === "abs" || negativeFormat === "brackets" || negativeFormat === "dash" || isPlainObject(negativeFormat))) {
throw new TypeError(
`Parameter \`negativeFormat\` property of the \`options\` (second parameter) must be of type \`string\` must be one of "abs" | "brackets" | "dash" or \`plain-object\` type, but received: \`${getPreciseType(
negativeFormat
)}\`, with value: \`${safeStableStringify(negativeFormat, {
keepUndefined: true
})}\`.`
);
}
const rawNum = isString(value) ? parseCurrencyString(value) : value;
if (isNaN(rawNum)) {
throw new TypeError(
`First parameter (\`value\`) could not be parsed into a valid \`number\`.`
);
}
let integerPart = "";
let decimalPartRaw = "";
let num = Math.abs(rawNum);
const factor = Math.pow(10, totalDecimal);
if (roundedDecimal) {
const scaled = num * factor;
switch (roundedDecimal) {
case "round":
num = Math.round(scaled) / factor;
break;
case "ceil":
num = Math.ceil(scaled) / factor;
break;
case "floor":
num = Math.floor(scaled) / factor;
break;
}
}
if (roundedDecimal) {
[integerPart, decimalPartRaw] = num.toFixed(totalDecimal).split(".");
decimalPartRaw = decimalPartRaw ?? "".padEnd(totalDecimal, "0");
} else {
const split = String(num).split(".");
integerPart = split[0];
decimalPartRaw = (split[1] || "").slice(0, totalDecimal).padEnd(totalDecimal, "0");
}
let formattedInteger;
if (indianFormat) {
separator = ",";
separatorDecimals = ".";
formattedInteger = (suffixCurrency.trim().length ? suffixCurrency : "") + formatIndianNumber(integerPart, separator);
} else {
formattedInteger = (suffixCurrency.trim().length ? suffixCurrency : "") + integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
}
if (decimal && !isUndefined(decimalPartRaw) && totalDecimal > 0) {
let formattedDecimal = separatorDecimals + decimalPartRaw;
if (endDecimal) formattedDecimal += suffixDecimal;
formattedInteger += formattedDecimal;
}
if (rawNum < 0) {
if (negativeFormat === "dash") {
formattedInteger = "-" + formattedInteger;
} else if (negativeFormat === "brackets") {
formattedInteger = "(" + formattedInteger + ")";
} else if (negativeFormat === "abs") ; else if (isPlainObject(negativeFormat)) {
if (hasOwnProp(negativeFormat, "custom")) {
const formatCustomNegative = negativeFormat.custom;
if (!isFunction(formatCustomNegative)) {
throw new TypeError(
`Parameter \`negativeFormat.custom\` property of the \`options\` (second parameter) must be of type function: \`(formatted: string) => string\`, but received: \`${getPreciseType(
formatCustomNegative
)}\`.`
);
}
const result = formatCustomNegative(formattedInteger);
assertIsString(result, {
message: ({ currentType, validType }) => `Parameter \`negativeFormat.custom\` property of the \`options\` (second parameter) expected return a \`${validType}\` type value, but received: \`${currentType}\`.`
});
formattedInteger = result;
} else {
const formatStyleNegative = negativeFormat.style || "dash";
const formatSpaceNegative = !isUndefined(negativeFormat.space) ? negativeFormat.space : false;
assertIsBoolean(formatSpaceNegative, {
message: ({ currentType, validType }) => `Parameter \`negativeFormat.space\` property of the \`options\` (second parameter) must be of type \`${validType} or undefined\`, but received: \`${currentType}\`.`
});
if (!(formatStyleNegative === "abs" || formatStyleNegative === "brackets" || formatStyleNegative === "dash")) {
throw new TypeError(
`Parameter \`negativeFormat.style\` property of the \`options\` (second parameter) must be of type \`string\` must be of type "abs" | "brackets" | "dash", but received: \`${getPreciseType(
formatStyleNegative
)}\`, with value: \`${safeStableStringify(formatStyleNegative, {
keepUndefined: true
})}\`.`
);
}
switch (formatStyleNegative) {
case "dash":
formattedInteger = "-" + (formatSpaceNegative ? " " : "") + formattedInteger;
break;
case "brackets":
formattedInteger = formatSpaceNegative ? `( ${formattedInteger} )` : `(${formattedInteger})`;
break;
}
}
}
}
return formattedInteger;
};
var formatNumber = (value, separator = ",") => {
if (!isString(value) && !isFinite(value)) {
throw new TypeError(
`First parameter (\`value\`) must be of type \`string\` or \`primitive number\`, but received: \`${getPreciseType(
value
)}\`.`
);
}
if (!isString(separator)) {
throw new TypeError(
`Second parameter (\`separator\`) must be of type \`string\` or empty as \`undefined\`, but received: \`${getPreciseType(
separator
)}\`.`
);
}
separator = isString(separator) ? separator : ",";
const decimalSeparator = separator === "." ? "," : separator === "," ? "." : ".";
const stringValue = value.toString().trim();
const lastDot = stringValue.lastIndexOf(".");
const lastComma = stringValue.lastIndexOf(",");
let actualDecimal = "";
if (lastDot > lastComma) {
actualDecimal = ".";
} else if (lastComma > lastDot) {
actualDecimal = ",";
}
let integerPart = stringValue;
let decimalPart = "";
if (actualDecimal) {
const parts = stringValue.split(actualDecimal);
integerPart = parts.slice(0, -1).join(actualDecimal);
decimalPart = parts.slice(-1)[0];
}
integerPart = integerPart.replace(/[^\d]/g, "");
const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
return decimalPart ? `${formattedInteger}${decimalSeparator}${decimalPart}` : formattedInteger;
};
var parsingAsYouType = (value, defaultCountry) => {
let parsed;
try {
parsed = new AsYouType(defaultCountry);
parsed.input(value);
return parsed;
} catch {
parsed?.reset();
return void 0;
}
};
var isValidParseAsYouType = (parsedAsYouType) => {
const parsed = !!parsedAsYouType?.isValid() && !!parsedAsYouType.getNumber();
return parsed;
};
function formatPhoneNumber(value, options = {}) {
if (isNil(value)) return "";
if (!isString(value) && !isNumber(value)) {
throw new TypeError(
`First parameter (\`value\`) must be of type \`string\`, \`number\`, \`null\` or \`undefined\`, but received: \`${getPreciseType(
value
)}\`.`
);
}
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const takeNumberOnly = hasOwnProp(options, "takeNumberOnly") ? options.takeNumberOnly : false;
const checkValidOnly = hasOwnProp(options, "checkValidOnly") ? options.checkValidOnly : false;
const defaultCountry = hasOwnProp(
options,
"defaultCountry"
) ? options.defaultCountry : void 0;
const separator = hasOwnProp(options, "separator") ? options.separator : " ";
const prependPlusCountryCode = hasOwnProp(options, "prependPlusCountryCode") ? options.prependPlusCountryCode : true;
const outputFormat = hasOwnProp(options, "outputFormat") ? options.outputFormat : "INTERNATIONAL";
const openingNumberCountry = hasOwnProp(options, "openingNumberCountry") ? options.openingNumberCountry : "";
const closingNumberCountry = hasOwnProp(options, "closingNumberCountry") ? options.closingNumberCountry : "";
if (!isBoolean(takeNumberOnly) || !isBoolean(checkValidOnly) || !isBoolean(prependPlusCountryCode)) {
throw new TypeError(
`Parameter \`takeNumberOnly\`, \`checkValidOnly\` and \`prependPlusCountryCode\` property of the \`options\` (second parameter) must be of type \`boolean\` or unset as \`undefined\` value, but received: ['takeNumberOnly': \`${getPreciseType(
takeNumberOnly
)}\`, 'checkValidOnly': \`${getPreciseType(
checkValidOnly
)}\`, 'prependPlusCountryCode': \`${getPreciseType(prependPlusCountryCode)}\`].`
);
}
if (!isUndefined(defaultCountry) && !isSupportedCountry(defaultCountry)) {
throw new TypeError(
`Parameter \`defaultCountry\` property of the \`options\` (second parameter) must be of type \`string\` as \`CountryCode\` (ISO-3166-1 alpha-2) or unset as \`undefined\` value, but received: \`${getPreciseType(
defaultCountry
)}\`, with value: \`${safeStableStringify(defaultCountry, {
keepUndefined: true
})}\`.
See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements, for all ISO 3166-1 alpha-2 code.`
);
}
if (!["INTERNATIONAL", "NATIONAL", "RFC3966", "E.164"].includes(outputFormat)) {
throw new TypeError(
`Parameter \`outputFormat\` property of the \`options\` (second parameter) must be of type \`string\` as \`OutputFormat\` ("NATIONAL" | "INTERNATIONAL" | "E.164" | "RFC3966") or unset as \`undefined\` (default value to: \`INTERNATIONAL\`) value, but received: \`${getPreciseType(
outputFormat
)}\`, with value: ${safeStableStringify(outputFormat, { keepUndefined: true })}.`
);
}
if (!isString(separator) || !isString(openingNumberCountry) || !isString(closingNumberCountry)) {
throw new TypeError(
`Parameter \`separator\`, \`plusNumberCountry\`, \`openingNumberCountry\` and \`closingNumberCountry\` property of the \`options\` (second parameter) must be of type \`string\` or unset as \`undefined\` value, but received: ['separator': \`${getPreciseType(
separator
)}\`,'openingNumberCountry': \`${getPreciseType(
openingNumberCountry
)}\`, 'closingNumberCountry': \`${getPreciseType(closingNumberCountry)}\`].`
);
}
if (!isString(value)) value = String(value);
const parsedPhoneNumber = parsingAsYouType(value, defaultCountry);
const validPhoneNumber = isValidParseAsYouType(parsedPhoneNumber);
if (checkValidOnly) return validPhoneNumber;
if (!validPhoneNumber) return "";
if (takeNumberOnly) {
return parsedPhoneNumber.getNumber().formatNational().replace(/\D/g, "");
}
const num = parsedPhoneNumber.getNumber();
const intlNumb = num.format(outputFormat);
if (outputFormat === "INTERNATIONAL") {
const [cc, ...rest] = intlNumb.split(" ");
const countryCode = prependPlusCountryCode ? cc : cc.replace(/^\++/, "");
const restWithSeparator = rest.join(separator);
if (isNonEmptyString(openingNumberCountry) && isNonEmptyString(closingNumberCountry)) {
return `${openingNumberCountry}${countryCode}${closingNumberCountry} ${restWithSeparator}`;
}
return `${countryCode} ${restWithSeparator}`;
}
if (outputFormat === "NATIONAL") {
const restWithSeparator = intlNumb.split(" ").join(separator);
return `${restWithSeparator}`;
}
return intlNumb;
}
var hashSeedGenerate = (mode, email) => {
const generateSeed = () => {
let hash = 0;
for (let i = 0; i < email.length; i++) {
hash = (hash << 5) - hash + email.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
};
return mode === "fixed" ? generateSeed() : void 0;
};
var _censor = (str, minCensor, maxPercentage, hashSeed) => {
if (str.length <= minCensor) return "*".repeat(str.length);
const strArr = str.split("");
const totalCensor = Math.max(minCensor, Math.ceil(str.length * maxPercentage));
const indexes = /* @__PURE__ */ new Set();
let i = 0;
while (indexes.size < totalCensor) {
const idx = !isUndefined(hashSeed) ? (hashSeed + str.length + i * 31) % str.length : Math.floor(Math.random() * str.length);
indexes.add(idx);
i++;
}
for (const index of indexes) {
strArr[index] = "*";
}
return strArr.join("");
};
var censorEmail = (email, options = {}) => {
if (!isNonEmptyString(email)) return "";
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const mode = hasOwnProp(options, "mode") ? options.mode : "fixed";
if (mode !== "random" && mode !== "fixed") {
throw new TypeError(
`Parameter \`mode\` property of the \`options\` (second parameter) must be one of "fixed" or "random", but received: \`${getPreciseType(
mode
)}\`, with value: \`${safeStableStringify(mode, {
keepUndefined: true
})}\`.`
);
}
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(email)) return "";
const [local, domain] = email.split("@");
const domainParts = domain.split(".");
if (domainParts.length < 2) return "";
const [domainName, ...tldParts] = domainParts;
const tld = tldParts.join(".");
const hashSeed = hashSeedGenerate(mode, email);
const localMinCensor = local.length < 4 ? 1 : 2;
const domainMinCensor = domainName.length < 4 ? 1 : 2;
const censoredLocal = _censor(local, localMinCensor, 0.6, hashSeed);
const censoredDomain = _censor(domainName, domainMinCensor, 0.5, hashSeed);
const censoredTLD = tld.length <= 2 ? tld : _censor(tld, 1, 0.4, hashSeed);
return `${censoredLocal}@${censoredDomain}.${censoredTLD}`;
};
function chunkString(subject, limiter, options = {}) {
if (isNil(subject) || limiter <= 0) return subject;
assertIsString(subject, {
message: ({ currentType, validType }) => `First parameter (\`subject\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
if (!isInteger(limiter)) {
throw new TypeError(
`Second parameter (\`limiter\`) must be of type \`integer-number\`, but received: \`${getPreciseType(
limiter
)}\`, with value: \`${safeStableStringify(limiter, {
keepUndefined: true
})}\`.`
);
}
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Third parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const separator = hasOwnProp(options, "separator") ? options.separator : " ";
const reCountAfterSpace = hasOwnProp(options, "reCountAfterSpace") ? options.reCountAfterSpace : false;
assertIsString(separator, {
message: ({ currentType, validType }) => `Parameter \`separator\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
assertIsBoolean(reCountAfterSpace, {
message: ({ currentType, validType }) => `Parameter \`reCountAfterSpace\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
subject = normalizeSpaces(subject);
if (!reCountAfterSpace) {
let result = "";
let currentCount = 0;
for (let i = 0; i < subject.length; i++) {
const char = subject[i];
if (currentCount === limiter) {
result += separator;
currentCount = 0;
}
result += char;
currentCount++;
}
return result;
}
const words = subject.split(" ");
const finalSegments = [];
let currentGroup = [];
let wordsInCurrentGroupCount = 0;
for (let i = 0; i < words.length; i++) {
const word = words[i];
let processedWord = "";
let charCountInWord = 0;
for (let j = 0; j < word.length; j++) {
processedWord += word[j];
charCountInWord++;
if (charCountInWord === limiter && j < word.length - 1) {
processedWord += separator;
charCountInWord = 0;
}
}
currentGroup.push(processedWord);
wordsInCurrentGroupCount++;
if (wordsInCurrentGroupCount === limiter || i === words.length - 1) {
finalSegments.push(currentGroup.join(separator));
currentGroup = [];
wordsInCurrentGroupCount = 0;
}
}
return finalSegments.join(" ");
}
var truncateString = (text, options = {}) => {
if (!isNonEmptyString(text)) return "";
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Seconds parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const trim = hasOwnProp(options, "trim") ? options.trim : true;
const length2 = hasOwnProp(options, "length") ? options.length : 10;
let ending = hasOwnProp(options, "ending") ? options.ending : "...";
if (!isInteger(length2)) {
throw new TypeError(
`Parameter \`length\` property of the \`options\` (second parameter) must be of type \`integer-number\`, but received: \`${getPreciseType(
length2
)}\`, with value: \`${safeStableStringify(length2, {
keepUndefined: true
})}\`.`
);
}
if (length2 < 1) return "";
assertIsString(ending, {
message: ({ currentType, validType }) => `Parameter \`ending\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
assertIsBoolean(trim, {
message: ({ currentType, validType }) => `Parameter \`trim\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
if (isEmptyString(ending)) {
ending = "...";
} else {
ending = ending.trim();
}
const original = trim ? text.trim() : text;
const originalTrimmedLength = original.length;
if (originalTrimmedLength <= length2) return original;
const sliced = original.slice(0, length2);
const cleanSliced = trim ? sliced : sliced.trimEnd();
return cleanSliced + ending;
};
var formatDateFns = (date, options = {}) => {
if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) return null;
if (!isPlainObject(options)) {
options = {};
}
const { inputFormat, locale = "en", inputLocale = "en", ...restOptions } = options;
const format$1 = hasOwnProp(options, "format") && isNonEmptyString(options.format) ? options.format : "dd MMM yyyy - HH:mm:ss";
let parsedDate;
try {
if (isNonEmptyString(date) && inputFormat && inputLocale) {
const valueOfInputLocale = isNonEmptyString(inputLocale) ? inputLocale === "id" ? id : enUS : inputLocale;
parsedDate = parse(date, inputFormat, /* @__PURE__ */ new Date(), {
locale: valueOfInputLocale
});
} else {
parsedDate = new Date(date);
}
if (isNaN(parsedDate.getTime())) return null;
const valueOfLocale = isNonEmptyString(locale) ? locale === "id" ? id : enUS : locale;
return format(parsedDate, format$1, {
...restOptions,
locale: valueOfLocale
});
} catch {
return null;
}
};
var formatDateIntl = (date, options) => {
if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) return null;
const parsedDate = new Date(date);
if (isNaN(parsedDate.getTime())) return null;
if (!isPlainObject(options)) {
options = {};
}
const { locale = "en-US", ...restProps } = options;
try {
return new Intl.DateTimeFormat(
isNonEmptyString(locale) ? locale.trim() : "en-US",
restProps
).format(parsedDate);
} catch {
return null;
}
};
var formatDateTime = (date, format) => {
if (isNil(format)) {
format = "YYYY-MM-DD hh:mm:ss";
}
if (!isString(format)) return null;
if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) {
return null;
}
try {
const parsedDate = new Date(date);
if (isNaN(parsedDate.getTime())) return null;
const pad2 = (n) => n.toString().padStart(2, "0");
const map = {
YYYY: parsedDate.getFullYear().toString(),
MM: pad2(parsedDate.getMonth() + 1),
DD: pad2(parsedDate.getDate()),
hh: pad2(parsedDate.getHours()),
mm: pad2(parsedDate.getMinutes()),
ss: pad2(parsedDate.getSeconds())
};
const result = Object.entries(map).reduce(
(prev, [key, value]) => prev.split(key).join(value),
format
);
return !result.includes("NaN") ? result : null;
} catch {
return null;
}
};
var getGMTOffset = (date) => {
try {
if (isNil(date) || isString(date) && isEmptyString(date)) {
date = /* @__PURE__ */ new Date();
} else if (!(isDate(date) || isNonEmptyString(date))) {
return "0";
}
const parsedDate = new Date(date);
if (isNaN(parsedDate.getTime())) return "0";
const padZero = (num) => num.toString().padStart(2, "0");
let offset = parsedDate.getTimezoneOffset();
const sign = offset < 0 ? "+" : "-";
offset = Math.abs(offset);
return `${sign}${padZero(Math.floor(offset / 60))}${padZero(offset % 60)}`;
} catch {
return "0";
}
};
export { censorEmail, chunkString, formatCurrency, formatDateFns, formatDateIntl, formatDateTime, formatNumber, formatPhoneNumber, getGMTOffset, truncateString };