@formatjs/intl-datetimeformat
Version:
Intl.DateTimeFormat polyfill
194 lines (193 loc) • 8.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.InitializeDateTimeFormat = InitializeDateTimeFormat;
var ecma402_abstract_1 = require("@formatjs/ecma402-abstract");
var intl_localematcher_1 = require("@formatjs/intl-localematcher");
var BasicFormatMatcher_1 = require("./BasicFormatMatcher");
var BestFitFormatMatcher_1 = require("./BestFitFormatMatcher");
var DateTimeStyleFormat_1 = require("./DateTimeStyleFormat");
var ToDateTimeOptions_1 = require("./ToDateTimeOptions");
var utils_1 = require("./utils");
function isTimeRelated(opt) {
for (var _i = 0, _a = ['hour', 'minute', 'second']; _i < _a.length; _i++) {
var prop = _a[_i];
var value = opt[prop];
if (value !== undefined) {
return true;
}
}
return false;
}
function resolveHourCycle(hc, hcDefault, hour12) {
if (hc == null) {
hc = hcDefault;
}
if (hour12 !== undefined) {
if (hour12) {
if (hcDefault === 'h11' || hcDefault === 'h23') {
hc = 'h11';
}
else {
hc = 'h12';
}
}
else {
(0, ecma402_abstract_1.invariant)(!hour12, 'hour12 must not be set');
if (hcDefault === 'h11' || hcDefault === 'h23') {
hc = 'h23';
}
else {
hc = 'h24';
}
}
}
return hc;
}
var TYPE_REGEX = /^[a-z0-9]{3,8}$/i;
/**
* https://tc39.es/ecma402/#sec-initializedatetimeformat
* @param dtf DateTimeFormat
* @param locales locales
* @param opts options
*/
function InitializeDateTimeFormat(dtf, locales, opts, _a) {
var getInternalSlots = _a.getInternalSlots, availableLocales = _a.availableLocales, localeData = _a.localeData, getDefaultLocale = _a.getDefaultLocale, getDefaultTimeZone = _a.getDefaultTimeZone, relevantExtensionKeys = _a.relevantExtensionKeys, tzData = _a.tzData, uppercaseLinks = _a.uppercaseLinks;
// @ts-ignore
var requestedLocales = (0, ecma402_abstract_1.CanonicalizeLocaleList)(locales);
var options = (0, ToDateTimeOptions_1.ToDateTimeOptions)(opts, 'any', 'date');
var opt = Object.create(null);
var matcher = (0, ecma402_abstract_1.GetOption)(options, 'localeMatcher', 'string', ['lookup', 'best fit'], 'best fit');
opt.localeMatcher = matcher;
var calendar = (0, ecma402_abstract_1.GetOption)(options, 'calendar', 'string', undefined, undefined);
if (calendar !== undefined && !TYPE_REGEX.test(calendar)) {
throw new RangeError('Malformed calendar');
}
var internalSlots = getInternalSlots(dtf);
opt.ca = calendar;
var numberingSystem = (0, ecma402_abstract_1.GetOption)(options, 'numberingSystem', 'string', undefined, undefined);
if (numberingSystem !== undefined && !TYPE_REGEX.test(numberingSystem)) {
throw new RangeError('Malformed numbering system');
}
opt.nu = numberingSystem;
var hour12 = (0, ecma402_abstract_1.GetOption)(options, 'hour12', 'boolean', undefined, undefined);
var hourCycle = (0, ecma402_abstract_1.GetOption)(options, 'hourCycle', 'string', ['h11', 'h12', 'h23', 'h24'], undefined);
if (hour12 !== undefined) {
// @ts-ignore
hourCycle = null;
}
opt.hc = hourCycle;
var r = (0, intl_localematcher_1.ResolveLocale)(availableLocales, requestedLocales, opt, relevantExtensionKeys, localeData, getDefaultLocale);
internalSlots.locale = r.locale;
calendar = r.ca;
internalSlots.calendar = calendar;
internalSlots.hourCycle = r.hc;
internalSlots.numberingSystem = r.nu;
var dataLocale = r.dataLocale;
internalSlots.dataLocale = dataLocale;
var timeZone = options.timeZone;
if (timeZone !== undefined) {
timeZone = String(timeZone);
if (!(0, ecma402_abstract_1.IsValidTimeZoneName)(timeZone, {
zoneNamesFromData: Object.keys(tzData),
uppercaseLinks: uppercaseLinks,
})) {
throw new RangeError('Invalid timeZoneName');
}
timeZone = (0, ecma402_abstract_1.CanonicalizeTimeZoneName)(timeZone, {
zoneNames: Object.keys(tzData),
uppercaseLinks: uppercaseLinks,
});
}
else {
timeZone = getDefaultTimeZone();
}
internalSlots.timeZone = timeZone;
opt = Object.create(null);
opt.weekday = (0, ecma402_abstract_1.GetOption)(options, 'weekday', 'string', ['narrow', 'short', 'long'], undefined);
opt.era = (0, ecma402_abstract_1.GetOption)(options, 'era', 'string', ['narrow', 'short', 'long'], undefined);
opt.year = (0, ecma402_abstract_1.GetOption)(options, 'year', 'string', ['2-digit', 'numeric'], undefined);
opt.month = (0, ecma402_abstract_1.GetOption)(options, 'month', 'string', ['2-digit', 'numeric', 'narrow', 'short', 'long'], undefined);
opt.day = (0, ecma402_abstract_1.GetOption)(options, 'day', 'string', ['2-digit', 'numeric'], undefined);
opt.hour = (0, ecma402_abstract_1.GetOption)(options, 'hour', 'string', ['2-digit', 'numeric'], undefined);
opt.minute = (0, ecma402_abstract_1.GetOption)(options, 'minute', 'string', ['2-digit', 'numeric'], undefined);
opt.second = (0, ecma402_abstract_1.GetOption)(options, 'second', 'string', ['2-digit', 'numeric'], undefined);
opt.timeZoneName = (0, ecma402_abstract_1.GetOption)(options, 'timeZoneName', 'string', [
'long',
'short',
'longOffset',
'shortOffset',
'longGeneric',
'shortGeneric',
], undefined);
opt.fractionalSecondDigits = (0, ecma402_abstract_1.GetNumberOption)(options, 'fractionalSecondDigits', 1, 3, undefined);
var dataLocaleData = localeData[dataLocale];
(0, ecma402_abstract_1.invariant)(!!dataLocaleData, "Missing locale data for ".concat(dataLocale));
var formats = dataLocaleData.formats[calendar];
// UNSPECCED: IMPLEMENTATION DETAILS
if (!formats) {
throw new RangeError("Calendar \"".concat(calendar, "\" is not supported. Try setting \"calendar\" to 1 of the following: ").concat(Object.keys(dataLocaleData.formats).join(', ')));
}
var formatMatcher = (0, ecma402_abstract_1.GetOption)(options, 'formatMatcher', 'string', ['basic', 'best fit'], 'best fit');
var dateStyle = (0, ecma402_abstract_1.GetOption)(options, 'dateStyle', 'string', ['full', 'long', 'medium', 'short'], undefined);
internalSlots.dateStyle = dateStyle;
var timeStyle = (0, ecma402_abstract_1.GetOption)(options, 'timeStyle', 'string', ['full', 'long', 'medium', 'short'], undefined);
internalSlots.timeStyle = timeStyle;
var bestFormat;
if (dateStyle === undefined && timeStyle === undefined) {
if (formatMatcher === 'basic') {
bestFormat = (0, BasicFormatMatcher_1.BasicFormatMatcher)(opt, formats);
}
else {
// IMPL DETAILS START
if (isTimeRelated(opt)) {
var hc = resolveHourCycle(internalSlots.hourCycle, dataLocaleData.hourCycle, hour12);
opt.hour12 = hc === 'h11' || hc === 'h12';
}
// IMPL DETAILS END
bestFormat = (0, BestFitFormatMatcher_1.BestFitFormatMatcher)(opt, formats);
}
}
else {
for (var _i = 0, DATE_TIME_PROPS_1 = utils_1.DATE_TIME_PROPS; _i < DATE_TIME_PROPS_1.length; _i++) {
var prop = DATE_TIME_PROPS_1[_i];
var p = opt[prop];
if (p !== undefined) {
throw new TypeError("Intl.DateTimeFormat can't set option ".concat(prop, " when ").concat(dateStyle ? 'dateStyle' : 'timeStyle', " is used"));
}
}
bestFormat = (0, DateTimeStyleFormat_1.DateTimeStyleFormat)(dateStyle, timeStyle, dataLocaleData);
}
// IMPL DETAIL START
// For debugging
internalSlots.format = bestFormat;
// IMPL DETAIL END
for (var prop in opt) {
var p = bestFormat[prop];
if (p !== undefined) {
internalSlots[prop] = p;
}
}
var pattern;
var rangePatterns;
if (internalSlots.hour !== undefined) {
var hc = resolveHourCycle(internalSlots.hourCycle, dataLocaleData.hourCycle, hour12);
internalSlots.hourCycle = hc;
if (hc === 'h11' || hc === 'h12') {
pattern = bestFormat.pattern12;
rangePatterns = bestFormat.rangePatterns12;
}
else {
pattern = bestFormat.pattern;
rangePatterns = bestFormat.rangePatterns;
}
}
else {
// @ts-ignore
internalSlots.hourCycle = undefined;
pattern = bestFormat.pattern;
rangePatterns = bestFormat.rangePatterns;
}
internalSlots.pattern = pattern;
internalSlots.rangePatterns = rangePatterns;
return dtf; // TODO: remove this when https://github.com/microsoft/TypeScript/pull/50402 is merged
}