From 17c7534a96d3aa59d458bddaff3c5ca6cf772507 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 15 Mar 2023 17:26:05 -0700 Subject: [PATCH] Fix download charts after a DST transition When falling back, a bug in date-fns[^0] results in the 23 hour day being skipped when building the `dates` array in `toChartData` if the current time is between 00:00 and 01:00 UTC. This results in that day's data essentially going missing, resulting in the subtly broken charts noted in #5477. This commit adds a workaround adapted from a comment on date-fns/date-fns#571[^1] by @bertho-zero, which correctly adjusts the new date based on the time zone offsets, and means that `dates` is built as expected. Fixes #5477. [^0]: https://github.com/date-fns/date-fns/issues/571 [^1]: https://github.com/date-fns/date-fns/issues/571#issuecomment-602496322 --- app/components/download-graph.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/components/download-graph.js b/app/components/download-graph.js index 1b70764f9f..4c951f14ab 100644 --- a/app/components/download-graph.js +++ b/app/components/download-graph.js @@ -3,7 +3,7 @@ import { inject as service } from '@ember/service'; import { waitForPromise } from '@ember/test-waiters'; import Component from '@glimmer/component'; -import subDays from 'date-fns/subDays'; +import { addMinutes, subDays as brokenSubDays, subMinutes } from 'date-fns'; import window from 'ember-window-mock'; import semverSort from 'semver/functions/sort'; @@ -190,3 +190,18 @@ export function toChartData(data) { function midnightForDate(date) { return Date.parse(date.toISOString().slice(0, 10)); } + +// This works around a bug in date-fn's subDays() function when crossing a DST +// transition: https://github.com/date-fns/date-fns/issues/571 +// +// The specific implementation is based on @bertho-zero's here: +// https://github.com/date-fns/date-fns/issues/571#issuecomment-602496322 +function subDays(date, amount) { + const originalTZO = date.getTimezoneOffset(); + const endDate = brokenSubDays(date, amount); + const endTZO = endDate.getTimezoneOffset(); + + const dstDiff = originalTZO - endTZO; + + return dstDiff >= 0 ? addMinutes(endDate, dstDiff) : subMinutes(endDate, Math.abs(dstDiff)); +}