如何将 JavaScript 倒计时与服务器时间同步

发布于 2024-10-24 21:38:57 字数 261 浏览 1 评论 0原文

我正在建立一个网站,其时间和价格都会下降。我最关心的是同步时间,以便所有客户端的时间尽可能准确。

目前,我向客户端发送剩余的毫秒数,然后用于为倒计时器提供燃料,但由于传输和渲染延迟,即使同一台计算机上有 2 个浏览器,这也可能会延迟几秒钟。

有没有办法同步客户端的 javascript 时间和服务器时间,或者我是否只需要处理这种轻微的延迟?

如果有一种方法可以准确测量服务器之间的时间差就好了发送数据并由客户端接收和呈现。

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.

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?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

很糊涂小朋友 2024-10-31 21:38:58

有一种方法可以使客户端与服务器的时间同步。我编写了一个库来执行此操作:ServerDate

以下是自述文件的一部分:

您可以像使用 Date 函数或其其中之一一样使用 ServerDate
实例,例如:

> 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

There is a way to synchronize a client with the server's time. I wrote a library that does just this: 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()
"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.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
恏ㄋ傷疤忘ㄋ疼 2024-10-31 21:38:58

您可以测量整个服务器往返所花费的时间并除以二以获得时间差的良好估计。请注意:不能保证 IP 包在两个方向上都采用相同的路由,但概率相当高。

如果毫秒分辨率足够您使用,您可以使用 Date.getTime()

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.

You can use Date.getTime() if millisesonds resolution is enough for you.

美羊羊 2024-10-31 21:38:58

解决方案是 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 中的数据有效,这将为您提供正确的用户时区名称 - 请注意,有许多“重复”名称,例如“欧洲/柏林”和“欧洲/苏黎世”,其中具有完全相同的时区设置(至少目前如此),并且您可以获得其中之一的适当偏移量和 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’);

就是这样!

来源:http://togl.me/eE2

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:

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.

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:

$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.

Creating date strings with a given time zone
With 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:

// 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

乱世争霸 2024-10-31 21:38:57

尽管服务器和客户端上的时间不同,但时间变化的速率应该基本相同。我会将剩余时间发送给客户端,让客户端将该时间添加到当前时间,然后让客户端计算倒计时。例如:

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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文