JavaScript — таймер с коррекцией по серверному времени

Одна из проблем административных систем (например, баз данных) - различие времени на клиентском компьютере и времени на сервере. Решить эту проблему почти невозможно, так как NTP протокол для HTTP сессии нереализуем из-за непредсказуемых задержек, а время генерации страницы не представляет интереса из-за AJAX запросов отображения данных. Но что-то можно получить имитацией NTP.

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

#!perl
sub ntp {
  my $c = shift;
  $c->render(inline=> int(Time::HiRes::time() * 1000));
}

#!javascript
<!-- 
# #############################################################################
#
#                             Дата и время
#
# #############################################################################
 -->

<script type="text/javascript">

function ntp_formatDate(date) {

  var dd = date.getUTCDate();
  if ( dd < 10 ) dd = '0' + dd;

  var mm = date.getUTCMonth()+1;
  if ( mm < 10 ) mm = '0' + mm;

  var yy = date.getUTCFullYear() ;

  var hh = date.getUTCHours();
  if ( hh < 10 ) hh = '0' + hh;

  var mi = date.getUTCMinutes();
  if ( mi < 10 ) mi = '0' + mi;

  var ss = date.getUTCSeconds();
  if ( ss < 10 ) ss = '0' + ss;

  return yy+'-'+mm+'-'+dd + ' ' + hh + ':' + mi + ':' + ss;
}



function ntp(t0, t1, t2, t3) {
    return {
        roundtripdelay: (t3 - t0) - (t2 - t1),
        offset: ((t1 - t0) + (t2 - t3)) / 2
    };
}

var ntp_corrected=false; // true после корректировки в ntp_get_offset
var ntp_c={offset:0};

// процесс отображения скорректированного времени
var timer = setTimeout(function  ntp_show_time(){
    var t3 = (new Date()).valueOf();
    $('#ntp').html(
      ((ntp_corrected)? '<b>':'' ) + ntp_formatDate(new Date(t3 + ntp_c.offset))+' UTC' + ((ntp_corrected)? '</b>':'' )
      );
    ntp_corrected=false;
    //console.log("NTP delay:", ntp_c.roundtripdelay, "NTP offset:", ntp_c.offset, "corrected: ", (new Date(t3 + ntp_c.offset)), 'UTC:', ntp_formatDate(new Date(t3 + ntp_c.offset))); 
    timer = setTimeout(ntp_show_time, 1000);
}, 1000);


var timer = setTimeout(function  ntp_get_offset(){

  var t0 = (new Date()).valueOf();
    $.ajax({
      url: '/cgi-bin/ntp',
      success: function(servertime, text, resp) {
          var t1 = servertime,
              t2 = servertime,
              t3 = (new Date()).valueOf();
          ntp_c = ntp(t0, t1, t2, t3);
          /* console.log("NTP delay:", ntp_c.roundtripdelay, "NTP offset:", ntp_c.offset, "corrected: ", (new Date(t3 + ntp_c.offset))); */
          ntp_corrected=true;
          timer = setTimeout(ntp_get_offset, 60*1000);
      }
    });
}, 5000);


</script>

<li  class="dropdown">

    <a class="dropdown-toggle" data-toggle="dropdown" data-target="#" id="ntp">2014-12-25 14:16:36</a>
</li>

Leave a Reply