夏令时的Javascript日期计算错误

时间:2019-10-02 05:18:35

标签: javascript timezone-offset

我正在三个连续的日期使用JavaScript进行以下相同的计算。

在墨尔本的“日光节约”生效之日(2019-10-06),得出的日期有所不同。第一个和第三个正确显示日期,第二个正确显示日期为10月5日。

有人可以告诉我哪里出了问题吗?

var apiRes = "2019-10-05";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

var apiRes = "2019-10-06";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

var apiRes = "2019-10-07";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

2 个答案:

答案 0 :(得分:1)

我通常使用中午12点来确保不碰到这个-也许我们需要15:00来确定

var apiRes = "2019-10-05 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-06 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-07 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-27 15:00:00"; // EU DST ends
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

答案 1 :(得分:1)

解释问题: 日期“ 2019-10-06”为2019-10-06:T00:00:00Z-2019-10-06:11:00:00UTC+11,因为到了2019-10-06:T00:00:00Z时,夏令时开始了。

因此,当您“计算”时区时,您将减去11小时,而不是10小时。

但是,由于在墨尔本的上午11点,一天只有10个小时,因此您的调整后的日期为2019-10-05:23:00:00UTC+10

如果您的目标是仅使用YYYY-MM-DD字符串获取午夜,那么有几种方法可以实现。

在UTC和UTC的时区EAST中,

d.setHours(0,0);

(您想要像阿德莱德这样的奇数时区的第二个0)

然后在UTC以西的时区,您需要

d.setDate(d.getDate() + 1)

您还可以在应用更改之前和之后检查时区偏移量,并进行相应的调整-我并没有为此烦恼

但是,我认为是最简单,最可靠的方法,并且仅使用Date构造函数中指定的方法(即“保证”可以跨环境工作),如下所述

看起来有点时髦,但是根本不需要了解本地时区偏移

var apiRes = "2019-10-05";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

var apiRes = "2019-10-06";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

var apiRes = "2019-10-07";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

解释...apiRes.split('-').map((n, i) => Number(n) - (i %2))

apiRes.split('-') // results in ["2019", "10", "06"]

所以我们现在有...["2019", "10", "06"].map((n, i) => Number(n) - (i %2))

下一步

.map(n, i) => Number(n) - (i %2))

将每个元素转换为一个数字,并在索引为1时减去1,即每个月减去1,因为在构造函数中为零

现在我们有:

new Date(...[2019, 9, 6])

在ES6 +中就像

new Date(2019, 9, 6)

哪个将在午夜根据给定的y / m / d构造一个日期