@technobuddha/library
Version:
A large library of useful functions
134 lines (125 loc) • 8.86 kB
text/typescript
import { secondsPerHour, secondsPerMinute } from '../constants';
import padNumber from '../padNumber';
import ordinal from '../ordinal';
import getDayOfYear from '../getDayOfYear';
import getWeekOfYear from '../getISOWeekOfYear';
import getTimezone from '../getTimezone';
import getJulian from '../getJulian';
import getDayOfWeek from '../getDayOfWeek';
const tokenizer = /[hHmDfO]{1,2}|[s]{1,3}|YYYY|YY|[Md]{1,4}|W(y|w{1,2}|d)|TZ|GMT|TH|T{1,2}|AM|PM|CE|BCE|AD|BC|E{2,3}|J|Q|"[^"]*"|'[^']*'/ug;
const masks: Readonly<Record<string, string>> = Object.freeze({
'default': 'YYYY-MM-DD hh:mm:ss.ff',
'rfc1123': 'ddd, DD MMM YYYY hh:mm:ss GMT',
'asctime': 'ddd MMM DD hh:mm:ss',
'shortDate': 'M/D/YY',
'mediumDate': 'MMM D, YYYY',
'longDate': 'MMMM D, YYYY',
'fullDate': 'dddd, MMMM D, YYYY',
'shortTime': 'H:mm TT',
'shortDateTime': 'M/D/YYYY H:mm TT',
'mediumTime': 'H:mm:ss TT',
'mediumDateTime': 'MMM D, YYYY H:mm:ss TT',
'longTime': 'H:mm:ss TT GMT',
'longDateTime': 'MMMM D, YYYY H:mm:ss TT GMT',
'ISODate': 'YYYY-MM-DD',
'ISODateTime': 'YYYY-MM-DD"T"hh:mm:ss',
'ISODateFull': 'YYYY-MM-DD"T"hh:mm:ss.ff',
'ISODateTimeZone': 'YYYY-MM-DD"T"hh:mm:ssTZ',
'ISODateFullZone': 'YYYY-MM-DD"T"hh:mm:ss.ffTZ',
'ISOTime': 'hh:mm:ss',
'ISOTimeFull': 'hh:mm:ss.ff',
'ISOTimeZone': 'hh:mm:ssTZ',
'ISOFullZone': 'hh:mm:ss.ffTZ',
'ISOWeek': 'Wy"W"Www-Wd',
'ISOWeekTime': 'Wy"W"Www-Wd"T"hh:mm:ss',
'ISOWeekFull': 'Wy"W"Www-Wd"T"hh:mm:ss.ff',
'ISOWeekTimeZone': 'Wy"W"Www-Wd"T"hh:mm:ssTZ',
'ISOWeekFullZone': 'Wy"W"Www-Wd"T"hh:mm:ss.ffTZ',
'ISOOrdinal': 'YYYY-OO',
'cookie': 'dddd, DD MMM YYYY hh:mm:ss GMT',
});
const dayOne = [ 'U', 'M', 'T', 'W', 'R', 'F', 'S' ];
const dayTwo = [ 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ];
const dayAbbrev = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat' ];
const dayName = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ];
const monthAbbrev = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
const monthName = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
type Options = {
/** Format the date in the UTC timezone */
UTC?: boolean;
};
/**
* Format a date
*
* @param input The date
* @param mask The mask
* @param __namedParameters see {@link Options}
* @default UTC false
*/
export function formatDate(input: Date, mask?: string, { UTC = false }: Options = {}): string {
mask = mask ? (mask in masks ? masks[mask] : mask) : masks.default;
const da = UTC ? input.getUTCDate() : input.getDate();
const dy = UTC ? input.getUTCDay() : input.getDay();
const mo = UTC ? input.getUTCMonth() : input.getMonth();
const yr = UTC ? input.getUTCFullYear() : input.getFullYear();
const ho = UTC ? input.getUTCHours() : input.getHours();
const mi = UTC ? input.getUTCMinutes() : input.getMinutes();
const se = UTC ? input.getUTCSeconds() : input.getSeconds();
const ms = UTC ? input.getUTCMilliseconds() : input.getMilliseconds();
const o = UTC ? 0 : input.getTimezoneOffset();
return mask.replace(
tokenizer,
token => {
switch(token) {
case 'h': return padNumber(ho, 0); //Hours (24)
case 'hh': return padNumber(ho, 2); //Hours (24)
case 'H': return padNumber(ho % 12 || 12, 0); //Hours (12)
case 'HH': return padNumber(ho % 12 || 12, 2); //Hours (12)
case 'm': return padNumber(mi, 0); //Minutes
case 'mm': return padNumber(mi, 2); //Minutes
case 's': return padNumber(se, 0); //Seconds
case 'ss': return padNumber(se, 2); //Seconds
case 'sss': return padNumber(ho * secondsPerHour + mi * secondsPerMinute + se, 0); //Seconds
case 'f': return padNumber(ms, 0); //Milliseconds
case 'ff': return padNumber(ms, 3); //Milliseconds
case 'YYYY': return padNumber(yr < 1 ? -yr + 1 : yr, 4); //Year
case 'YY': return padNumber((yr < 1 ? -yr + 1 : yr) % 100, 2); //Year
case 'M': return padNumber(mo + 1, 0); //Month
case 'MM': return padNumber(mo + 1, 2); //Month
case 'MMM': return monthAbbrev[mo]; //Month
case 'MMMM': return monthName[mo]; //Month
case 'D': return padNumber(da, 0); //Day
case 'DD': return padNumber(da, 2); //Day
case 'TH': return ordinal(da);
case 'd': return dayOne[dy]; //WeekDay
case 'dd': return dayTwo[dy];
case 'ddd': return dayAbbrev[dy]; //WeekDay
case 'dddd': return dayName[dy];
case 'O': return padNumber(getDayOfYear(input, { UTC }), 0); //Day of Year (1-366)
case 'OO': return padNumber(getDayOfYear(input, { UTC }), 3); //Day of Year (1-366)
case 'Wy': return padNumber(getWeekOfYear(input, { UTC }).year, 0);
case 'Ww': return padNumber(getWeekOfYear(input, { UTC }).week, 0); //Week of Year (1-53)
case 'Www': return padNumber(getWeekOfYear(input, { UTC }).week, 2); //
case 'Wd': return padNumber(getDayOfWeek(input, { UTC }), 0);
case 'TZ': return getTimezone(o);
case 'GMT': return getTimezone(o, { GMT: true });
case 'AM': return ho < 12 ? 'AM' : ''; //AM / --
case 'PM': return ho < 12 ? '' : 'PM'; //-- / PM
case 'T': return ho < 12 ? 'A' : 'P'; //A / P
case 'TT': return ho < 12 ? 'AM' : 'PM'; //AM / PM
case 'AD': return yr < 1 ? '' : 'AD'; //-- / AD
case 'BC': return yr < 1 ? 'BC' : ''; //BC / --
case 'CE': return yr < 1 ? '' : 'CE'; //-- / CE
case 'BCE': return yr < 1 ? 'BCE' : ''; //BCE / --
case 'EE': return yr < 1 ? 'BC' : 'AD'; //BC / AD
case 'EEE': return yr < 1 ? 'BCE' : 'CE'; //BCE / CE
case 'J': return padNumber(Math.floor(getJulian(input)), 0);
case 'Q': return padNumber(Math.floor((mo + 3) / 3), 0);
//RM: Month in roman numerals (UC);
//rm: Month in roman numerals (LC);
default: return token.slice(1, -1);
}
}
);
}
export default formatDate;