Javascript倒计时器 - 客户端时间与mySQL时间

chr*_*rth 3 javascript mysql

以下代码是倒数计时器.它从mySQL中提取结束日期时间戳并使用它来计算.问题是mysql时间可能与使用计时器查看页面的客户端位于不同的时区.

我还使用NOW()从mySQL中提取当前时间戳,认为这将允许计时器计算为创建它的用户.

如果我把NOW()值放在这个片段中

var timeDiff = target - (new Date()); 
Run Code Online (Sandbox Code Playgroud)

像这样

var nt='2015-03-11 05:12:15'.split(/[- :]/);
var timeDiff = target - (new Date(nt[0],nt[1]-1,nt[2],nt[3],nt[4],nt[5]));
Run Code Online (Sandbox Code Playgroud)

计数器显示页面加载时剩余的正确时间,但不再以交互方式计数.我想我需要在客户端本地时间和mySQL NOW()之间获得数小时的差异,并调整此行中的日期以使交互式计时器运行.

var timeDiff = target - (new Date());  
Run Code Online (Sandbox Code Playgroud)

我尝试的任何东西似乎都有用.

如果客户端碰巧在同一时区内,则这是工作脚本.

 <script language="javaScript">              
  document.write(hrs);
  function timeDiff(target) {
    function z(n) {return (n<10? '0' : '') + n;}
    var timeDiff = target - (new Date()); 
    var hours    = timeDiff / 3.6e6 | 0;
    var minutes  = timeDiff % 3.6e6 / 6e4 | 0;
    var seconds  = timeDiff % 6e4 / 1e3 | 0;
    if (hours<0 || minutes<0 || seconds<0) {
      document.getElementById('divBody').style.display='none';
      document.getElementById('divExpired').style.display='';    
      return '<b>EXPIRED</b>';
      }
    else {
      return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b>  Mins, <b>' + z(seconds) + '</b> Secs';
      }
    }
  function doCountDown(target) {
    document.getElementById('timer').innerHTML = '<img src=\"/backhaul/images/my/al-active.png\" class=\"vm2\" /> <span style=\"color:#c40000\"><b>EXPIRES IN</b></span>: ' + timeDiff(target);
    var lag = 1020 - (new Date() % 100);
    setTimeout(function(){doCountDown(target);}, lag);
    }
  window.onload = function() {
    //Insert Expiratin Date from mySQL into t var
    var t='2015-03-12 00:00:00'.split(/[- :]/);
    doCountDown(new Date(t[0],t[1]-1,t[2],t[3],t[4],t[5]));
  }
</script>
Run Code Online (Sandbox Code Playgroud)

mfi*_*aus 6

有很多方法可以做到这一点,但我会详细说明两种方法.

方法1:调整客户端的时间

一种方法是你要做的是获取服务器的当前时间并找出与客户端当前时间的差异.您只需将服务器目标时间调整为客户端的时间即可.这可以通过以下方式完成

var serverDifference=Date.parse(mysql_data.now)-Date.now()
var target=Date.parse(mysql_data.server_time_in_two_hours)-serverDifference
Run Code Online (Sandbox Code Playgroud)

然后你可以毫无问题地将它输入你的功能.

方法2:计算剩余的时间,服务器端

由于你只需要一个倒数计时器,我认为简单地发送秒左服务器端更合适.这可以使用SQL来完成

 select timestampdiff(SECOND,now(),end_time) seconds_left from timers;
Run Code Online (Sandbox Code Playgroud)

然后你只需制作一个计时器,根据剩余的秒数而不是目标日期倒计时.您可以通过从服务器收到的时间中扣除javascript运行的时间来计算剩余的秒数.所以像

var client_start=Date.now()
function timeDiff_fromseconds(target) {
    function z(n) {return (n<10? '0' : '') + n;}
    var timeDiff =target-(Date.now()-client_start)
    var hours    = timeDiff / 3.6e6 | 0;
    var minutes  = timeDiff % 3.6e6 / 6e4 | 0;
    var seconds  = timeDiff % 6e4 / 1e3 | 0;
    if (hours<0 || minutes<0 || seconds<0) {   
      return '<b>EXPIRED</b>';
      }
    else {
      return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b>  Mins, <b>' + z(seconds) + '</b> Secs';
      }
}
Run Code Online (Sandbox Code Playgroud)

还有@dandavis的performance.now()建议.这将返回自打开选项卡以来的毫秒数,精确到1/1000毫秒.即使客户端浏览器的系统时钟发生变化,这也不会改变.要获得完全支持,您应该使用polyfill(截至撰写本文时,iOS Safari不支持它).在这种情况下,我们可以替换它.Date.now()

JSFiddle演示:

http://jsfiddle.net/3o3u5r5j/1/

  • 我不认为你需要#1的缺点.即使时钟完全关闭,两者仍然每秒提前1次,滞后很少超过1000ms.没有什么可以说你不能简单地计算第一个代码所需的秒数,然后将其提供给你的第二个代码. (2认同)
  • 可能值得一提的是,performance.now()更精确,忽略了打开选项卡后进行的本地时钟调整. (2认同)