diff --git a/src/panels/lovelace/cards/energy/common/energy-chart-options.ts b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts
index 76dde725aa..943ade0bb5 100644
--- a/src/panels/lovelace/cards/energy/common/energy-chart-options.ts
+++ b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts
@@ -1,5 +1,16 @@
import type { HassConfig } from "home-assistant-js-websocket";
-import { addHours, subHours, differenceInDays } from "date-fns";
+import {
+ differenceInMonths,
+ subHours,
+ differenceInDays,
+ differenceInYears,
+ startOfYear,
+ addMilliseconds,
+ startOfMonth,
+ addYears,
+ addMonths,
+ addHours,
+} from "date-fns";
import type {
BarSeriesOption,
CallbackDataParams,
@@ -7,7 +18,10 @@ import type {
} from "echarts/types/dist/shared";
import type { FrontendLocaleData } from "../../../../../data/translation";
import { formatNumber } from "../../../../../common/number/format_number";
-import { formatDateVeryShort } from "../../../../../common/datetime/format_date";
+import {
+ formatDateMonthYear,
+ formatDateVeryShort,
+} from "../../../../../common/datetime/format_date";
import { formatTime } from "../../../../../common/datetime/format_time";
import type { ECOption } from "../../../../../resources/echarts";
@@ -53,7 +67,7 @@ export function getCommonOptions(
xAxis: {
type: "time",
min: start,
- max: end,
+ max: getSuggestedMax(dayDifference, end),
},
yAxis: {
type: "value",
@@ -88,7 +102,6 @@ export function getCommonOptions(
}
});
return [mainItems, compareItems]
- .filter((items) => items.length > 0)
.map((items) =>
formatTooltip(
items,
@@ -100,6 +113,7 @@ export function getCommonOptions(
formatTotal
)
)
+ .filter(Boolean)
.join("
");
}
return formatTooltip(
@@ -126,14 +140,16 @@ function formatTooltip(
unit?: string,
formatTotal?: (total: number) => string
) {
- if (!params[0].value) {
+ if (!params[0]?.value) {
return "";
}
// when comparing the first value is offset to match the main period
// and the real date is in the third value
const date = new Date(params[0].value?.[2] ?? params[0].value?.[0]);
let period: string;
- if (dayDifference > 0) {
+ if (dayDifference > 89) {
+ period = `${formatDateMonthYear(date, locale, config)}`;
+ } else if (dayDifference > 0) {
period = `${formatDateVeryShort(date, locale, config)}`;
} else {
period = `${
@@ -242,3 +258,25 @@ export function fillDataGapsAndRoundCaps(datasets: BarSeriesOption[]) {
}
});
}
+
+export function getCompareTransform(start: Date, compareStart?: Date) {
+ if (!compareStart) {
+ return (ts: Date) => ts;
+ }
+ const compareYearDiff = differenceInYears(start, compareStart);
+ if (
+ compareYearDiff !== 0 &&
+ start.getTime() === startOfYear(start).getTime()
+ ) {
+ return (ts: Date) => addYears(ts, compareYearDiff);
+ }
+ const compareMonthDiff = differenceInMonths(start, compareStart);
+ if (
+ compareMonthDiff !== 0 &&
+ start.getTime() === startOfMonth(start).getTime()
+ ) {
+ return (ts: Date) => addMonths(ts, compareMonthDiff);
+ }
+ const compareOffset = start.getTime() - compareStart.getTime();
+ return (ts: Date) => addMilliseconds(ts, compareOffset);
+}
diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts
index e0d2db9e60..8a609fe507 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts
@@ -33,6 +33,7 @@ import { hasConfigChanged } from "../../common/has-changed";
import {
fillDataGapsAndRoundCaps,
getCommonOptions,
+ getCompareTransform,
} from "./common/energy-chart-options";
import { storage } from "../../../../common/decorators/storage";
import type { ECOption } from "../../../../resources/echarts";
@@ -319,18 +320,19 @@ export class HuiEnergyDevicesDetailGraphCard
datapoint[1];
});
});
- const compareOffset = compare
- ? this._start.getTime() - this._compareStart!.getTime()
- : 0;
+ const compareTransform = getCompareTransform(
+ this._start,
+ this._compareStart!
+ );
const untrackedConsumption: BarSeriesOption["data"] = [];
Object.keys(consumptionData.total).forEach((time) => {
const value =
consumptionData.total[time] - (totalDeviceConsumption[time] || 0);
- const dataPoint = [Number(time), value];
+ const dataPoint: (Date | string | number)[] = [time, value];
if (compare) {
dataPoint[2] = dataPoint[0];
- dataPoint[0] += compareOffset;
+ dataPoint[0] = compareTransform(new Date(time));
}
untrackedConsumption.push(dataPoint);
});
diff --git a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
index 0c19285d70..6612a58c8f 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
@@ -29,6 +29,7 @@ import { hasConfigChanged } from "../../common/has-changed";
import {
fillDataGapsAndRoundCaps,
getCommonOptions,
+ getCompareTransform,
} from "./common/energy-chart-options";
import type { ECOption } from "../../../../resources/echarts";
@@ -213,9 +214,10 @@ export class HuiEnergyGasGraphCard
compare = false
) {
const data: BarSeriesOption[] = [];
- const compareOffset = compare
- ? this._start.getTime() - this._compareStart!.getTime()
- : 0;
+ const compareTransform = getCompareTransform(
+ this._start,
+ this._compareStart!
+ );
gasSources.forEach((source, idx) => {
let prevStart: number | null = null;
@@ -236,10 +238,13 @@ export class HuiEnergyGasGraphCard
if (prevStart === point.start) {
continue;
}
- const dataPoint = [point.start, point.change];
+ const dataPoint: (Date | string | number)[] = [
+ point.start,
+ point.change,
+ ];
if (compare) {
dataPoint[2] = dataPoint[0];
- dataPoint[0] += compareOffset;
+ dataPoint[0] = compareTransform(new Date(point.start));
}
gasConsumptionData.push(dataPoint);
prevStart = point.start;
diff --git a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
index e679022a1b..e1ffa869f0 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
@@ -30,6 +30,7 @@ import { hasConfigChanged } from "../../common/has-changed";
import {
fillDataGapsAndRoundCaps,
getCommonOptions,
+ getCompareTransform,
} from "./common/energy-chart-options";
import type { ECOption } from "../../../../resources/echarts";
@@ -231,9 +232,10 @@ export class HuiEnergySolarGraphCard
compare = false
) {
const data: BarSeriesOption[] = [];
- const compareOffset = compare
- ? this._start.getTime() - this._compareStart!.getTime()
- : 0;
+ const compareTransform = getCompareTransform(
+ this._start,
+ this._compareStart!
+ );
solarSources.forEach((source, idx) => {
let prevStart: number | null = null;
@@ -255,10 +257,13 @@ export class HuiEnergySolarGraphCard
if (prevStart === point.start) {
continue;
}
- const dataPoint = [point.start, point.change];
+ const dataPoint: (Date | string | number)[] = [
+ point.start,
+ point.change,
+ ];
if (compare) {
dataPoint[2] = dataPoint[0];
- dataPoint[0] += compareOffset;
+ dataPoint[0] = compareTransform(new Date(point.start));
}
solarProductionData.push(dataPoint);
prevStart = point.start;
diff --git a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
index 74fc5dc83f..9836c7f061 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
@@ -27,6 +27,7 @@ import { hasConfigChanged } from "../../common/has-changed";
import {
fillDataGapsAndRoundCaps,
getCommonOptions,
+ getCompareTransform,
} from "./common/energy-chart-options";
import type { ECOption } from "../../../../resources/echarts";
@@ -476,9 +477,10 @@ export class HuiEnergyUsageGraphCard
(a, b) => Number(a) - Number(b)
);
- const compareOffset = compare
- ? this._start.getTime() - this._compareStart!.getTime()
- : 0;
+ const compareTransform = getCompareTransform(
+ this._start,
+ this._compareStart!
+ );
Object.entries(combinedData).forEach(([type, sources]) => {
Object.entries(sources).forEach(([statId, source]) => {
@@ -494,7 +496,7 @@ export class HuiEnergyUsageGraphCard
];
if (compare) {
dataPoint[2] = dataPoint[0];
- dataPoint[0] += compareOffset;
+ dataPoint[0] = compareTransform(dataPoint[0]);
}
points.push(dataPoint);
}
diff --git a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
index 919bd06ed1..adfc3d217a 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
@@ -28,6 +28,7 @@ import { hasConfigChanged } from "../../common/has-changed";
import {
fillDataGapsAndRoundCaps,
getCommonOptions,
+ getCompareTransform,
} from "./common/energy-chart-options";
import type { ECOption } from "../../../../resources/echarts";
import { formatNumber } from "../../../../common/number/format_number";
@@ -211,9 +212,10 @@ export class HuiEnergyWaterGraphCard
compare = false
) {
const data: BarSeriesOption[] = [];
- const compareOffset = compare
- ? this._start.getTime() - this._compareStart!.getTime()
- : 0;
+ const compareTransform = getCompareTransform(
+ this._start,
+ this._compareStart!
+ );
waterSources.forEach((source, idx) => {
let prevStart: number | null = null;
@@ -234,10 +236,13 @@ export class HuiEnergyWaterGraphCard
if (prevStart === point.start) {
continue;
}
- const dataPoint = [point.start, point.change];
+ const dataPoint: (Date | string | number)[] = [
+ point.start,
+ point.change,
+ ];
if (compare) {
dataPoint[2] = dataPoint[0];
- dataPoint[0] += compareOffset;
+ dataPoint[0] = compareTransform(new Date(point.start));
}
waterConsumptionData.push(dataPoint);
prevStart = point.start;