@burglekitt/gmt
Version:
Temporal-based date and time utilities with timezone support and polyfill integration
57 lines (56 loc) • 2.52 kB
JavaScript
import { Temporal } from "@js-temporal/polyfill";
import { isValidTimeZone } from "../validate/index.js";
/**
* Return the localized display name for an IANA timeZone.
*
* - `options.style` covers every `Intl.DateTimeFormatOptions` `timeZoneName`
* value: "short" (EST), "long" (Eastern Standard Time), "shortOffset"
* (GMT-5), "longOffset" (GMT-05:00), "shortGeneric" (ET), "longGeneric"
* (Eastern Time). Default "long".
* - "short"/"long"/"shortOffset"/"longOffset" name the zone's *current*
* offset — for a DST-observing zone the label flips between standard and
* daylight names depending on when this is called, since there's no
* instant parameter to pin it to (this matches how
* `Intl.DateTimeFormat.prototype.format()` itself defaults to "now" when
* called with no argument). "shortGeneric"/"longGeneric" are
* season-independent (e.g. "ET", "Eastern Time") and don't have this
* issue — prefer them for a name that won't change twice a year.
* - Output depends on runtime ICU data.
* - Returns "" for an invalid timeZone or locale.
*
* @param timeZone IANA timeZone identifier
* @param locale BCP 47 locale tag (e.g. "en-US")
* @param options optional: { style } name style, default "long"
* @returns localized zone name, or "" on invalid input
*
* @example formatTimeZoneName("America/New_York", "en-US", { style: "shortGeneric" }) // "ET"
* @example formatTimeZoneName("America/New_York", "en-US", { style: "longGeneric" }) // "Eastern Time"
* @example formatTimeZoneName("America/New_York", "en-US", { style: "shortOffset" }) // "GMT-4" or "GMT-5", depending on the current date
* @example formatTimeZoneName("Asia/Tokyo", "ja-JP", { style: "longGeneric" }) // "日本標準時"
* @example formatTimeZoneName("Invalid/Zone", "en-US") // ""
* @example formatTimeZoneName("America/New_York", "!!!") // ""
*/
export function formatTimeZoneName(timeZone, locale, options) {
if (!isValidTimeZone(timeZone)) {
return "";
}
try {
new Intl.Locale(locale);
}
catch {
return "";
}
try {
const style = options?.style ?? "long";
const formatter = new Intl.DateTimeFormat(locale, {
timeZone,
timeZoneName: style,
hour: "numeric",
});
const parts = formatter.formatToParts(Temporal.Now.instant().epochMilliseconds);
return parts.find((part) => part.type === "timeZoneName")?.value ?? "";
}
catch {
return "";
}
}