const formattersCache = {} as Record; export type Locale = string | null | undefined; export const getFormatterForLocale = ( locale: Locale, options?: Intl.DateTimeFormatOptions, ): Intl.DateTimeFormat => { const l = locale ?? navigator.language; return ( formattersCache[l + JSON.stringify(options)] ?? new Intl.DateTimeFormat(l, options) ); }; /** * the day on which a week should start */ export type StartOfWeek = "monday" | "sunday"; export const getWeeDayNames = ( locale: Locale, startOfWeek: StartOfWeek, weekday: Intl.DateTimeFormatOptions["weekday"], ) => Array.from( { length: 7 }, (_, i) => getFormatterForLocale(locale, { weekday }) .formatToParts( new Date(2024, 0, i + (startOfWeek === "sunday" ? 0 : 1)), ) .find((part) => part.type === "weekday")!.value, ); /** * get the localized month name according to a given format */ export const getMonthName = ( value: Date, locale: Locale, month?: Intl.DateTimeFormatOptions["month"], ) => getFormatterForLocale(locale, { month }) .formatToParts(value) .find(({ type }) => type === "month")!.value;