import type { HassConfig } from "home-assistant-js-websocket"; import memoizeOne from "memoize-one"; import type { FrontendLocaleData } from "../../data/translation"; import { DateFormat } from "../../data/translation"; import { resolveTimeZone } from "./resolve-time-zone"; // Tuesday, August 10 export const formatDateWeekdayDay = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateWeekdayDayMem(locale, config.time_zone).format(dateObj); const formatDateWeekdayDayMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "long", month: "long", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // August 10, 2021 export const formatDate = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateMem(locale, config.time_zone).format(dateObj); const formatDateMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { year: "numeric", month: "long", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Aug 10, 2021 export const formatDateShort = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateShortMem(locale, config.time_zone).format(dateObj); const formatDateShortMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { year: "numeric", month: "short", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // 10/08/2021 export const formatDateNumeric = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => { const formatter = formatDateNumericMem(locale, config.time_zone); if ( locale.date_format === DateFormat.language || locale.date_format === DateFormat.system ) { return formatter.format(dateObj); } const parts = formatter.formatToParts(dateObj); const literal = parts.find((value) => value.type === "literal")?.value; const day = parts.find((value) => value.type === "day")?.value; const month = parts.find((value) => value.type === "month")?.value; const year = parts.find((value) => value.type === "year")?.value; const lastPart = parts[parts.length - 1]; let lastLiteral = lastPart?.type === "literal" ? lastPart?.value : ""; if (locale.language === "bg" && locale.date_format === DateFormat.YMD) { lastLiteral = ""; } const formats = { [DateFormat.DMY]: `${day}${literal}${month}${literal}${year}${lastLiteral}`, [DateFormat.MDY]: `${month}${literal}${day}${literal}${year}${lastLiteral}`, [DateFormat.YMD]: `${year}${literal}${month}${literal}${day}${lastLiteral}`, }; return formats[locale.date_format]; }; const formatDateNumericMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => { const localeString = locale.date_format === DateFormat.system ? undefined : locale.language; if ( locale.date_format === DateFormat.language || locale.date_format === DateFormat.system ) { return new Intl.DateTimeFormat(localeString, { year: "numeric", month: "numeric", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }); } return new Intl.DateTimeFormat(localeString, { year: "numeric", month: "numeric", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }); } ); // Aug 10 export const formatDateVeryShort = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateVeryShortMem(locale, config.time_zone).format(dateObj); const formatDateVeryShortMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { day: "numeric", month: "short", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // August 2021 export const formatDateMonthYear = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateMonthYearMem(locale, config.time_zone).format(dateObj); const formatDateMonthYearMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { month: "long", year: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // August export const formatDateMonth = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateMonthMem(locale, config.time_zone).format(dateObj); const formatDateMonthMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { month: "long", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Aug export const formatDateMonthShort = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateMonthShortMem(locale, config.time_zone).format(dateObj); const formatDateMonthShortMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { month: "short", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // 2021 export const formatDateYear = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateYearMem(locale, config.time_zone).format(dateObj); const formatDateYearMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { year: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Monday export const formatDateWeekday = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateWeekdayMem(locale, config.time_zone).format(dateObj); const formatDateWeekdayMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "long", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Mon export const formatDateWeekdayShort = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateWeekdayShortMem(locale, config.time_zone).format(dateObj); const formatDateWeekdayShortMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "short", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Mon, Aug 10 export const formatDateWeekdayVeryShortDate = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateWeekdayVeryShortDateMem(locale, config.time_zone).format(dateObj); const formatDateWeekdayVeryShortDateMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "short", month: "short", day: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); // Mon, Aug 10, 2021 export const formatDateWeekdayShortDate = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => formatDateWeekdayShortDateMem(locale, config.time_zone).format(dateObj); const formatDateWeekdayShortDateMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "short", month: "short", day: "numeric", year: "numeric", timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); /** * Format a date as YYYY-MM-DD. Uses "en-CA" because it's the only * Intl locale that natively outputs ISO 8601 date format. * Locale/config are only used to resolve the time zone. */ export const formatISODateOnly = ( dateObj: Date, locale: FrontendLocaleData, config: HassConfig ) => { const timeZone = resolveTimeZone(locale.time_zone, config.time_zone); const formatter = new Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit", timeZone, }); return formatter.format(dateObj); }; // 2026-08-10/2026-08-15 export const formatCallyDateRange = ( start: Date, end: Date, locale: FrontendLocaleData, config: HassConfig ) => { const startDate = formatISODateOnly(start, locale, config); const endDate = formatISODateOnly(end, locale, config); return `${startDate}/${endDate}`; };