【问题标题】:Leap in time in PHP's function time()PHP 函数 time() 中的时间飞跃
【发布时间】:2010-02-01 11:55:52
【问题描述】:

使用 PHP 的 time() 函数的时间戳,我用 date() 向用户显示当前时间。

格式:H:i => 13:57

但有时似乎有时间飞跃。当我访问该页面时,我的 Windows 时钟显示为 13:40。但我的网站说 14:XX。我已经不知道确切的时间了。

另一个示例:用户访问了“谁在线?”页面。 00:16。列出了一个用户,他最后一次操作的时间是 00:39。每次页面加载时,最后一次操作时间都会写入数据库。所以 time() 函数必须在 00:39 时返回 00:39,并且必须将错误的值写入数据库。

怎么会这样?

非常感谢您的帮助:)

编辑 #1 我已将代码缩减为对这个问题很重要的部分:

我在 serverData.php 中使用 $tStamp = time() 将时间戳保存到一个新变量中,并且该文件包含在 index.php 中,我在其中使用 date('d.m.Y, H:i', $t邮票)。变量 $tStamp 在任何其他行中都没有更改。

编辑 #2 我网站上的用户注意到 2010 年 1 月 21 日 00:16 的时间错误,页面在很短的时间内显示为 00:39。我查看了日志文件,大约在这个时候,日志文件中缺少一个完整的小时:

127.0.0.1 - - [2010 年 1 月 20 日:23:34:53 +0100] ...

127.0.0.1 - - [20/Jan/2010:23:34:55 +0100] ...

127.0.0.1 - - [21/Jan/2010:00:38:41 +0100] ...

127.0.0.1 - - [21/Jan/2010:00:38:41 +0100] ...

我的宿主宣布了 2010-01-20 00:00-06:00 的维护工作。你认为维护被推迟了吗?难不成是在这个时间段的第二天就进行了维护工作?这样的工作会不会弄错时间?

Edit #3 最后,我得到了房东的答复 :) 在给定的时间段内,服务器崩溃了。正因为如此,手表/时钟停止了。就这么简单,但我没想到服务器崩溃。非常感谢大家!

