【问题标题】:Javascript and PHP Clock that Matches the Server Time与服务器时间匹配的 Javascript 和 PHP 时钟
【发布时间】:2021-06-01 13:56:57
【问题描述】:

我有一个显示实时数字时钟的 JS 代码,从服务器纠正分钟/秒,所以如果其中一个客户端或多或少有几分钟,它会纠正它们以匹配服务器时间。

<script>
    
    var serverTime = <?php echo (int) round(microtime(true) * 1000) ?>;
    var localTime = +Date.now();
    var timeDiff = serverTime - localTime;

    $(document).ready(function() {
        clockUpdate();
        setInterval(clockUpdate, 1000);
    });

    function clockUpdate() {

        var t = +Date.now() + timeDiff
        var date = new Date(t);

        $('.digital-clock').css({'color': '#fff', 'text-shadow': '0 0 0px #ff0'});
        function addZero(x) {
            if (x < 10) {
                return x = '0' + x;
            } else {
                return x;
            }
        }

        function twelveHour(x) {
            if (x > 12) {
                return x = x - 12;
            } else if (x == 0) {
                return x = 12;
            } else {
                return x;
            }
        }

        var h = addZero(twelveHour(date.getHours()));
        var m = addZero(date.getMinutes());
        var s = addZero(date.getSeconds());

        $('.digital-clock').text(h + ':' + m + ':' + s)
    }

</script>

现在脚本按预期工作,但我意识到当其中一个客户端设置为不同的时区时,时钟将与客户端上的小时匹配,

如果现在服务器上是 14:52 而客户端上是 15:52,它将显示 15:52 而我想要相反,我希望所有客户端上显示的所有时钟都与服务器上的确切时间匹配(14:52)。

请帮我修改这段代码中的东西,不需要其他在线示例。

/**********************/

感谢所有认真对待并试图提供帮助的人(不像那些准备在我问问题的那一刻就投票结束问题的人)

我想多解释一下:

服务器位于法国,使用 GMT+1 和 DST

客户在突尼斯,同一时区 GMT+1,但 DST 不适用。但出于某种原因,突尼斯的许多客户可能不知道使用 DST。

这就是为什么页面上的时间必须与服务器和其他任何地方的时间完全相同。

所以对于 PHP,我使用 date_default_timezone_set('Africa/Tunis'); 将服务器时间设置为突尼斯时区。

谢谢!

【问题讨论】:

  • 请分享更多细节。您尝试过什么来解决问题?你被困在哪里了?这和 PHP 有什么关系?
  • +Date.now() 中的一元“+”是多余的,因为 now 被指定为返回一个数字。 return x = x - 12中的赋值也是多余的,应该只是return x - 12,但是整个twelveHour函数体可以是return x%12 || 12

标签: javascript php datetime


【解决方案1】:

好的,感谢所有试图提供帮助的人,我通过 Reinhard Schnetzinger 的回答解决了这个问题:

getUTCHours();
getUTCMinutes();
getUTCSeconds();

所以我使用的代码是:

var h = addZero(twelveHour(date.getUTCHours() + 1));
var m = addZero(date.getUTCMinutes());
var s = addZero(date.getUTCSeconds());

使用getUTCHours() + 1 作为所需时间是GMT+1

【讨论】:

    【解决方案2】:

    它错误地输出时间,因为您使用的方法根据客户端的本地时区(getHours()getMinutes()getSeconds())返回时间。 您应该改用以下方法:

    getUTCHours();
    getUTCMinutes();
    getUTCSeconds();
    

    编辑

    因为不清楚为什么我认为这可能会解决问题,所以这里稍微解释一下。

    在 PHP 中使用microtime() 函数设置服务器时间,使用Data.now() 设置客户端时间。两者都返回 UNIX 时间戳,并且根据定义它们与时区无关,as described here

    因此,JavaScript中的时间必须以UTC格式输出,否则客户端显示的时间可能与服务器实际时间不同。


    但是假设服务器时间将包括时区偏移量(例如时间戳中的额外一小时)。它仍然需要以 UTC 格式输出时间,因为 JavaScript 中的时间是用new Date(epochTimestamp) 设置的。此构造函数正确解释了 UNIX 时间戳as UTC,并且根本不关心时区(即使存在时区偏移;就像下面的 fakeOffset 示例)。

    const timeInUtc = document.getElementById('time-in-utc');
    const timeInLt = document.getElementById('time-in-lt');
    const fakeOffset = 3600000; // emulate one extra hour on the server; UTC + 1h
    const serverTime = Date.now() + fakeOffset; // for demonstration purposes microtime() is replaced with Date.now()
    const clientTime = Date.now();
    const timeDiff = serverTime - clientTime;
    
    setInterval(() => {
      const currentTimestamp = Date.now() + timeDiff;
      const currentTime = new Date(currentTimestamp);
      timeInUtc.innerHTML = `${currentTime.getUTCHours()}:${currentTime.getUTCMinutes()}:${currentTime.getUTCSeconds()}`;
      timeInLt.innerHTML = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}`;
    }, 500)
    Actual Server Time (output in UTC): <span id="time-in-utc">Unset</span><br>
    Server Time (output in Local Time): <span id="time-in-lt">Unset</span>
    
    <p>Keep in mind that the times may match if your time zone is the same as UTC time.</p>

    编辑#2

    正如@medk 解释的那样,服务器的时区确实与客户端的不同。我的建议是提供已包含偏移量的服务器时间戳,以便 JavaScript 代码始终显示正确的服务器时间,而无需手动更改输出(例如避免getUTCHours() + 1)。

    在 PHP 中,可以使用函数date_offset_get(new DateTime) 获得感知偏移量。这将以秒为单位返回偏移量。现在我们有了偏移量(例如 1h)、UNIX 时间戳(UTC),如果我们将这两者相加,我们就得到了正确的服务器时间戳(UTC+1)。

    var serverTime = <?php echo (int) round((microtime(true) + date_offset_get(new DateTime)) * 1000); ?>;
    

    因此,无论您在服务器上设置什么时区,或者 DST 是否处于活动状态,客户端上的时间都应始终与服务器时间匹配。

    【讨论】:

    • 您为什么认为这可以解决问题?服务器不一定是 UTC。
    • 因为 PHP 中的 microtime 和 JS 中的 Date.now() 都为我们提供了自 1970 年以来的过去时间,没有任何时区对话。所以他在 JS 中设置的日期是 UTC。但是,当他使用getHours() 时,时间会发生变化,因为这些方法会自动转换为客户端时间。
    • 即使服务器时间包含时区偏移量,也没有关系,因为他正确计算了服务器和客户端之间的时间差。然后他将新创建的时间设置为 UTC (new Date(t))。所以服务器的时区会出现在 JS 中,但它只是“存储”为 UTC。
    • 如果你愿意看一下,我编辑了我的问题。
    • 是的,谢谢,我编辑了关于您的新详细信息的答案 :)
    猜你喜欢
    • 2011-05-15
    • 2015-08-15
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多