From fb0c64b0bbf49f2f6eaa44f0e846057655831a47 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Mon, 18 Feb 2013 00:31:54 -0500 Subject: [PATCH] Fix & regression test for issue 433: Glitch in two-hourly ticks when crossing a "spring forward" daylight savings switch --- auto_tests/tests/axis_labels.js | 60 +++++++++++++++++++++++++++++++++++++++++ dygraph-tickers.js | 14 +++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index c95f35a..4f041c1 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -827,3 +827,63 @@ AxisLabelsTestCase.prototype.testLabelsCrossDstChangeHighFreq = function() { '01:00', '01:05' // 1 AM number two! ], Util.getXLabels()); }; + + +// Tests data which crosses a "spring forward" at a low frequency. +// Regression test for http://code.google.com/p/dygraphs/issues/detail?id=433 +AxisLabelsTestCase.prototype.testLabelsCrossSpringForward = function() { + var g = new Dygraph( + document.getElementById("graph"), + "Date/Time,Purchases\n" + + "2011-03-11 00:00:00,167082\n" + + "2011-03-12 00:00:00,168571\n" + + "2011-03-13 00:00:00,177796\n" + + "2011-03-14 00:00:00,165587\n" + + "2011-03-15 00:00:00,164380\n", + { + width: 1024, + dateWindow: [1299989043119.4365, 1300080693627.4866] + }); + + var okLabels = { + '13Mar': true, + // '02:00': true, // not a real time! + '04:00': true, + '06:00': true, + '08:00': true, + '10:00': true, + '12:00': true, + '14:00': true, + '16:00': true, + '18:00': true, + '20:00': true, + '22:00': true, + '14Mar': true + }; + + var xLabels = Util.getXLabels(); + for (var i = 0; i < xLabels.length; i++) { + assertTrue(okLabels[xLabels[i]]); + } +}; + +AxisLabelsTestCase.prototype.testLabelsCrossSpringForwardHighFreq = function() { + var base_ms_spring = 1299999000000; + var dst_data_spring = []; + for (var x = base_ms_spring; x < base_ms_spring + 1000 * 60 * 80; x += 1000) { + dst_data_spring.push([new Date(x), x]); + } + + var g = new Dygraph( + document.getElementById("graph"), + dst_data_spring, + { width: 1024, labels: ['Date', 'Value'] } + ); + + assertEquals([ + '01:50', '01:55', + '03:00', '03:05', '03:10', '03:15', '03:20', '03:25', + '03:30', '03:35', '03:40', '03:45', '03:50', '03:55', + '04:00', '04:05' + ], Util.getXLabels()); +}; diff --git a/dygraph-tickers.js b/dygraph-tickers.js index 4b4d9dd..c6939cb 100644 --- a/dygraph-tickers.js +++ b/dygraph-tickers.js @@ -392,9 +392,21 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { // daylight savings transitions. Without this, the ticks could get off // by an hour. See tests/daylight-savings.html or issue 147. if (check_dst && d.getTimezoneOffset() != start_offset_min) { - t += (d.getTimezoneOffset() - start_offset_min) * 60 * 1000; + var delta_min = d.getTimezoneOffset() - start_offset_min; + t += delta_min * 60 * 1000; d = new Date(t); start_offset_min = d.getTimezoneOffset(); + + // Check whether we've backed into the previous timezone again. + // This can happen during a "spring forward" transition. In this case, + // it's best to skip this tick altogether (we may be shooting for a + // non-existent time like the 2AM that's skipped) and go to the next + // one. + if (new Date(t + spacing).getTimezoneOffset() != start_offset_min) { + t += spacing; + d = new Date(t); + start_offset_min = d.getTimezoneOffset(); + } } ticks.push({ v:t, -- 2.7.4