intl-dateformat
Version:
Format a date using Intl.DateTimeFormat goodness.
99 lines (91 loc) • 3.94 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global['intl-dateformat'] = {}));
}(this, function (exports) { 'use strict';
const defaultPattern = '[YMDdAaHhms]+';
const identity = (x) => x;
const formatters = {
YYYY: parts => parts.year,
YY: parts => parts.year.slice(-2),
MMMM: parts => parts.lmonth,
MMM: parts => parts.lmonth.slice(0, 3),
MM: parts => parts.month,
DD: parts => parts.day,
dddd: parts => parts.weekday,
ddd: parts => parts.weekday.slice(0, 3),
A: parts => parts.dayPeriod,
a: parts => parts.dayPeriod.toLowerCase(),
HH: parts => ('0' + (Number(parts.lhour) % 24)).slice(-2),
hh: parts => parts.hour,
mm: parts => parts.minute,
ss: parts => parts.second
};
const createCustomPattern = (customFormatters) => Object.keys(customFormatters).reduce((pattern, key) => `|${key}`, '');
function formatDate(customFormatters, format, parts, date) {
const customPattern = createCustomPattern(customFormatters);
const patternRegexp = new RegExp(`${defaultPattern}${customPattern}`, 'g');
const allFormatters = Object.assign({}, formatters, customFormatters);
return format.replace(patternRegexp, (mask) => (allFormatters[mask] || identity)(parts, date));
}
const parsers = new Map();
const intlFormattersOptions = [
{
weekday: 'long',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
},
{
month: 'long',
hour: '2-digit',
hour12: false,
},
];
const createIntlFormatterWith = (options) => intlFormattersOptions.map((intlFormatterOptions) => new Intl.DateTimeFormat(options.locale, Object.assign({}, intlFormatterOptions, { timeZone: options.timezone })));
const longTokensTransformer = (token) => (token.type !== 'literal' ? { type: `l${token.type}`, value: token.value } : token);
const datePartsReducer = (parts, token) => {
parts[token.type] = token.value;
return parts;
};
const tokenize = (intlFormatter, date) => intlFormatter.formatToParts(date).filter((token) => token.type !== 'literal');
const normalize = (parts) => {
parts.dayPeriod = parts.dayPeriod || parts.dayperiod || '';
delete parts.dayperiod;
parts.lhour = ('0' + (Number(parts.lhour) % 24)).slice(-2);
return parts;
};
const createParser = (options) => {
const [intlFormatter, intlFormatterLong] = createIntlFormatterWith(options);
return function parseDateImpl(date) {
const tokens = tokenize(intlFormatter, date);
const longTokens = tokenize(intlFormatterLong, date).map(longTokensTransformer);
const allTokens = [...tokens, ...longTokens];
const parts = allTokens.reduce(datePartsReducer, {});
return normalize(parts);
};
};
function parseDate(date, options = {}) {
const key = `${options.locale}${options.timezone}`;
let parser = parsers.get(key);
if (!parser) {
parser = createParser(options);
parsers.set(key, parser);
}
return parser(date);
}
function createDateFormatter(customFormatters) {
return function intlFormatDate(date, format, options) {
const tokens = parseDate(date, options);
const output = formatDate(customFormatters, format, tokens, date);
return output;
};
}
var index = createDateFormatter({});
exports.default = index;
exports.createDateFormatter = createDateFormatter;
Object.defineProperty(exports, '__esModule', { value: true });
}));