mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Fix energy charts with leap years (#24059)
* Fix energy charts with leap years * handle quarters
This commit is contained in:
parent
ce0f02a45b
commit
31180e3a9e
@ -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("<br><br>");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user