Нужно, чтобы клиент максимально точно «знал», сколько сейчас времени на сервере. Для этого можно несколько раз послать запрос на сервер, и
предположить, что время ответа сервера лежит точно посередине между отправкой запроса и получением ответа. Примерно так работает
NTP – протокол сетевого времени.
Второе предположение, что ход собственных часов точен: 1 секунда на клиенте и на сервере точно равны.
На сервере разместить простейший скрипт, который возвращает время с миллисекундами до События:
// getTimeTill.php
$deadline = strtotime("2017-07-01 03:00:00");
echo round( 1000 * $deadline - 1000 * microtime(true)); // в миллисекундах
На клиенте в JS надо засечь время, выполнить ajax запрос, получить ответ, и считать, что полученное число микросекунд оставалось до события половину разницы назад:
var start = (new Date).getTime();
$.get("getTimeTill.php", function( ms ){
var bias = Math.round(((new Date).getTime() - start) / 2);
var remains = ms + bias; // сколько остаётся микросекунд до события на данный момент
var deadline = (new Date).getTime() + remains; // локальное время События
// можно запускать таймер, который раз в 200 ms будет обновлять время до События
var el = document.getElementById("timer");
window.setInterval( function(){
var remains = Math.floor((deadline - (new Date).getTime())/1000);
var H = Math.floor( remains / 3600);
remains -= 3600 * H;
H = ( '0' + H ).substr(-2);
var M = Math.floor( remains / 60);
remains -= 60 * M;
M = ( '0' + M ).substr(-2);
var S = ( '0' + remains ).substr(-2);
timer.innerText = "" + H + ":" + M + ":" + S;
}, 200);
});
Такие запросы можно выполнять неоднократно, каждый раз уточняя таймер отсчёта на клиенте.