Skip to content

Commit

Permalink
perf(input-time-zone): improve memory footprint by leveraging browser…
Browse files Browse the repository at this point in the history
… cache and releasing utils after their use (#9945)

**Related Issue:** N/A

## Summary

✨🚀✨
  • Loading branch information
jcfranco authored Aug 14, 2024
1 parent a392d51 commit a3d2141
Showing 1 changed file with 85 additions and 116 deletions.
201 changes: 85 additions & 116 deletions packages/calcite-components/src/components/input-time-zone/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,6 @@ export function getUserTimeZoneName(): string {
return dateFormatter.resolvedOptions().timeZone;
}

/**
* The lazy-loaded timezone-groups lib to be used across instances.
*/
let offsetGroupUtils: Promise<
[
typeof import("timezone-groups/dist/groupByOffset/index.mjs"),
typeof import("timezone-groups/dist/groupByOffset/strategy/native.mjs"),
]
>;
let regionGroupUtils: Promise<
[
typeof import("timezone-groups/dist/groupByRegion/index.mjs"),
typeof import("timezone-groups/dist/utils/country.mjs"),
]
>;
let nameGroupUtils: Promise<typeof import("timezone-groups/dist/groupByName/index.mjs")>;

export async function createTimeZoneItems(
locale: SupportedLocale,
messages: InputTimeZoneMessages,
Expand All @@ -81,27 +64,22 @@ export async function createTimeZoneItems(
standardTime: OffsetStyle,
): Promise<TimeZoneItem[] | TimeZoneItemGroup[]> {
if (mode === "name") {
if (!nameGroupUtils) {
nameGroupUtils = import("timezone-groups/dist/groupByName/index.mjs");
}

return nameGroupUtils.then(async ({ groupByName }) => {
const groups = await groupByName();

return groups
.map<TimeZoneItem<string>>(({ label: timeZone }) => {
const label = toUserFriendlyName(timeZone);
const value = timeZone;

return {
label,
value,
filterValue: timeZone,
};
})
.filter((group) => !!group)
.sort();
});
const { groupByName } = await import("timezone-groups/dist/groupByName/index.mjs");
const groups = await groupByName();

return groups
.map<TimeZoneItem<string>>(({ label: timeZone }) => {
const label = toUserFriendlyName(timeZone);
const value = timeZone;

return {
label,
value,
filterValue: timeZone,
};
})
.filter((group) => !!group)
.sort();
}

const effectiveLocale =
Expand All @@ -114,95 +92,86 @@ export async function createTimeZoneItems(
const referenceDateInMs: number = referenceDate.getTime();

if (mode === "region") {
if (!regionGroupUtils) {
regionGroupUtils = Promise.all([
import("timezone-groups/dist/groupByRegion/index.mjs"),
import("timezone-groups/dist/utils/country.mjs"),
]);
}

return regionGroupUtils.then(async ([{ groupByRegion }, { getCountry }]) => {
const groups = await groupByRegion();

return groups
.map<TimeZoneItemGroup>(({ label: region, tzs }) => {
return {
label: region,
items: tzs.map((timeZone) => {
const decimalOffset = timeZoneOffsetToDecimal(
getTimeZoneShortOffset(timeZone, effectiveLocale, referenceDateInMs),
);

return {
label: getTimeZoneLabel(timeZone, messages),
value: timeZone,
filterValue: toUserFriendlyName(timeZone),
metadata: {
offset: decimalOffset,
country: getCountry(timeZone),
},
};
}),
};
})
.sort((groupA, groupB) => groupA.label.localeCompare(groupB.label));
});
}

if (!offsetGroupUtils) {
offsetGroupUtils = Promise.all([
import("timezone-groups/dist/groupByOffset/index.mjs"),
import("timezone-groups/dist/groupByOffset/strategy/native/index.mjs"),
const [{ groupByRegion }, { getCountry }] = await Promise.all([
import("timezone-groups/dist/groupByRegion/index.mjs"),
import("timezone-groups/dist/utils/country.mjs"),
]);
}
const groups = await groupByRegion();

return offsetGroupUtils.then(async ([{ groupByOffset }, { DateEngine }]) => {
const groups = await groupByOffset({
dateEngine: new DateEngine(),
groupDateRange: 1,
startDate: new Date(referenceDateInMs).toISOString(),
});
return groups
.map<TimeZoneItemGroup>(({ label: region, tzs }) => {
return {
label: region,
items: tzs.map((timeZone) => {
const decimalOffset = timeZoneOffsetToDecimal(
getTimeZoneShortOffset(timeZone, effectiveLocale, referenceDateInMs),
);

return {
label: getTimeZoneLabel(timeZone, messages),
value: timeZone,
filterValue: toUserFriendlyName(timeZone),
metadata: {
offset: decimalOffset,
country: getCountry(timeZone),
},
};
}),
};
})
.sort((groupA, groupB) => groupA.label.localeCompare(groupB.label));
}

const listFormatter = new Intl.ListFormat(locale, { style: "long", type: "conjunction" });
const [{ groupByOffset }, { DateEngine }] = await Promise.all([
import("timezone-groups/dist/groupByOffset/index.mjs"),
import("timezone-groups/dist/groupByOffset/strategy/native/index.mjs"),
]);

// we remove blocked entries from tzs and adjust label indices accordingly
groups.forEach((group) => {
const indexOffsets: number[] = [];
let removedSoFar = 0;
const groups = await groupByOffset({
dateEngine: new DateEngine(),
groupDateRange: 1,
startDate: new Date(referenceDateInMs).toISOString(),
});

group.tzs.forEach((tz, index) => {
if (timeZoneNameBlockList.includes(tz)) {
removedSoFar++;
}
indexOffsets[index] = removedSoFar;
});
const listFormatter = new Intl.ListFormat(locale, { style: "long", type: "conjunction" });

group.tzs = group.tzs.filter((tz) => !timeZoneNameBlockList.includes(tz));
// we remove blocked entries from tzs and adjust label indices accordingly
groups.forEach((group) => {
const indexOffsets: number[] = [];
let removedSoFar = 0;

group.labelTzIdx = group.labelTzIdx
.map((index) => index - indexOffsets[index])
.filter((index) => index >= 0 && index < group.tzs.length);
group.tzs.forEach((tz, index) => {
if (timeZoneNameBlockList.includes(tz)) {
removedSoFar++;
}
indexOffsets[index] = removedSoFar;
});

return groups
.map<TimeZoneItem<number>>(({ labelTzIdx, tzs }) => {
const groupRepTz = tzs[0];
const decimalOffset = timeZoneOffsetToDecimal(
getTimeZoneShortOffset(groupRepTz, effectiveLocale, referenceDateInMs),
);
const value = toOffsetValue(groupRepTz, referenceDateInMs);
const tzLabels = labelTzIdx.map((index: number) => getTimeZoneLabel(tzs[index], messages));
const label = createTimeZoneOffsetLabel(messages, decimalOffset, listFormatter.format(tzLabels));
group.tzs = group.tzs.filter((tz) => !timeZoneNameBlockList.includes(tz));

return {
label,
value,
filterValue: tzs.map((tz) => toUserFriendlyName(tz)),
};
})
.filter((group) => !!group)
.sort((groupA, groupB) => groupA.value - groupB.value);
group.labelTzIdx = group.labelTzIdx
.map((index) => index - indexOffsets[index])
.filter((index) => index >= 0 && index < group.tzs.length);
});

return groups
.map<TimeZoneItem<number>>(({ labelTzIdx, tzs }) => {
const groupRepTz = tzs[0];
const decimalOffset = timeZoneOffsetToDecimal(
getTimeZoneShortOffset(groupRepTz, effectiveLocale, referenceDateInMs),
);
const value = toOffsetValue(groupRepTz, referenceDateInMs);
const tzLabels = labelTzIdx.map((index: number) => getTimeZoneLabel(tzs[index], messages));
const label = createTimeZoneOffsetLabel(messages, decimalOffset, listFormatter.format(tzLabels));

return {
label,
value,
filterValue: tzs.map((tz) => toUserFriendlyName(tz)),
};
})
.filter((group) => !!group)
.sort((groupA, groupB) => groupA.value - groupB.value);
}

function getTimeZoneLabel(timeZone: string, messages: InputTimeZoneMessages): string {
Expand Down

0 comments on commit a3d2141

Please sign in to comment.