From 6582eba1ca8a1e69493a98fa8217b4b1daa9afc4 Mon Sep 17 00:00:00 2001 From: sushuang Date: Fri, 8 Sep 2017 11:45:53 +0800 Subject: [PATCH] Fix parseDate, consider DST --- src/scale/Time.js | 8 +++--- src/util/number.js | 63 ++++++++++++++++++++++++++++++---------------- test/timeZone.html | 4 +-- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/scale/Time.js b/src/scale/Time.js index ddfd2b431..72119d1ac 100644 --- a/src/scale/Time.js +++ b/src/scale/Time.js @@ -77,7 +77,7 @@ define(function (require) { // If there are no data and extent are [Infinity, -Infinity] if (extent[1] === -Infinity && extent[0] === Infinity) { var d = new Date(); - extent[1] = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); extent[0] = extent[1] - ONE_DAY; } @@ -98,8 +98,6 @@ define(function (require) { * @override */ niceTicks: function (approxTickNum, minInterval, maxInterval) { - var timezoneOffset = this.getSetting('useUTC') - ? 0 : numberUtil.getTimezoneOffset() * 60 * 1000; approxTickNum = approxTickNum || 10; var extent = this._extent; @@ -129,9 +127,11 @@ define(function (require) { interval *= yearStep; } + var timezoneOffset = this.getSetting('useUTC') + ? 0 : (new Date(+extent[0] || +extent[1])).getTimezoneOffset() * 60 * 1000; var niceExtent = [ Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset), - Math.round(mathFloor((extent[1] - timezoneOffset)/ interval) * interval + timezoneOffset) + Math.round(mathFloor((extent[1] - timezoneOffset) / interval) * interval + timezoneOffset) ]; scaleHelper.fixExtent(niceExtent, extent); diff --git a/src/util/number.js b/src/util/number.js index dab93cc08..64419ae7f 100644 --- a/src/util/number.js +++ b/src/util/number.js @@ -273,11 +273,14 @@ define(function (require) { var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line /** + * Consider DST, it is incorrect to provide a method `getTimezoneOffset` + * without time specified. So this method is removed. + * * @return {number} in minutes */ - number.getTimezoneOffset = function () { - return (new Date()).getTimezoneOffset(); - }; + // number.getTimezoneOffset = function () { + // return (new Date()).getTimezoneOffset(); + // }; /** * @param {string|Date|number} value These values can be accepted: @@ -311,24 +314,42 @@ define(function (require) { return new Date(NaN); } - var timezoneOffset = number.getTimezoneOffset(); - var timeOffset = !match[8] - ? 0 - : match[8].toUpperCase() === 'Z' - ? timezoneOffset - : +match[8].slice(0, 3) * 60 + timezoneOffset; - - // match[n] can only be string or undefined. - // But take care of '12' + 1 => '121'. - return new Date( - +match[1], - +(match[2] || 1) - 1, - +match[3] || 1, - +match[4] || 0, - +(match[5] || 0) - timeOffset, - +match[6] || 0, - +match[7] || 0 - ); + // Use local time when no timezone offset specifed. + if (!match[8]) { + // match[n] can only be string or undefined. + // But take care of '12' + 1 => '121'. + return new Date( + +match[1], + +(match[2] || 1) - 1, + +match[3] || 1, + +match[4] || 0, + +(match[5] || 0), + +match[6] || 0, + +match[7] || 0 + ); + } + // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time, + // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment). + // For example, system timezone is set as "Time Zone: America/Toronto", + // then these code will get different result: + // `new Date(1478411999999).getTimezoneOffset(); // get 240` + // `new Date(1478412000000).getTimezoneOffset(); // get 300` + // So we should not use `new Date`, but use `Date.UTC`. + else { + var hour = +match[4] || 0; + if (match[8].toUpperCase() !== 'Z') { + hour -= match[8].slice(0, 3); + } + return new Date(Date.UTC( + +match[1], + +(match[2] || 1) - 1, + +match[3] || 1, + hour, + +(match[5] || 0), + +match[6] || 0, + +match[7] || 0 + )); + } } else if (value == null) { return new Date(NaN); diff --git a/test/timeZone.html b/test/timeZone.html index a7df234f9..485c47f62 100644 --- a/test/timeZone.html +++ b/test/timeZone.html @@ -22,10 +22,10 @@ -

time scale label shoule in local time when timestamp (in UTC) input, tick should align with day.

+

time scale label should in local time when timestamp (in UTC) input, tick should align with day.

-

time scale label shoule in UTC time when option.useUTC is `true`, tick should not align with day.

+

time scale label should in UTC time when option.useUTC is `true`, tick should not align with day.

useUTC: null, should display '00:00 01-03' in tooltip on the 1st point

-- GitLab