1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-04-18 07:56:44 +01:00

Use whole months for "Last 12 Months" on Energy Date Picker (#30091)

* Make "now-12m" use month boundaries

Currently the "Last 12 Months" date function calculates precisely 12 months from the current day. So today is March 10, then it would retrieve April 11 to March 10.

However logically the name implies whole months - i.e. "now" would be "March", so the last 12 months ought to be Apr 1 to March 31.

* Let energy date picker detect 12 Month range

With now-12m changed to mean whole months rather than partial months, we can make the energy date picker nicely detect and render any month range, and also fix the now button so that it can pick a "now-12m" range.

* Use Short Month for Displayed Range
To avoid making the displayed range too large to fit on small screens.

* Move subMonths into calcDate fn not input

Perform both startOfMonth and subMonths as a custom function in calcDate rather than performing subMonths on the input to avoid any wierd timezone issues.

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
This commit is contained in:
Tom Carpenter
2026-03-12 07:40:50 +00:00
committed by GitHub
parent 5ddb31ce7b
commit c5cb196aa1
3 changed files with 110 additions and 39 deletions

View File

@@ -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 [

View File

@@ -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,

View File

@@ -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
)}&ndash;${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
)}&ndash;${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
)}&ndash;${formatDateVeryShort(
this._endDate || new Date(),
this.hass.locale,
this.hass.config
)}`}`}`}
</div>
${showSubtitleYear
? html`<div class="header-subtitle">
@@ -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(