From 0501e5000ba50fd8903405c7d18871b1dfe9e07f Mon Sep 17 00:00:00 2001 From: David Buezas Date: Sat, 12 Nov 2022 12:12:49 +0100 Subject: [PATCH] Fix #132. Negative years (e.g zooming out) break fetching and rendering Fix parsing of negative iso dates Default x axis type to date to avoid the axis defaulting to numbers when all traces are empty. --- src/cache/Cache.ts | 3 +++ src/plotly-graph-card.ts | 26 ++++++++++++++++++++++---- src/themed-layout.ts | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/cache/Cache.ts b/src/cache/Cache.ts index 525d14f..dc4414d 100644 --- a/src/cache/Cache.ts +++ b/src/cache/Cache.ts @@ -98,6 +98,8 @@ export function getEntityKey(entity: EntityConfig) { } throw new Error(`Entity malformed:${JSON.stringify(entity)}`); } + +const MIN_SAFE_TIMESTAMP = Date.parse("0001-01-02T00:00:00.000Z"); export default class Cache { ranges: Record = {}; histories: Record = {}; @@ -132,6 +134,7 @@ export default class Cache { significant_changes_only: boolean, minimal_response: boolean ) { + range = range.map((n) => Math.max(MIN_SAFE_TIMESTAMP, n)); // HA API can't handle negative years return (this.busy = this.busy .catch(() => {}) .then(async () => { diff --git a/src/plotly-graph-card.ts b/src/plotly-graph-card.ts index 08d0358..e6eaaa4 100644 --- a/src/plotly-graph-card.ts +++ b/src/plotly-graph-card.ts @@ -263,10 +263,28 @@ export class PlotlyGraph extends HTMLElement { return [start, end + msPad]; } getVisibleRange() { - return this.contentEl.layout.xaxis!.range!.map((date) => - // if autoscale is used after scrolling, plotly returns the dates as numbers instead of strings - Number.isFinite(date) ? date : +parseISO(date) - ); + console.log(this.contentEl.layout.xaxis!.range); + return this.contentEl.layout.xaxis!.range!.map((date) => { + // if autoscale is used after scrolling, plotly returns the dates as timestamps (numbers) instead of iso strings + if (Number.isFinite(date)) return date; + if (date.startsWith("-")) { + /* + The function parseISO can't handle negative dates. + To work around that, I'm parsing it without the minus, and then manually calculating the timestamp from that. + The arithmetic has a twist because timestamps start on 1970 and not on year zero, + so the distance to a the year zero has to be calculated by subtracting the "zero year" timestamp. + positive_date = -date (which is negative) + timestamp = (year 0) - (time from year 0) + timestamp = (year 0) - (positive_date - year 0) + timestamp = 2 * (year 0) - positive_date + timestamp = 2 * (year 0) - (-date) + */ + return ( + 2 * +parseISO("0000-01-01 00:00:00.000") - +parseISO(date.slice(1)) + ); + } + return +parseISO(date); + }); } async enterBrowsingMode() { this.isBrowsing = true; diff --git a/src/themed-layout.ts b/src/themed-layout.ts index 6d6459e..109fd77 100644 --- a/src/themed-layout.ts +++ b/src/themed-layout.ts @@ -14,6 +14,7 @@ const defaultLayout: Partial = { dragmode: "pan", xaxis: { autorange: false, + type: "date", // automargin: true, // it makes zooming very jumpy }, yaxis: {