@formatjs/intl-datetimeformat
Version:
Intl.DateTimeFormat polyfill
301 lines (300 loc) • 12.5 kB
JavaScript
import { __assign, __rest } from "tslib";
import { CanonicalizeLocaleList, CanonicalizeTimeZoneName, IsValidTimeZoneName, OrdinaryHasInstance, SupportedLocales, ToNumber, defineProperty, invariant, } from '@formatjs/ecma402-abstract';
import Decimal from 'decimal.js';
import { FormatDateTime } from './abstract/FormatDateTime';
import { FormatDateTimeRange } from './abstract/FormatDateTimeRange';
import { FormatDateTimeRangeToParts } from './abstract/FormatDateTimeRangeToParts';
import { FormatDateTimeToParts } from './abstract/FormatDateTimeToParts';
import { InitializeDateTimeFormat } from './abstract/InitializeDateTimeFormat';
import { parseDateTimeSkeleton } from './abstract/skeleton';
import { DATE_TIME_PROPS } from './abstract/utils';
import links from './data/links';
import getInternalSlots from './get_internal_slots';
import { unpack } from './packer';
var UPPERCASED_LINKS = Object.keys(links).reduce(function (all, l) {
all[l.toUpperCase()] = links[l];
return all;
}, {});
var RESOLVED_OPTIONS_KEYS = [
'locale',
'calendar',
'numberingSystem',
'dateStyle',
'timeStyle',
'timeZone',
'hourCycle',
'weekday',
'era',
'year',
'month',
'day',
'hour',
'minute',
'second',
'timeZoneName',
];
var formatDescriptor = {
enumerable: false,
configurable: true,
get: function () {
if (typeof this !== 'object' ||
!OrdinaryHasInstance(DateTimeFormat, this)) {
throw TypeError('Intl.DateTimeFormat format property accessor called on incompatible receiver');
}
var internalSlots = getInternalSlots(this);
// eslint-disable-next-line @typescript-eslint/no-this-alias
var dtf = this;
var boundFormat = internalSlots.boundFormat;
if (boundFormat === undefined) {
// https://tc39.es/proposal-unified-intl-numberformat/section11/numberformat_diff_out.html#sec-number-format-functions
boundFormat = function (date) {
var x;
if (date === undefined) {
x = new Decimal(Date.now());
}
else {
x = ToNumber(date);
}
return FormatDateTime(dtf, x, {
getInternalSlots: getInternalSlots,
localeData: DateTimeFormat.localeData,
tzData: DateTimeFormat.tzData,
getDefaultTimeZone: DateTimeFormat.getDefaultTimeZone,
});
};
try {
// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/prototype/format/format-function-name.js
Object.defineProperty(boundFormat, 'name', {
configurable: true,
enumerable: false,
writable: false,
value: '',
});
}
catch (e) {
// In older browser (e.g Chrome 36 like polyfill-fastly.io)
// TypeError: Cannot redefine property: name
}
internalSlots.boundFormat = boundFormat;
}
return boundFormat;
},
};
try {
// https://github.com/tc39/test262/blob/master/test/intl402/NumberFormat/prototype/format/name.js
Object.defineProperty(formatDescriptor.get, 'name', {
configurable: true,
enumerable: false,
writable: false,
value: 'get format',
});
}
catch (e) {
// In older browser (e.g Chrome 36 like polyfill-fastly.io)
// TypeError: Cannot redefine property: name
}
export var DateTimeFormat = function (locales, options) {
// Cannot use `new.target` bc of IE11 & TS transpiles it to something else
if (!this || !OrdinaryHasInstance(DateTimeFormat, this)) {
return new DateTimeFormat(locales, options);
}
InitializeDateTimeFormat(this, locales, options, {
tzData: DateTimeFormat.tzData,
uppercaseLinks: UPPERCASED_LINKS,
availableLocales: DateTimeFormat.availableLocales,
relevantExtensionKeys: DateTimeFormat.relevantExtensionKeys,
getDefaultLocale: DateTimeFormat.getDefaultLocale,
getDefaultTimeZone: DateTimeFormat.getDefaultTimeZone,
getInternalSlots: getInternalSlots,
localeData: DateTimeFormat.localeData,
});
/** IMPL START */
var internalSlots = getInternalSlots(this);
var dataLocale = internalSlots.dataLocale;
var dataLocaleData = DateTimeFormat.localeData[dataLocale];
invariant(dataLocaleData !== undefined, "Cannot load locale-dependent data for ".concat(dataLocale, "."));
/** IMPL END */
};
// Static properties
defineProperty(DateTimeFormat, 'supportedLocalesOf', {
value: function supportedLocalesOf(locales, options) {
return SupportedLocales(DateTimeFormat.availableLocales, CanonicalizeLocaleList(locales), options);
},
});
defineProperty(DateTimeFormat.prototype, 'resolvedOptions', {
value: function resolvedOptions() {
if (typeof this !== 'object' ||
!OrdinaryHasInstance(DateTimeFormat, this)) {
throw TypeError('Method Intl.DateTimeFormat.prototype.resolvedOptions called on incompatible receiver');
}
var internalSlots = getInternalSlots(this);
var ro = {};
for (var _i = 0, RESOLVED_OPTIONS_KEYS_1 = RESOLVED_OPTIONS_KEYS; _i < RESOLVED_OPTIONS_KEYS_1.length; _i++) {
var key = RESOLVED_OPTIONS_KEYS_1[_i];
var value = internalSlots[key];
if (key === 'hourCycle') {
var hour12 = value === 'h11' || value === 'h12'
? true
: value === 'h23' || value === 'h24'
? false
: undefined;
if (hour12 !== undefined) {
ro.hour12 = hour12;
}
}
if (DATE_TIME_PROPS.indexOf(key) > -1) {
if (internalSlots.dateStyle !== undefined ||
internalSlots.timeStyle !== undefined) {
value = undefined;
}
}
if (value !== undefined) {
ro[key] = value;
}
}
return ro;
},
});
defineProperty(DateTimeFormat.prototype, 'formatToParts', {
value: function formatToParts(date) {
var x;
if (date === undefined) {
x = new Decimal(Date.now());
}
else {
x = ToNumber(date);
}
return FormatDateTimeToParts(this, x, {
getInternalSlots: getInternalSlots,
localeData: DateTimeFormat.localeData,
tzData: DateTimeFormat.tzData,
getDefaultTimeZone: DateTimeFormat.getDefaultTimeZone,
});
},
});
defineProperty(DateTimeFormat.prototype, 'formatRangeToParts', {
value: function formatRangeToParts(startDate, endDate) {
var dtf = this;
invariant(typeof dtf === 'object', 'receiver is not an object', TypeError);
invariant(startDate !== undefined && endDate !== undefined, 'startDate/endDate cannot be undefined', TypeError);
return FormatDateTimeRangeToParts(dtf, ToNumber(startDate), ToNumber(endDate), {
getInternalSlots: getInternalSlots,
localeData: DateTimeFormat.localeData,
tzData: DateTimeFormat.tzData,
getDefaultTimeZone: DateTimeFormat.getDefaultTimeZone,
});
},
});
defineProperty(DateTimeFormat.prototype, 'formatRange', {
value: function formatRange(startDate, endDate) {
var dtf = this;
invariant(typeof dtf === 'object', 'receiver is not an object', TypeError);
invariant(startDate !== undefined && endDate !== undefined, 'startDate/endDate cannot be undefined', TypeError);
return FormatDateTimeRange(dtf, ToNumber(startDate), ToNumber(endDate), {
getInternalSlots: getInternalSlots,
localeData: DateTimeFormat.localeData,
tzData: DateTimeFormat.tzData,
getDefaultTimeZone: DateTimeFormat.getDefaultTimeZone,
});
},
});
var DEFAULT_TIMEZONE = 'UTC';
DateTimeFormat.__setDefaultTimeZone = function (timeZone) {
if (timeZone !== undefined) {
timeZone = String(timeZone);
if (!IsValidTimeZoneName(timeZone, {
zoneNamesFromData: Object.keys(DateTimeFormat.tzData),
uppercaseLinks: UPPERCASED_LINKS,
})) {
throw new RangeError('Invalid timeZoneName');
}
timeZone = CanonicalizeTimeZoneName(timeZone, {
zoneNames: Object.keys(DateTimeFormat.tzData),
uppercaseLinks: UPPERCASED_LINKS,
});
}
else {
timeZone = DEFAULT_TIMEZONE;
}
DateTimeFormat.__defaultTimeZone = timeZone;
};
DateTimeFormat.relevantExtensionKeys = ['nu', 'ca', 'hc'];
DateTimeFormat.__defaultTimeZone = DEFAULT_TIMEZONE;
DateTimeFormat.getDefaultTimeZone = function () { return DateTimeFormat.__defaultTimeZone; };
DateTimeFormat.__addLocaleData = function __addLocaleData() {
var data = [];
for (var _i = 0; _i < arguments.length; _i++) {
data[_i] = arguments[_i];
}
var _loop_1 = function (d, locale) {
var dateFormat = d.dateFormat, timeFormat = d.timeFormat, dateTimeFormat = d.dateTimeFormat, formats = d.formats, intervalFormats = d.intervalFormats, rawData = __rest(d, ["dateFormat", "timeFormat", "dateTimeFormat", "formats", "intervalFormats"]);
var processedData = __assign(__assign({}, rawData), { dateFormat: {
full: parseDateTimeSkeleton(dateFormat.full),
long: parseDateTimeSkeleton(dateFormat.long),
medium: parseDateTimeSkeleton(dateFormat.medium),
short: parseDateTimeSkeleton(dateFormat.short),
}, timeFormat: {
full: parseDateTimeSkeleton(timeFormat.full),
long: parseDateTimeSkeleton(timeFormat.long),
medium: parseDateTimeSkeleton(timeFormat.medium),
short: parseDateTimeSkeleton(timeFormat.short),
}, dateTimeFormat: {
full: parseDateTimeSkeleton(dateTimeFormat.full).pattern,
long: parseDateTimeSkeleton(dateTimeFormat.long).pattern,
medium: parseDateTimeSkeleton(dateTimeFormat.medium).pattern,
short: parseDateTimeSkeleton(dateTimeFormat.short).pattern,
}, formats: {} });
var _loop_2 = function (calendar) {
processedData.formats[calendar] = Object.keys(formats[calendar]).map(function (skeleton) {
return parseDateTimeSkeleton(skeleton, formats[calendar][skeleton], intervalFormats[skeleton], intervalFormats.intervalFormatFallback);
});
};
for (var calendar in formats) {
_loop_2(calendar);
}
var minimizedLocale = new Intl.Locale(locale)
.minimize()
.toString();
DateTimeFormat.localeData[locale] = DateTimeFormat.localeData[minimizedLocale] = processedData;
DateTimeFormat.availableLocales.add(locale);
DateTimeFormat.availableLocales.add(minimizedLocale);
if (!DateTimeFormat.__defaultLocale) {
DateTimeFormat.__defaultLocale = minimizedLocale;
}
};
for (var _a = 0, data_1 = data; _a < data_1.length; _a++) {
var _b = data_1[_a], d = _b.data, locale = _b.locale;
_loop_1(d, locale);
}
};
Object.defineProperty(DateTimeFormat.prototype, 'format', formatDescriptor);
DateTimeFormat.__defaultLocale = '';
DateTimeFormat.localeData = {};
DateTimeFormat.availableLocales = new Set();
DateTimeFormat.getDefaultLocale = function () {
return DateTimeFormat.__defaultLocale;
};
DateTimeFormat.polyfilled = true;
DateTimeFormat.tzData = {};
DateTimeFormat.__addTZData = function (d) {
DateTimeFormat.tzData = unpack(d);
};
try {
if (typeof Symbol !== 'undefined') {
Object.defineProperty(DateTimeFormat.prototype, Symbol.toStringTag, {
value: 'Intl.DateTimeFormat',
writable: false,
enumerable: false,
configurable: true,
});
}
Object.defineProperty(DateTimeFormat.prototype.constructor, 'length', {
value: 1,
writable: false,
enumerable: false,
configurable: true,
});
}
catch (e) {
// Meta fix so we're test262-compliant, not important
}