Skip to content

Instantly share code, notes, and snippets.

@westc
Created October 18, 2023 02:45
Show Gist options
  • Save westc/fed8f6a71a63bcaa2159d3638f262cfe to your computer and use it in GitHub Desktop.
Save westc/fed8f6a71a63bcaa2159d3638f262cfe to your computer and use it in GitHub Desktop.
Uses the new Intl API to format a date as a string.
var formatIntlDate = (() => {
const CODE_TO_PROP_NAME = {
Y: ['year', 'numeric'],
M: ['month', 'long'],
D: ['day', 'numeric'],
WD: ['weekday', 'long'],
h: ['hour', '2-digit'],
m: ['minute', '2-digit'],
s: ['second', '2-digit'],
ms: ['fractionalSecondDigits', 3],
DS: ['dateStyle', 'full'],
TS: ['timeStyle', 'full'],
};
const CODES = Object.keys(CODE_TO_PROP_NAME).sort(
(a, b) => a.length === b.length
? a < b ? -1 : 1
: (b.length - a.length)
).join('|');
const RGX = new RegExp(
`%(${CODES})(?:<(numeric|2-digit|long|narrow|short|medium|1|2|3)>)?|([%<>])\\3`,
'g'
);
/**
* Uses the new Intl API to format a date as a string.
* @param {Date} date
* @param {?FormatIntlDateOptions=} opt_options
* @returns {string}
*/
function formatIntlDate(date, opt_options) {
const {timeZone, format, locale, dateStyle, timeStyle} = opt_options ?? {};
if ('string' === typeof format) {
return format.replace(RGX, (m, id, format, escaped) => {
if (escaped) return escaped;
try {
const [name, defaultValue] = CODE_TO_PROP_NAME[id];
return new Intl.DateTimeFormat(locale, {
[name]: format || defaultValue,
timeZone
}).format(date);
} catch(e){}
return m;
});
}
return new Intl.DateTimeFormat(
locale,
{
dateStyle: dateStyle ?? 'full',
timeStyle: timeStyle ?? 'full',
timeZone
}
).format(date);
}
/**
* @typedef FormatIntlDateOptions
* @property {?string=} timeZone
* @property {?string=} format
* @property {?string=} locale
* @property {?("full"|"long"|"medium"|"short")=} dateStyle
* @property {?("full"|"long"|"medium"|"short")=} timeStyle
*/
return formatIntlDate;
})();
console.log(
formatIntlDate(new Date, {
format: 'It is currently %WD<short> (AKA "%WD") in Adelaide.',
timeZone: 'Australia/Adelaide'
})
);
console.log(
formatIntlDate(new Date, {
format: 'It is currently %WD<short> (AKA "%WD") in Hawaii.',
timeZone: 'US/Hawaii'
})
);
for (const locale of ['en', 'en-AU', 'en-GB', 'en-US', 'es', 'es-419', 'es-BR', 'es-ES', 'es-MX', 'es-BO', 'es-AR', 'es-CO', 'pt', 'pt-BR', 'pt-PT', 'pt-AO', 'pt-CH', 'pt-CV', 'pt-GQ', 'pt-GW', 'pt-LU', 'pt-MO', 'pt-MZ', 'pt-ST', 'pt-TL', 'qu', 'qu-BO', 'qu-EC', 'qu-PE', 'sr', 'vi', 'vi-VN', 'sv', 'sw', 'zh', 'de', 'da', 'cs', 'ca', 'bo', 'bg', 'ar', 'af', 'el', 'fil', 'ga', 'fr', 'gl', 'haw', 'he', 'it', 'ko', 'mk', 'nds', 'nl', 'ru', 'sn', 'uk']) {
console.log(`${locale}:\n\t${formatIntlDate(new Date, {locale})}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment