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

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

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

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

Если бы только был способ точно измерить разницу во времени между отправкой сервером данных и их получением и рендерингом клиентом.


person smdrager    schedule 18.03.2011    source источник
comment
что вы думаете о подпитке таймера обратного отсчета с помощью вызова ajax после загрузки страницы, вы могли бы изначально не отображать счетчик, скрывая его, а затем отображать при успехе ajax. Запрос был бы намного быстрее, так как вы не отправляете сообщение на всю страницу.   -  person The Muffin Man    schedule 19.03.2011
comment
@The Muffin Man вызов ajax также зависит от объема трафика / нагрузки на сервер ... это также приведет к задержке.   -  person girish    schedule 04.04.2018


Ответы (4)


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

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;
person tilleryj    schedule 18.03.2011
comment
Обратите внимание, что если вы заполните timeRemaining при загрузке страницы, иногда страница кэшируется веб-браузером, и эта кэшированная версия будет отображаться, если ваш пользователь уходит со страницы и возвращается на нее с помощью кнопки «Назад». В этом случае будет казаться, что таймер вообще не сдвинулся (поскольку timeRemaining остается в кэше и не изменяется). Действительно сложно. - person stereoscott; 26.07.2012
comment
Я вообще не могу этого понять, что вы имеете в виду под скоростью изменения времени? когда сервер вычисляет оставшееся время, а затем отправляет его, где задержка для задержки ответа? - person Karim Tarabishy; 02.08.2014
comment
Скорость изменения времени @Doggynub означает, что 1 секунда на клиенте такая же, как 1 секунда на сервере. - person ian; 02.12.2014
comment
Единственная проблема здесь заключается в том, что обратный отсчет Мастера должен быть эталоном для обратного отсчета последователей. Скажем, у вас есть участник, который не может ответить на вопрос через 1:00, и зрители, наблюдающие за ним, хотят отслеживать его обратный отсчет. Задержки сервера могут означать разницу в 1/2 секунды. Я прав? - person Laurent; 22.11.2015

Есть способ синхронизировать клиент со временем сервера. Я написал библиотеку, которая делает именно это: 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
person David Braun    schedule 14.08.2012
comment
Рада, что нашла вашу работу. Это очень помогает мне, особенно при работе с обратным отсчетом, который нужно синхронизировать со всеми остальными. Я думал, что серверное время основано, но не знал, как правильно его реализовать, но вы это сделали. Руки вниз. Можно ли добавить обратные вызовы, например, если местное время не синхронизировано или когда оно уже синхронизировано? - person Kenneth Palaganas; 28.04.2018
comment
Не стесняйтесь создавать проблему на GitHub и давайте обсудим ее там. - person David Braun; 11.05.2018
comment
Пожалуйста, не могли бы вы уточнить, относится ли ServerDate.js к этому комментарию опасается кэширования страниц? - person rybo111; 30.05.2018
comment
Он обрабатывает кэширование страниц. - person David Braun; 31.05.2018

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

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

person Alexander Gessler    schedule 18.03.2011
comment
Плюс смещение для любой разницы системных часов сервера и клиента. - person Nick Sweeting; 11.07.2017

Решением этой проблемы является 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 действительны — обратите внимание, что существует много «дубликатов» имен, например «Европа/Берлин» и «Европа/Цюрих», которые имеют точное одинаковые настройки часового пояса (по крайней мере, на данный момент), и вы можете получить любой из них для соответствующих переменных смещения и летнего времени. Список названий часовых поясов можно найти в списке поддерживаемых часовых поясов на 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

person Oral ÜNAL    schedule 19.02.2012