UNPKG

@burglekitt/gmt

Version:

Temporal-based date and time utilities with timezone support and polyfill integration

67 lines (66 loc) 2.59 kB
import { Temporal } from "@js-temporal/polyfill"; /** * Return a locale's Gregorian era names as [BCE-label, CE-label]. * * - The two-element array is [Before Common Era label, Common Era label]. * - Uses the host runtime's `Intl` data via `Intl.DateTimeFormat`, so output * depends on the runtime's ICU build (full-ICU runtimes localize every * locale; partial-ICU runtimes fall back to English). * - If a locale has no distinct BCE/CE era names, both array elements * contain the same string — the function never returns a sentinel for * a valid locale, only for invalid input. * - Returns `[]` if `locale` is not a valid BCP 47 tag. * * @param locale BCP 47 locale tag (e.g. "en-US", "fr-FR", "ar-SA") * @param style Optional name style: `"long"` (default), `"short"`, or `"narrow"` * @returns 2-element `[BCE-label, CE-label]` array, or `[]` on invalid input * * @example getLocaleEraNames("en-US") // ["Before Christ", "Anno Domini"] * @example getLocaleEraNames("de-DE", "short") // ["v. Chr.", "n. Chr."] * @example getLocaleEraNames("ja-JP", "narrow") // ["BC", "AD"] * @example getLocaleEraNames("not-a-locale") // [] */ export function getLocaleEraNames(locale, style = "long") { if (typeof locale !== "string") return []; try { new Intl.Locale(locale); } catch { return []; } try { const resolved = style === "short" || style === "narrow" ? style : "long"; const formatter = new Intl.DateTimeFormat(locale, { calendar: "gregory", era: resolved, timeZone: "UTC", }); // Year 1 BC (proleptic Gregorian) — Temporal represents 1 BC as year 0. const bceInstant = Temporal.ZonedDateTime.from({ year: 0, month: 1, day: 1, hour: 12, timeZone: "UTC", calendar: "gregory", }).toInstant(); // Year 1 AD (proleptic Gregorian). const ceInstant = Temporal.ZonedDateTime.from({ year: 1, month: 1, day: 1, hour: 12, timeZone: "UTC", calendar: "gregory", }).toInstant(); const bceParts = formatter.formatToParts(bceInstant.epochMilliseconds); const bceEra = bceParts.find((part) => part.type === "era")?.value ?? ""; const ceParts = formatter.formatToParts(ceInstant.epochMilliseconds); const ceEra = ceParts.find((part) => part.type === "era")?.value ?? ""; return [bceEra, ceEra]; } catch { return []; } }