Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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