diff --git a/src/common/datetime/calc_date_range.ts b/src/common/datetime/calc_date_range.ts index 1d7580cae6..c87a1b8976 100644 --- a/src/common/datetime/calc_date_range.ts +++ b/src/common/datetime/calc_date_range.ts @@ -93,8 +93,13 @@ export const calcDateRange = ( ]; case "now-12m": return [ - calcDate(today, subMonths, hass.locale, hass.config, 12), - calcDate(today, subMonths, hass.locale, hass.config, 0), + calcDate( + today, + (date) => subMonths(startOfMonth(date), 11), + hass.locale, + hass.config + ), + calcDate(today, endOfMonth, hass.locale, hass.config), ]; case "now-1h": return [ diff --git a/src/common/datetime/format_date.ts b/src/common/datetime/format_date.ts index aeed82b33b..7f8e331ad8 100644 --- a/src/common/datetime/format_date.ts +++ b/src/common/datetime/format_date.ts @@ -166,6 +166,21 @@ const formatDateMonthMem = memoizeOne( }) ); +// 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, diff --git a/src/panels/lovelace/components/hui-energy-period-selector.ts b/src/panels/lovelace/components/hui-energy-period-selector.ts index 477c847917..d4547560c4 100644 --- a/src/panels/lovelace/components/hui-energy-period-selector.ts +++ b/src/panels/lovelace/components/hui-energy-period-selector.ts @@ -8,17 +8,21 @@ import { mdiHomeClock, } from "@mdi/js"; import { + differenceInCalendarMonths, differenceInCalendarYears, differenceInDays, differenceInMonths, endOfDay, + endOfMonth, endOfToday, endOfWeek, isFirstDayOfMonth, isLastDayOfMonth, startOfDay, + startOfMonth, startOfWeek, subDays, + subMonths, } from "date-fns"; import type { UnsubscribeFunc } from "home-assistant-js-websocket"; import type { PropertyValues } from "lit"; @@ -39,6 +43,7 @@ import { calcDateRange } from "../../../common/datetime/calc_date_range"; import { firstWeekdayIndex } from "../../../common/datetime/first_weekday"; import { formatDateMonth, + formatDateMonthShort, formatDateVeryShort, formatDateYear, } from "../../../common/datetime/format_date"; @@ -286,27 +291,39 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) { this.hass.locale, this.hass.config )}` - : html`${simpleRange === "month" - ? html`${formatDateMonth( + : html`${simpleRange === "12month" || + simpleRange === "months" || + simpleRange === "quarter" + ? html`${formatDateMonthShort( this._startDate, this.hass.locale, this.hass.config + )}–${formatDateMonthShort( + this._endDate || new Date(), + this.hass.locale, + this.hass.config )}` - : simpleRange === "day" - ? html`${formatDateVeryShort( - this._startDate, - this.hass.locale, - this.hass.config - )}` - : html`${formatDateVeryShort( - this._startDate, - this.hass.locale, - this.hass.config - )}–${formatDateVeryShort( - this._endDate || new Date(), - this.hass.locale, - this.hass.config - )}`}`} + : html`${simpleRange === "month" + ? html`${formatDateMonth( + this._startDate, + this.hass.locale, + this.hass.config + )}` + : simpleRange === "day" + ? html`${formatDateVeryShort( + this._startDate, + this.hass.locale, + this.hass.config + )}` + : html`${formatDateVeryShort( + this._startDate, + this.hass.locale, + this.hass.config + )}–${formatDateVeryShort( + this._endDate || new Date(), + this.hass.locale, + this.hass.config + )}`}`}`} ${showSubtitleYear ? html`
@@ -386,6 +403,7 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) { if (differenceInDays(endDate!, startDate!) === 0) { return "day"; } + // Check if range is one or more whole months if ( (calcDateProperty( startDate, @@ -404,6 +422,7 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) { config ) as number) === 0 ) { + // Single month return "month"; } if ( @@ -416,29 +435,37 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) { ) as number) === 2 && startDate.getMonth() % 3 === 0 ) { + // Quarter year return "quarter"; } + if ( + calcDateDifferenceProperty( + endDate, + startDate, + differenceInMonths, + locale, + config + ) === 11 + ) { + if ( + calcDateDifferenceProperty( + endDate, + startDate, + differenceInCalendarYears, + locale, + config + ) === 0 + ) { + // Exact year + return "year"; + } + // Last 12 months + return "12month"; + } + // Otherwise some number of whole months + return "months"; } - if ( - calcDateProperty(startDate, isFirstDayOfMonth, locale, config) && - calcDateProperty(endDate, isLastDayOfMonth, locale, config) && - calcDateDifferenceProperty( - endDate, - startDate, - differenceInCalendarYears, - locale, - config - ) === 0 && - calcDateDifferenceProperty( - endDate, - startDate, - differenceInMonths, - locale, - config - ) === 11 - ) { - return "year"; - } + // Unnamed date range return "other"; } ); @@ -508,6 +535,30 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) { ); } else if (range === "year") { [this._startDate, this._endDate] = calcDateRange(this.hass, "this_year"); + } else if (range === "12month") { + [this._startDate, this._endDate] = calcDateRange(this.hass, "now-12m"); + } else if (range === "months") { + // Custom month range + const difference = calcDateDifferenceProperty( + this._endDate!, + this._startDate, + differenceInCalendarMonths, + this.hass.locale, + this.hass.config + ) as number; + this._startDate = calcDate( + calcDate(today, startOfMonth, this.hass.locale, this.hass.config), + subMonths, + this.hass.locale, + this.hass.config, + difference + ); + this._endDate = calcDate( + today, + endOfMonth, + this.hass.locale, + this.hass.config + ); } else { const weekStartsOn = firstWeekdayIndex(this.hass.locale); const weekStart = calcDate(