From: Dan Vanderkam Date: Mon, 18 Feb 2013 02:17:51 +0000 (-0500) Subject: Fix some more DST issues X-Git-Tag: v1.0.0~66 X-Git-Url: https://adrianiainlam.tk/git/?a=commitdiff_plain;h=0f9bf3690e52ba8fcc62e652aeb2c4b9c722df03;p=dygraphs.git Fix some more DST issues --- diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index a40a1d2..c95f35a 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -782,4 +782,48 @@ AxisLabelsTestCase.prototype.testLabelsCrossDstChange = function() { for (var i = 0; i < xLabels.length; i++) { assertTrue(okLabels[xLabels[i]]); } + + // This range had issues of its own on tests/daylight-savings.html. + g.updateOptions({ + dateWindow: [1289109997722.8127, 1289261208937.7659] + }); + xLabels = Util.getXLabels(); + for (var i = 0; i < xLabels.length; i++) { + assertTrue(okLabels[xLabels[i]]); + } +}; + + +// Tests data which crosses a "fall back" at a high enough frequency that you +// can see both 1:00 A.M.s. +AxisLabelsTestCase.prototype.testLabelsCrossDstChangeHighFreq = function() { + // Generate data which crosses the EST/EDT boundary. + var dst_data = []; + var base_ms = 1383454200000; + for (var x = base_ms; x < base_ms + 1000 * 60 * 80; x += 1000) { + dst_data.push([new Date(x), x]); + } + + var g = new Dygraph( + document.getElementById("graph"), + dst_data, + { width: 1024, labels: ['Date', 'Value'] } + ); + + assertEquals([ + '00:50', '00:55', + '01:00', '01:05', '01:10', '01:15', '01:20', '01:25', + '01:30', '01:35', '01:40', '01:45', '01:50', '01:55', + '01:00', '01:05' // 1 AM number two! + ], Util.getXLabels()); + + // Now zoom past the initial 1 AM. This used to cause trouble. + g.updateOptions({ + dateWindow: [1383454200000 + 15*60*1000, g.xAxisExtremes()[1]]} + ); + assertEquals([ + '01:05', '01:10', '01:15', '01:20', '01:25', + '01:30', '01:35', '01:40', '01:45', '01:50', '01:55', + '01:00', '01:05' // 1 AM number two! + ], Util.getXLabels()); }; diff --git a/dygraph-tickers.js b/dygraph-tickers.js index 65355e5..e57e8bd 100644 --- a/dygraph-tickers.js +++ b/dygraph-tickers.js @@ -340,6 +340,25 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { var ticks = []; var t; + var setters = { + ms: Date.prototype.setMilliseconds, + s: Date.prototype.setSeconds, + m: Date.prototype.setMinutes, + h: Date.prototype.setHours + }; + var safeSet = function(d, parts) { + var tz = d.getTimezoneOffset(); + for (var k in parts) { + if (!parts.hasOwnProperty(k)) continue; + var setter = setters[k]; + if (!setter) throw "Invalid setter: " + k; + setter.call(d, parts[k]); + if (d.getTimezoneOffset() != tz) { + d.setTime(d.getTime() + (tz - d.getTimezoneOffset()) * 60 * 1000); + } + } + }; + if (granularity < Dygraph.MONTHLY) { // Generate one tick mark for every fixed interval of time. var spacing = Dygraph.SHORT_SPACINGS[granularity]; @@ -348,21 +367,25 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { // for this granularity. var g = spacing / 1000; var d = new Date(start_time); - d.setMilliseconds(0); + safeSet(d, {ms: 0}); + var x; if (g <= 60) { // seconds - x = d.getSeconds(); d.setSeconds(x - x % g); + x = d.getSeconds(); + safeSet(d, {s: x - x % g}); } else { - d.setSeconds(0); + safeSet(d, {s: 0}); g /= 60; if (g <= 60) { // minutes - x = d.getMinutes(); d.setMinutes(x - x % g); + x = d.getMinutes(); + safeSet(d, {m: x - x % g}); } else { - d.setMinutes(0); + safeSet(d, {m: 0}); g /= 60; if (g <= 24) { // days - x = d.getHours(); d.setHours(x - x % g); + x = d.getHours(); + d.setHours(x - x % g); } else { d.setHours(0); g /= 24; @@ -376,13 +399,15 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { start_time = d.getTime(); var start_offset_min = new Date(start_time).getTimezoneOffset(); + var check_dst = (spacing >= Dygraph.SHORT_SPACINGS[Dygraph.TWO_HOURLY]); + for (t = start_time; t <= end_time; t += spacing) { var d = new Date(t); // This ensures that we stay on the same hourly "rhythm" across // daylight savings transitions. Without this, the ticks could get off // by an hour. See tests/daylight-savings.html or issue 147. - if (d.getTimezoneOffset() != start_offset_min) { + if (check_dst && d.getTimezoneOffset() != start_offset_min) { t += (d.getTimezoneOffset() - start_offset_min) * 60 * 1000; d = new Date(t); start_offset_min = d.getTimezoneOffset(); diff --git a/tests/daylight-savings.html b/tests/daylight-savings.html index 2961883..4e9e4c0 100644 --- a/tests/daylight-savings.html +++ b/tests/daylight-savings.html @@ -36,7 +36,9 @@ "2010-11-07 00:00:00,177796\n" + "2010-11-08 00:00:00,165587\n" + "2010-11-09 00:00:00,164380\n", - { width: 1024 } + { + width: 1024 + } ); // Generate data which crosses the EST/EDT boundary.