我正在制作一张画布图,它实时更新我们正在向客户展示的信息,并且正在准备时钟上的DST更改。我们的要求之一是图表可以照常运行,而不需要客户在时钟切换时刷新页面。
在解决这个问题时,我发现了Firefox的这个错误:
https://bugzilla.mozilla.org/show_bug.cgi?id=127246
基本上JavaScript中的Date()对象不会在Firefox中更新,如果更改系统时间而不必关闭浏览器/选项卡,并且因为我们使用系统时钟查询API,这是一个非常重要的问题
我假设它没有修复,因为故障单仍然标记为“新”,我也很确定这是导致问题而不是我的代码的另一部分,所以我怎样才能获得当前时间在Firefox中更改系统时钟而不必刷新页面?
仅供参考我正在使用的Firefox版本是19.0.2
提前致谢
示例
将系统时钟设置为12:00并打开网络应用程序...
var currentHour = new Date().getHours() //returns 12
将系统时钟设置为13:00,而无需重新打开网络应用..
var currentHour = new Date().getHours() //returns 12
答案 0 :(得分:9)
您无论如何都不能依赖客户端设置正确的日期/时间。我能想到的唯一解决方法是从其他来源请求当前时间,例如服务器。
如果你不想破坏你自己的服务器,你可以找到一个返回时间戳的公共API,比如某些kind of Time API或具有可靠正常运行时间的服务,例如eBay的Client Alerts API:
http://clientalerts.ebay.com/ws/ecasvc/ClientAlerts?callbackname=hello&callname=GetPublicAlerts
hello({"Timestamp":"2013-03-22T14:43:21.757Z","Ack":"Failure","Errors":[{"ShortMessage":"Missing required input element.","LongMessage":"Required input element is missing from the request.","ErrorCode":"1.19","SeverityCode":"Error","ErrorParameters":[{"Value":"ChannelDescriptor","ParamID":"0"}],"ErrorClassification":"RequestError"}],"Build":"E809_CORE_BUNDLED_15739296_R1","Version":"809"});
忽略所有内容并获取UTC时间戳。只要确保你没有从一些服务器中掏出你真正不需要的数据!
答案 1 :(得分:5)
不是像Sergiu Toarca's answer中那样创建新窗口,而是每次需要更新时都创建一个新的Web工作者。每当生成新的Web worker时,Firefox都会更新Date()
对象。
function currDate() {
var blob = new Blob([""]),
blobURL = window.URL ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob),
worker = new Worker(blobURL);
worker.terminate();
return new Date();
}
您可以像普通Date()
对象一样使用它:
currDate().getHours(); // Gives you an updated hour
请参阅DEMO(适用于Firefox 19)。
答案 2 :(得分:3)
这个问题有一个简单(但非常hacky)的解决方法。您可以创建一个新窗口(由于某种原因重置当前窗口的缓存),从那里获取日期,然后立即关闭窗口。
var getRealDate = function() {
var w = window.open();
var ret = new Date();
w.close();
return ret;
};
在jsfiddle上查看它的工作原理。单击按钮,然后更改您的时区,然后再次单击该按钮,您将获得更新的值。
注意:仅在Firefox 19中测试
答案 3 :(得分:2)
当你在讨论画布的实时更新时,我假设你正在使用某种推送技术,例如使用网络套接字,或者使用一些假推送技术,例如AJAX长轮询。
但是,由于您无论如何都不能依赖客户端时间(如其他答案中所述),为什么不使用实时推送数据包来包含当前时间?
通过这种方式你可以一石二鸟(对不起军事表达,但这就是他们的说法; - )):
您的所有客户需要做的是获取他们最初的时区,然后添加或减去服务器提供的时区的差异。例如,如果您的客户端是UTC + 1而您的服务器是UTC + 4,则只需从服务器提供的每个时间戳中减去3小时。
由于DST更改每年只出现两次,您甚至可以将其硬编码到客户端并使用两种不同的加/减算法。您必须使用哪一个可以根据服务器发送给您的时间戳的日期部分来决定。
这样你就可以解决所有问题,它可以在每个浏览器中运行,并且独立于客户端的任何时间设置。
希望这会有所帮助: - )
答案 4 :(得分:1)
对于OP的特定情况,这是一个超级简单的解决方案,因为我所做的以下假设(基于他的问题和评论中所写的内容)是正确的:
如果上述情况属实(可能甚至不是全部),这就变得非常简单了。因为你真的只担心两个时区,GMT和BST,你可以调整你的例子如下:
在加载时/图初始化时添加这段代码:
// given a date object, returns the actual hour (works for GMT/BST only)
var getDisplayHour = (function() {
var initiallyGMT = (new Date().toString().indexOf('BST') === -1);
return function ( date ) {
var isGMT = (date.toString().indexOf('BST') === -1);
var offset = initiallyGMT - isGMT;
return date.getHours() + offset;
}
})();
将系统时钟设置为12:00并打开网络应用程序...
var currentDisplayHour = getDisplayHour( new Date() ); // returns 12
将系统时钟设置为13:00,而无需重新打开网络应用..
// the referenced bug keeps the same time, but it successfully changes the time zone, so:
var currentDisplayHour = getDisplayHour( new Date() ); // returns 13
在Mac和Windows 7上测试FF 19.0.0.2。
注意:由于我无法重现OP的问题,并考虑引用的用例,我甚至不确定是否需要任何这些解决方法。人们可能期望对OP的用例进行更准确的测试,包括改变时间和区域。例如。不只是12:00 - > 13:00,但格林威治标准时间12:00 - >英国夏令时13:00更准确地模拟DST转换将时钟设置为格林威治标准时间2013-03-31 00:59:00,检查new Date().getHours()
,等待几分钟,然后再次检查小时。 / p>
但是,正如我所说,我自己无法重现所引用的错误,所以我肯定是错的(在这种情况下我会修改或删除这个答案)。
希望这有帮助,无论如何!