Подтвердить что ты не робот

Как синхронизировать обратный отсчет javascript с временем сервера

Я создаю сайт, который имеет время и цены, которые тикают. То, что меня больше всего волнует, - это синхронизировать время, чтобы оно было максимально точным для всех клиентов.

В настоящее время я отправляю клиенту количество оставшихся миллисекунд, которое затем используется для подачи таймера обратного отсчета, но из-за задержки передачи и визуализации это может быть отключено на несколько секунд даже при использовании двух браузеров на одном компьютере.

Есть ли способ синхронизировать время javascript клиента и время сервера, или мне просто придется иметь дело с этим небольшим отставанием?

Если бы только был способ точно измерить разницу во времени между сервером, отправляющим данные, и он был получен и отображен клиентом.

4b9b3361

Ответ 1

Несмотря на то, что время на сервере и клиенте будет отличаться, скорость изменения времени должна быть одинаковой. Я отправил оставшееся время на клиент, дайте клиенту добавить это время к текущему времени, а затем попросит клиента вычислить обратный отсчет от этого. Например:

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;

Ответ 2

Существует способ синхронизации данных времени javascript клиента и времени сервера. Я написал библиотеку, которая делает именно это: ServerDate.

Здесь часть README:

Вы можете использовать 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

Ответ 3

Вы можете измерить время, в течение которого весь серверный раунд перемещается, и делить на два, чтобы получить хорошую оценку разницы во времени. Будьте осторожны: это не гарантирует, что IP-пакеты используют один и тот же маршрут в обоих направлениях, но проницаемость довольно высока.

Вы можете использовать Date.getTime(), если для вас достаточно разрешения на миллисекунды.

Ответ 4

Решением этого является 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 script. Вы должны включить приведенный выше код, по крайней мере, на первую страницу, к которой пользователь обращается - я включаю его на каждой странице для распознавания (и адаптации) изменений, даже если такие изменения во время сеанса маловероятны.

В 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