我正在建立一个有时间和价格下降的网站。我最关心的是同步时间,以便在所有客户端尽可能准确。
目前,我正在向客户端发送剩余的毫秒数,然后用于为倒数计时器提供燃料,但由于传输和渲染延迟,即使在同一台计算机上有2个浏览器,也可以关闭几秒钟。 / p>
有没有办法同步客户端的javascript时间和服务器时间,或者我只是要处理这种轻微的延迟?
如果只有一种方法可以准确测量发送数据的服务器与客户端接收和呈现数据之间的时差。
答案 0 :(得分:22)
即使服务器和客户端上的时间不同,时间变化的速率也应基本相同。我会将剩余时间发送到客户端,然后让客户端将该时间添加到当前时间,然后让客户端计算倒计时。例如:
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;
答案 1 :(得分:14)
有一种方法可以将客户端与服务器的时间同步。我写了一个这样做的库:ServerDate。
这是自述文件的一部分:
您可以像使用ServerDate
函数或其中一个函数一样使用Date
实例,例如:
> ServerDate()
"Mon Aug 13 2012 20:26:34 GMT-0300 (ART)"
> ServerDate.now()
1344900478753
> ServerDate.getMilliseconds()
22
还有一种新方法可以获得ServerDate估计的精确度 服务器的时钟(以毫秒为单位):
> ServerDate.toLocaleString() + " ± " + ServerDate.getPrecision() + " ms"
"Tue Aug 14 01:01:49 2012 ± 108 ms"
您可以看到服务器时钟和浏览器时钟之间的差异,以毫秒为单位:
> ServerDate - new Date()
39
答案 2 :(得分:1)
您可以测量完整服务器往返所用的时间并除以2,以获得对时间差的良好估计。注意:不能保证IP包在两个方向上采用相同的路由,但可用性非常高。
如果millisesonds分辨率足够你,你可以使用Date.getTime()
。
答案 3 :(得分:0)
解决方案是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, "/"); } }
您将结果保存为cookie,您可以通过PHP脚本访问它。您应该至少在用户访问的第一页上包含上述代码 - 我将其包含在每个页面上以识别(并适应)更改,即使在会话期间不太可能发生此类更改。
在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']);
如果Cookie中的数据有效,这将为您提供正确的时区名称 - 请注意,有许多“重复”名称,例如“Europe / Berlin”和“Europe / Zurich”,具有完全相同的时区设置(至少目前为止),您可以获得其中任何一个用于适当的偏移和DST变量。时区名称列表可以在php.net上支持的时区列表中找到。
使用给定时区创建日期字符串 使用用户时区的名称,您现在可以使用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’);
就是这样!