如何将 javascript 倒计时与服务器时间同步
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5357719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to sync a javascript countdown with server time
提问by smdrager
I am building a site which has times and prices which tick down. The thing I am most concerned with is syncing time so that it is as accurate as possible across all clients.
我正在建立一个网站,它的时间和价格都在下降。我最关心的是同步时间,以便它在所有客户端上尽可能准确。
Currently, I am sending the client the number of milliseconds left which is then used to fuel the countdown timer, but due to transfer and rendering delays, this can be off by several seconds even with 2 browsers on the same computer.
目前,我正在向客户端发送剩余的毫秒数,然后用于为倒数计时器提供燃料,但由于传输和渲染延迟,即使在同一台计算机上有 2 个浏览器,这也可能会关闭几秒钟。
Is there a way to sync the client's javascript time and server time, or am I just going to have to deal with this slight lag?
有没有办法同步客户端的 javascript 时间和服务器时间,或者我只需要处理这种轻微的延迟?
If only there was a way to accurately measure the time difference between the server sending the data and it being received and rendered by the client.
如果只有一种方法可以准确测量服务器发送数据与客户端接收和呈现数据之间的时间差。
回答by tilleryj
Even though the time on the server and client is going to be different, the rate at which time changes should essentially be same. I would send the remaining time down to the client, let the client then add that time to the current time, and then have the client calculate the countdown from that. For example:
即使服务器和客户端上的时间不同,时间变化的速率也应该基本相同。我会将剩余时间发送给客户端,让客户端然后将该时间添加到当前时间,然后让客户端从中计算倒计时。例如:
var timeRemaining = [rendered on page load or queried by ajax]; // in milliseconds
var endTime = new Date(new Date().getTime() + timeRemaining);
// Put this in a setInterval, or however you currently handle it
var countdown = (endTime.getTime() - new Date().getTime()) / 1000;
回答by David Braun
There is a way to synchronize a client with the server's time. I wrote a library that does just this: ServerDate.
有一种方法可以将客户端与服务器的时间同步。我写了一个库来做这个:ServerDate。
Here's part of the README:
这是自述文件的一部分:
You can use ServerDate
as you would use the Date
function or one of its
instances, e.g.:
您可以ServerDate
像使用该Date
函数或其实例之一一样使用,例如:
> ServerDate()
"Mon Aug 13 2012 20:26:34 GMT-0300 (ART)"
> ServerDate.now()
1344900478753
> ServerDate.getMilliseconds()
22
There is also a new method to get the precision of ServerDate's estimate of the server's clock (in milliseconds):
还有一种新方法可以获取 ServerDate 对服务器时钟的估计精度(以毫秒为单位):
> ServerDate.toLocaleString() + " ± " + ServerDate.getPrecision() + " ms"
"Tue Aug 14 01:01:49 2012 ± 108 ms"
You can see the difference between the server's clock and the browsers clock, in milliseconds:
您可以看到服务器时钟和浏览器时钟之间的差异,以毫秒为单位:
> ServerDate - new Date()
39
回答by Alexander Gessler
You can measure the time the full server roundtrip takes and divide by two to get a good estimate for the time difference. Be careful: it's not guaranteed that IP packages take the same route in both directions, but the propability is quite high.
您可以测量整个服务器往返所需的时间并将其除以 2 以获得对时间差的准确估计。注意:不能保证IP包在两个方向上走相同的路线,但概率相当高。
You can use Date.getTime()
if millisesonds resolution is enough for you.
Date.getTime()
如果毫秒分辨率对您来说足够了,您可以使用。
回答by Oral üNAL
The solution to this is Javascript – it can access time zone settings on the client. Unfortunately it can only get you time zone offsets (specified in minutes) for specific dates, no time zone name. So to pinpoint the correct time zone we also need to know if daylight saving time (DST) is being employed – this is the client side part of the solution:
对此的解决方案是 Javascript——它可以访问客户端上的时区设置。不幸的是,它只能为您提供特定日期的时区偏移量(以分钟为单位),没有时区名称。因此,为了确定正确的时区,我们还需要知道是否正在使用夏令时 (DST)——这是解决方案的客户端部分:
var now = new Date();
var later = new Date();
// Set time for how long the cookie should be saved
later.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
// Set cookie for the time zone offset in minutes
setCookie("time_zone_offset", now.getTimezoneOffset(), later, "/");
// Create two new dates
var d1 = new Date();
var d2 = new Date();
// Date one is set to January 1st of this year
// Guaranteed not to be in DST for northern hemisphere,
// and guaranteed to be in DST for southern hemisphere
// (If DST exists on client PC)
d1.setDate(1);
d1.setMonth(1);
// Date two is set to July 1st of this year
// Guaranteed to be in DST for northern hemisphere,
// and guaranteed not to be in DST for southern hemisphere
// (If DST exists on client PC)
d2.setDate(1);
d2.setMonth(7);
// If time zone offsets match, no DST exists for this time zone
if(parseInt(d1.getTimezoneOffset())==parseInt(d2.getTimezoneOffset()))
{
setCookie("time_zone_dst", "0", later, "/");
}
// DST exists for this time zone – check if it is currently active
else {
// Find out if we are on northern or southern hemisphere
// Hemisphere is positive for northern, and negative for southern
var hemisphere = parseInt(d1.getTimezoneOffset())-parseInt(d2.getTimezoneOffset());
// Current date is still before or after DST, not containing DST
if((hemisphere>0 && parseInt(d1.getTimezoneOffset())==parseInt(now.getTimezoneOffset())) ||
(hemisphere<0 && parseInt(d2.getTimezoneOffset())==parseInt(now.getTimezoneOffset()))) { setCookie("time_zone_dst", "0", later, "/"); } // DST is active right now with the current date else { setCookie("time_zone_dst", "1", later, "/"); } }
You save the results as cookies, which can be accessed by your PHP script. You should include the above code on at least the first page a user accesses – I include it on every page to recognize (and adapt to) changes, even if such changes during a session are unlikely.
您将结果保存为 cookie,您的 PHP 脚本可以访问它。您应该至少在用户访问的第一个页面上包含上述代码——我将它包含在每个页面上以识别(并适应)更改,即使在会话期间此类更改不太可能发生。
In PHP you can extract a valid time zone with a new function named timezone_name_from_abbr, available since PHP 5.1.3 – it either takes a time zone abbreviation or a combination of time zone offset (in seconds) and daylight saving time, and we have the latter combination:
在 PHP 中,您可以使用名为 timezone_name_from_abbr 的新函数提取有效时区,该函数自 PHP 5.1.3 起可用 - 它采用时区缩写或时区偏移(以秒为单位)和夏令时的组合,我们有后一种组合:
$time_zone_name = timezone_name_from_abbr(", -$_COOKIE['time_zone_offset']*60, $_COOKIE['time_zone_dst']);
This will give you a correct time zone name for the user, if the data in the cookies is valid – note that there are many “duplicate” names, for example “Europe/Berlin” and “Europe/Zurich”, which have the exact same time zone settings (at least for now), and you may get either one of them for the appropriate offset and DST variables. The list of time zone names can be found in the List of supported time zones on php.net.
如果 cookie 中的数据有效,这将为您提供正确的用户时区名称 - 请注意,有许多“重复”名称,例如“欧洲/柏林”和“欧洲/苏黎世”,它们具有准确的名称相同的时区设置(至少现在是这样),您可能会为适当的偏移量和 DST 变量获得其中之一。时区名称列表可以在 php.net 上的支持时区列表中找到。
Creating date strings with a given time zoneWith the name of the user's time zone you can now use the PHP classes DateTimeZone and DateTime to finally create date strings with the correct time zone:
创建具有给定时区的日期字符串使用用户时区的名称,您现在可以使用 PHP 类 DateTimeZone 和 DateTime 最终创建具有正确时区的日期字符串:
// Create time zone class
$time_zone_class = new DateTimeZone($time_zone_name);
// Create new date class with a given date
// Notice that the provided date will be regarded as being in the
// default time zone and converted accordingly
$new_date = new DateTime(‘2007-02-14 15:30:00′, $time_zone_class);
// Print date with the user's time zone echo $new_date->format(‘Y-m-d H:i:s');
That's it!
就是这样!
Source: http://togl.me/eE2
来源:http: //togl.me/eE2