Skip to content

Commit d6335df

Browse files
ferk6aptomato
authored andcommitted
Cache Intl.DateTimeFormat to reduce memory footprint
Creating Intl.DateTimeFormat instances in V8 is very 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 deliberately avoided. This is due to the fact that the user's time zone may change during the execution of a program. An example is calling Temporal.now.zonedDateTimeISO() which should always output the correct time zone. This shouldn't be a problem for server-sided code which usually doesn't (or rather, shouldn't) use the time zone from the environment for calculations.
1 parent 559cb66 commit d6335df

File tree

1 file changed

+23
-21
lines changed

1 file changed

+23
-21
lines changed

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)