gpt4 book ai didi

javascript - 消除Javascript夏令时差距,跨浏览器解决方案

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:53:24 24 4
gpt4 key购买 nike

经过一番折腾,我终于找到了真正的问题所在。这是由夏令时引起的差距,如果时区设置为 UTC+3:30(我不确定其他时区),不同浏览器的行为会有所不同。

这是产生问题的一个片段(如果您的系统的 TZ 设置为 UTC+3:30,问题是可重现的):

function zeroPad(n) {
n = n + '';
return n.length >= 2 ? n : new Array(2 - n.length + 1).join('0') + n;
}

document.write("<table border='1' cellpadding='3'><tr><td>Input date</td><td>Parsed timestamp</td><td>Output date</td></tr>");

var m = 22 * 60;
for (var i=0; i<8; i++) {
var input = "3/21/2015 " + zeroPad(Math.floor(m / 60)) + ":" + zeroPad(m % 60) + ":00";
var d = new Date(input);
var output = d.getFullYear()
+'-'+zeroPad(d.getMonth()+1)
+'-'+zeroPad(d.getDate())
+' '+zeroPad(d.getHours())
+':'+zeroPad(d.getMinutes())
+':'+zeroPad(d.getSeconds());


document.write("<tr><td>" + input + "</td><td>" + d.getTime() + "</td><td>" + output + "</td></tr>");
m = m + 15;
}
m = 0;
for (var i=0; i<7; i++) {
var input = "3/22/2015 " + zeroPad(Math.floor(m / 60)) + ":" + zeroPad(m % 60) + ":00";
var d = new Date(input);
var output = d.getFullYear()
+'-'+zeroPad(d.getMonth()+1)
+'-'+zeroPad(d.getDate())
+' '+zeroPad(d.getHours())
+':'+zeroPad(d.getMinutes())
+':'+zeroPad(d.getSeconds());


document.write("<tr><td>" + input + "</td><td>" + d.getTime() + "</td><td>" + output + "</td></tr>");
m = m + 15;
}

document.write("</table>");

我已经在 Firefox 和 Chromium 上运行了它,这是他们说的:

enter image description here

红框内的部分为gap发生的时间范围。我的问题是像日历这样的组件通常依赖于时间部分设置为“00:00:00”的日期对象,并且它们有一个循环通过在前一个日期上添加一天的时间戳来生成新日期。因此,一旦对象落入 3/22/2015 00:00:00,它将被视为 3/22/2015 01:00:0021/3/2015 23:00:00(取决于浏览器)因此生成的日期从那个时间点开始将无效!

问题是如何检测此类日期对象以及如何处理它们?

最佳答案

使用 moment.js将为您省去很多麻烦,并且是实现此类事情的跨浏览器兼容性的最简单方法。

var m = moment.utc("3/22/2015","M/D/YYYY")
var s = m.format("YYYY-MM-DD HH:mm:ss")

为此使用 UTC 很重要,因为您不希望受到用户时区的影响。否则,如果您的日期进入 DST 转换,它可能会调整为其他值。 (您不是真的对 UTC 感兴趣,您只是为了稳定使用它。)


针对您更新问题的这一部分:

To simplify the question, I'm looking for a function like this:

function date_decomposition(d) {
...
}

console.log(date_decomposition(new Date("3/22/2015 00:00:00")));
=> [2015, 3, 22, 0, 0, 0]

虽然现在很清楚您的要求,但您必须了解不可能实现您的确切要求,至少不能以跨浏览器、跨区域、跨时区的方式实现.

  • 每个浏览器都有自己的方式来实现字符串到最新的解析。当您使用构造函数 new Date(string)Date.parse(string) 方法时,您正在调用特定于实现.

    There's a chart showing many of the formatting differences here.

  • 即使实现在所有环境中都是一致的,您仍需要应对区域格式和时区差异。

综上所述,您当然可以获取一个Date对象并解构它的各个部分,非常简单:

function date_decomposition(d) {
return [d.getFullYear(), d.getMonth()+1, d.getDate(),
d.getHours(), d.getMinutes(), d.getSeconds()];
}

但这将始终基于运行代码的本地时区。你看,在 Date 对象中,只有一个值 - 一个数字,表示自 1970-01-01T00:00:00Z 以来经过的毫秒数(不考虑闰秒).该数字是基于 UTC 的。

因此,总而言之,您遇到的所有问题都与将字符串解析为 Date 对象的方式有关。再多关注输出函数也无法帮助您以完全安全的方式解决该问题。无论您使用库还是编写自己的代码,都需要获取原始数据字符串才能获得所需的结果。当它位于 Date 对象中时,您已经丢失了完成这项工作所需的信息。

顺便说一下,您可以考虑观看我的 Pluralsight 类(class),Date and Time Fundamentals ,其中更详细地涵盖了其中的大部分内容。第 7 单元完全是关于 JavaScript 和这些陷阱的。

关于javascript - 消除Javascript夏令时差距,跨浏览器解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28989484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com