UNPKG

intl-dateformat

Version:

Format a date using Intl.DateTimeFormat goodness.

99 lines (91 loc) 3.94 kB
(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 }); }));