【问题讨论】:

    标签: php time timestamp


    【解决方案1】:

    在阅读了所有这些问题以及您在 cmets 中的回答后,我可以说这是 PHP 中的错误的可能性非常小。 PHP 的time() 直接从操作系统拉取,它直接从主板上的硬件时钟拉取。由于您使用的是共享主机,因此如果这种情况经常发生足以成为问题,您将不得不要求您的主机进行调查。它可能是一个流氓 NTP 服务器或进程,它可能是某种硬件时钟短——无法访问服务器日志或物理访问计算机,据我所知,您个人可以做的事情并不多。

    【讨论】:

    • 非常感谢!所以总结一切:这可能是由服务器而不是由 PHP 引起的,我需要访问服务器以找出原因。这是正确的吗?
    • 看起来确实如此,绝对如此。每当它再次发生时,彻底记录它,以便您的主机可以使用。
    • 谢谢,我会问我的主人。请参阅我的编辑#2。你怎么看?
    • 在飞跃时间前后的维护可能表明服务器的时间已经漂移,他们发现并纠正了(或至少尝试过)。该日志显示了 64 分钟的漂移,这将是非常不寻常的,但并非不可能。或者它可能是完全不同的东西——仅仅从这些有限的症状很难准确地判断出问题出在哪里,而且我每天管理很多服务器。
    【解决方案2】:

    作为一个非常遥远的选择,可能存在一个错误的 ntp 位置,它在检查时会暂时更改系统时间。下次更新到正确的服务器时,它将被设置回正确的时间。我认为系统时间不会漂移那么大。

    【讨论】:

    • 什么时候再更新?我的问题很少发生,总是只有几秒钟。那么它可能是坏的 ntp 位置吗?
    • 我会检查 crontab 文件和 ntp 服务器池。您是否有权访问服务器上的这些信息?
    • 您是否还可以创建一个记录当前时间的文件,以查看它漂移的频率以及漂移是否一致(即,恰好 4 分钟,并且每 5 小时发生一次)?这可能会让您更准确地了解这个问题。
    • 这就是我要开始的地方,是的。编辑二带来了另一种可能性——故障转移服务器。如果他们关闭了您现有的服务器进行维护,那么他们可能已将您切换到另一台服务器,而这台服务器的时间可能设置错误。 23 分钟的休息时间很奇怪。丢失日志文件的时间可能是因为正常服务器在该时间段内停机。您是否尝试过与您的托管公司交谈,并在支持链中提升几个级别以了解您当时被调到哪里?
    • 其实,我会对 cron 作业(甚至是一个 php 脚本)执行以下操作:每分钟,将当前时间写入数据库表(为了更有趣的结果,还有另一列mysql的时间戳)。然后,编写一个 foreach 来解析 db 以查看当前行在任一方向上与前一个值的距离是否大于或 2 分钟,然后仅回显这些结果。这将为您提供每个事件的开始和结束时间。一旦你有了这些信息(并且可以另外检查 mysql 服务器是否有相同的打嗝),你可以查看它是否一致,并与主机聊天。
    【解决方案3】:

    记住 time() 返回的 server 时间不是你的。如果它返回不同的值,则表示服务器时间与您的电脑时间不同。

    【讨论】:

    • 不!你误会了什么。时间跳到错误的值一段时间。几秒钟后,正确的时间再次显示。如果我的电脑时间和服务器时间匹配,它们应该在 5 分钟内仍然匹配,对吧? ;)
    • NTP 服务器(即时间)同步问题?例如,这是否发生在另一台机器上?
    • 我在共享主机上托管了这个项目。所以我只有这个网站空间,没有其他服务器。
    • "如果我的电脑时间和服务器时间匹配,他们应该在5分钟后仍然匹配,对吧?"......听起来很有趣,但根本无法保证。哎呀,即使是我厨房里的挂钟也会漂移,有时我会调整它。 NTP 服务器是一个很好的提示。
    • 不,时间并没有逐渐漂移,它只是跳过了一小段时间,然后又正确了。
    【解决方案4】:

    这可能是由于服务器设置为另一个时区而导致的缓存问题 - 对于示例来说,似乎最有可能提前一小时。

    Turn off the browser's cache,如果服务器有缓存(squid 等),也将其关闭,然后重试实验。

    要么是这样,要么服务器场有一个或两个节点的时间设置不正确。

    【讨论】:

    • 我认为这不是缓存问题。如果它是由缓存引起的,那么错误的时间就会追溯到过去。但就我而言,它可以追溯到未来,错误的时间是在未来。你不这么认为吗?
    • 检查服务器日志中的时间戳会很有趣。
    • 我在上述问题的编辑#2 中发布了一些服务器日志行。这有帮助吗?
    • 只有 4 个时间戳?你有什么与异常发生的时间相符的吗?
    • 发生异常时,日志文件中缺少某些内容。日志中未列出一个完整的小时。所以我贴了异常前后的两个时间戳。
    【解决方案5】:

    您可以在 php.ini 中或在运行时使用 date_default_timezone_set() 函数配置服务器的时区。

    【讨论】:

    • 我已经这样做了:date_default_timezone_set('Europe/Berlin')
    • 在将 time() 返回的值插入数据库之前,您是否以任何方式对其进行处理?
    • 是的,我在“编辑#1”之后的问题中添加了一些细节。这有帮助吗?
    【解决方案6】:

    您的代码中可能存在错误。如果可以,请粘贴一些代码。

    否则,您可以创建一些测试页面,在其中将问题简化为更简单的代码库并仅测试时间函数。这将有助于澄清和隔离任何潜在问题。你明白我的意思吗?

    【讨论】:

    • 谢谢!我在我的问题中的“编辑#1”之后添加了更多的代码细节。有帮助吗?
    【解决方案7】:

    我建议将脚本输出与 apache 日志进行比较,甚至更好 - 还创建一个日志,该日志将在请求时记下时间值。这是为了排除以下可能性:

    一些提供商有缓存网络,它们不会直接将内容从您传送到站点,而是缓存它,希望其他人也会请求相同的页面,然后他们可以节省外部带宽。因此,如果此网络出现故障,您可能会得到错误的页面版本。

    与 apache 日志或 syslog 比较将帮助您了解其他代码是否与您的代码具有相同的时间观念 - 这消除了它是代码问题的可能性,并可能将其从 php 领域带入服务器领域。如果是这样,我会仔细研究 ntp - 这是我知道的唯一一个应该与时间混淆的守护进程。

    【讨论】:

    • 您如何看待我在上述问题的编辑#2 中发布的服务器日志?这可能是原因吗?
    【解决方案8】:

    方法是通过 PHP 获取服务器的时间并注入客户端 javascript,将其转换为 GMT 时间并添加偏移量,从而将时间转换为您所在时区的时间。 See this for more info.

    【讨论】:

      【解决方案9】:

      服务器场上时间设置不正确的流氓节点肯定会这样做(正如@wallyk 所建议的那样)——这比这是一个 NTP 问题更合理。

      查看是否有任何方法可以识别您的请求由哪个节点提供服务。

      尝试在 HTML 注释中包含 php_uname() 或 gethostname(),并检查时间不正确的页面来源。这些可能提供足够的信息来确定问题是否与特定节点相关。

      或者创建一个页面,将函数调用的结果与当前 time() 一起打印,并编写一个脚本,多次获取该页面,直到观察到异常。 (显然你会小心避免页面被缓存,并首先向自己保证 php_uname() 或 gethostname() 提供了足够的信息来确定不同的请求是否由不同的节点处理)

      【讨论】:

      • gethostname() 对我不可用,因为我有 PHP 版本 5.2.12。但是 php__uname() 会返回以下字符串:Linux wp029 2.6.30.2-he-xeon-64gb+4 #1 SMP Sat Aug 15 15:25:21 CEST 2009 i686 这有帮助吗?
      猜你喜欢
      • 2012-12-10
      • 2017-02-05
      • 1970-01-01
      • 2011-10-09
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2010-10-04
      • 2022-12-10
      相关资源
      最近更新 更多