Skip to content

Commit 48f6c83

Browse files
committed
Speed up TimeZone and ZonedDateTime code and tests
Creating Intl.DateTimeFormat instances in V8 is slow and memory heavy. GetFormatterParts and GetCanonicalTimeZoneIdentifier are functions that are called many times when using Temporal, and they used to create new instances of Intl.DateTimeFormat for each call. In this commit, we cache them using the time zone identifier as the key. It should be noted that doing the same to SystemTimeZone was avoided. This is due to the fact that user's time zone may change during the execution of a program. An example: Temporal.now.zonedDateTimeISO() should always output the correct time zone. This shouldn't be a problem for server-side code that usually doesn't (or rather, shouldn't) use the time zone from the environment for calculations. (ported from js-temporal/temporal-polyfill#10)
1 parent 44995c7 commit 48f6c83

File tree

1 file changed

+23
-21
lines changed

1 file changed

+23
-21
lines changed

polyfill/lib/ecmascript.mjs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,27 @@ const ES2020 = {
148148
Type
149149
};
150150

151+
const IntlDateTimeFormatEnUsCache = new Map();
152+
153+
function getIntlDateTimeFormatEnUsForTimeZone(timeZoneIdentifier) {
154+
let instance = IntlDateTimeFormatEnUsCache.get(timeZoneIdentifier);
155+
if (instance === undefined) {
156+
instance = new IntlDateTimeFormat('en-us', {
157+
timeZone: String(timeZoneIdentifier),
158+
hour12: false,
159+
era: 'short',
160+
year: 'numeric',
161+
month: 'numeric',
162+
day: 'numeric',
163+
hour: 'numeric',
164+
minute: 'numeric',
165+
second: 'numeric'
166+
});
167+
IntlDateTimeFormatEnUsCache.set(timeZoneIdentifier, instance);
168+
}
169+
return instance;
170+
}
171+
151172
export const ES = ObjectAssign({}, ES2020, {
152173
ToPositiveInteger: ToPositiveInteger,
153174
ToFiniteInteger: (value) => {
@@ -2081,16 +2102,7 @@ export const ES = ObjectAssign({}, ES2020, {
20812102
GetCanonicalTimeZoneIdentifier: (timeZoneIdentifier) => {
20822103
const offsetNs = ES.ParseOffsetString(timeZoneIdentifier);
20832104
if (offsetNs !== null) return ES.FormatTimeZoneOffsetString(offsetNs);
2084-
const formatter = new IntlDateTimeFormat('en-us', {
2085-
timeZone: String(timeZoneIdentifier),
2086-
hour12: false,
2087-
year: 'numeric',
2088-
month: 'numeric',
2089-
day: 'numeric',
2090-
hour: 'numeric',
2091-
minute: 'numeric',
2092-
second: 'numeric'
2093-
});
2105+
const formatter = getIntlDateTimeFormatEnUsForTimeZone(String(timeZoneIdentifier));
20942106
return formatter.resolvedOptions().timeZone;
20952107
},
20962108
GetIANATimeZoneOffsetNanoseconds: (epochNanoseconds, id) => {
@@ -2209,17 +2221,7 @@ export const ES = ObjectAssign({}, ES2020, {
22092221
return result;
22102222
},
22112223
GetFormatterParts: (timeZone, epochMilliseconds) => {
2212-
const formatter = new IntlDateTimeFormat('en-us', {
2213-
timeZone,
2214-
hour12: false,
2215-
era: 'short',
2216-
year: 'numeric',
2217-
month: 'numeric',
2218-
day: 'numeric',
2219-
hour: 'numeric',
2220-
minute: 'numeric',
2221-
second: 'numeric'
2222-
});
2224+
const formatter = getIntlDateTimeFormatEnUsForTimeZone(timeZone);
22232225
// FIXME: can this use formatToParts instead?
22242226
const datetime = formatter.format(new Date(epochMilliseconds));
22252227
const [date, fullYear, time] = datetime.split(/,\s+/);

0 commit comments

Comments
 (0)