nhb-toolbox
Version:
A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.
157 lines (156 loc) • 5.23 kB
JavaScript
import { isDate, isObjectWithKeys, isValidArray } from '../guards/non-primitives.js';
import { isNonEmptyString, isString } from '../guards/primitives.js';
import { isDateString } from '../guards/specials.js';
import { getOrdinal } from '../number/utilities.js';
import { BN_MONTH_TABLES, BN_SEASONS, BN_YEAR_OFFSET, DAYS, MONTHS, MS_PER_DAY, SORTED_TIME_FORMATS, } from './constants.js';
import { isLeapYear, isValidUTCOffset } from './guards.js';
export function _formatDateCore(format, dateComponents) {
const tokenRegex = new RegExp(`^(${SORTED_TIME_FORMATS.join('|')})`);
let result = '';
let i = 0;
while (i < format.length) {
if (format[i] === '[') {
const end = format.indexOf(']', i);
if (end !== -1) {
result += format.slice(i + 1, end);
i = end + 1;
continue;
}
}
const match = tokenRegex.exec(format.slice(i));
if (match) {
result += dateComponents[match[0]] ?? match[0];
i += match[0].length;
}
else {
result += format[i];
i++;
}
}
return result;
}
export function _formatDate(format, year, month, day, date, hours, minutes, seconds, milliseconds, offset) {
const paddedYear = _padZero(year, 4);
const dateComponents = {
YYYY: paddedYear,
YY: paddedYear.slice(-2),
yyyy: paddedYear,
yy: paddedYear.slice(-2),
M: String(month + 1),
MM: _padZero(month + 1),
mmm: MONTHS[month].slice(0, 3),
mmmm: MONTHS[month],
d: DAYS[day].slice(0, 2),
dd: DAYS[day].slice(0, 3),
ddd: DAYS[day],
D: String(date),
DD: _padZero(date),
Do: getOrdinal(date),
H: String(hours),
HH: _padZero(hours),
h: String(hours % 12 || 12),
hh: _padZero(hours % 12 || 12),
m: String(minutes),
mm: _padZero(minutes),
s: String(seconds),
ss: _padZero(seconds),
ms: String(milliseconds),
mss: _padZero(milliseconds, 3),
a: hours < 12 ? 'am' : 'pm',
A: hours < 12 ? 'AM' : 'PM',
Z: offset,
ZZ: offset,
};
return _formatDateCore(format, dateComponents);
}
export function _normalizeOffset(timeStr) {
return timeStr.replace(/([+-]\d{2})(?!:)/, '$1:00');
}
export const _toSeconds = (ms) => Math.floor(ms / 1000);
export const _secToDate = (sec) => new Date(sec * 1000);
export function _resolveNativeTzName(tzId, type, date) {
try {
const parts = new Intl.DateTimeFormat('en', {
timeZone: tzId,
timeZoneName: type,
}).formatToParts(date);
return parts.find((p) => p.type === 'timeZoneName')?.value;
}
catch {
return undefined;
}
}
export function _gmtToUtcOffset(gmt) {
return gmt === 'GMT' ? 'UTC+00:00' : gmt?.replace(/^GMT/, 'UTC');
}
export function _getBnSeason(month, locale) {
const season = BN_SEASONS[Math.floor(month / 2)];
return (locale === 'en' ? season.en : season.bn);
}
export function _isBnLeapYear(by, gy, v) {
return v === 'revised-1966' ? by % 4 === 2 : isLeapYear(gy);
}
export function _extractDateUnits(date) {
const month = date.getMonth();
return {
gy: date.getFullYear(),
$gm: month,
gm: (month + 1),
gd: date.getDate(),
wd: date.getDay(),
};
}
export function _getGregBaseYear(date) {
const { gy, gm, gd } = _extractDateUnits(date);
return gm < 4 || (gm === 4 && gd < 14) ? gy - 1 : gy;
}
export function _getBnYear(date) {
return _getGregBaseYear(date) - BN_YEAR_OFFSET;
}
export function _getUtcTs(date) {
const { gy, $gm, gd } = _extractDateUnits(date);
return Date.UTC(gy, $gm, gd);
}
export function _getElapsedDays(date) {
return Math.floor((_getUtcTs(date) - Date.UTC(_getGregBaseYear(date), 3, 14)) / MS_PER_DAY);
}
export function _bnDaysMonthIdx(date, variant) {
const v = variant ?? 'revised-2019';
const table = _isBnLeapYear(_getBnYear(date), date.getFullYear(), v)
? BN_MONTH_TABLES?.[v].leap
: BN_MONTH_TABLES?.[v].normal;
let days = _getElapsedDays(date);
let monthIdx = 0;
while (days >= table[monthIdx]) {
days -= table[monthIdx];
monthIdx++;
}
return { days, monthIdx };
}
export function _padZero(value, length = 2) {
return String(value).padStart(length, '0');
}
export function _padShunno(str, length = 2) {
return str.padStart(length, '০');
}
export function _dateArgsToDate(value) {
return new Date(isDate(value)
? value
: isString(value)
? value.replace(/['"]/g, '')
: (value ?? Date.now()));
}
export function _hasChronosProperties(value) {
return (isObjectWithKeys(value, [
'origin',
'native',
'utcOffset',
'timeZoneName',
'timeZoneId',
]) &&
isNonEmptyString(value.origin) &&
(isDate(value.native) || isDateString(value.native)) &&
isValidUTCOffset(value.utcOffset) &&
isNonEmptyString(value.timeZoneName) &&
(isNonEmptyString(value.timeZoneId) || isValidArray(value.timeZoneId)));
}