【问题标题】:strftime() and gmstrftime() return wrong results for "%s"strftime() 和 gmstrftime() 为 "%s" 返回错误结果
【发布时间】:2019-04-03 18:54:32
【问题描述】:

PHP 函数 strftime()gmstrftime() 返回(不同的)格式 "%s" 的错误结果。我使用 PHP 5.5.14 和 PHP 7.2.5 对它进行了测试,包括 CLI 和 Apache (OpenSuse)。我使用了带和不带 DST 的时间戳。

我的问题:你能确认其他版本/系统的错误吗?

测试脚本

<?PHP
header('Content-Type: text/plain; charset=utf-8');

$list = array(
    1546303600, // 2018-01-01 00:46:40 UTC
    1556703600, // 2019-05-01 09:40:00 UTC
);

echo "\ndate_default_timezone_set('UTC')\n";
date_default_timezone_set('UTC');

foreach ( $list as $time )
{
    printf("\n%u\n%4s\n%s\n",
        $time,
        strftime('%s, %F %T %Z',$time),
        gmstrftime('%s, %F %T %Z',$time) );
}

echo "\ndate_default_timezone_set('Europe/Berlin')\n";
date_default_timezone_set('Europe/Berlin');

foreach ( $list as $time )
{
    printf("\n%u\n%4s\n%s\n",
        $time,
        strftime('%s, %F %T %Z',$time),
        gmstrftime('%s, %F %T %Z',$time) );
}

?>

错误的结果

%s 应该返回原始时间戳,但它没有。结果相差 1 小时(3600 秒)。

date_default_timezone_set('UTC')

1546303600
1546300000, 2019-01-01 00:46:40 UTC <<< WRONG!
1546300000, 2019-01-01 00:46:40 GMT <<< WRONG!

1556703600
1556700000, 2019-05-01 09:40:00 UTC <<< WRONG!
1556700000, 2019-05-01 09:40:00 GMT <<< WRONG!

date_default_timezone_set('Europe/Berlin')

1546303600
1546303600, 2019-01-01 01:46:40 CET
1546300000, 2019-01-01 00:46:40 GMT <<< WRONG!

1556703600
1556703600, 2019-05-01 11:40:00 CEST
1556700000, 2019-05-01 09:40:00 GMT <<< WRONG!

我已经向 bugs.php.net 报告了这个错误:https://bugs.php.net/bug.php?id=77840

一些说明(编辑)

PHP 文档告诉:“%s 给出与time() 相同的结果”。这个结果与时区无关(自纪元以来的秒数)。所以strftime("%s",ANY_TIME) 必须返回ANY_TIMEgmstrftime() 也一样。

Unix 工具日期按预期工作:

date '+%s %F %T' -d@1556703600
date -u '+%s %F %T' -d@1556703600
TZ=UTC date '+%s %F %T' -d@1556703600

结果是:

1556703600 2019-05-01 11:40:00
1556703600 2019-05-01 09:40:00
1556703600 2019-05-01 09:40:00

所以这不是底层C函数的问题!

【问题讨论】:

  • 我怀疑这归结为 date_default_timezone_set 没有按您的预期工作,而不是与 strftime 有任何关系。
  • %s 必须始终提供独立于时区的时间戳。来自php.net/manual/en/function.strftime.php : "%s : Unix Epoch Time timestamp (same as the time() function)"
  • 一个有趣的旁注,%s 在 Windows 上的 strftimegmstrftime 中单独使用会导致根本没有输出,因此很难测试!

标签: php


【解决方案1】:

差异似乎取决于时区的设置方式。下面的测试将告诉你 strftime 认为无论使用 date_default_timezone_set 设置什么都存在 UTC 偏移量。

date_default_timezone_set("UTC");
echo strftime("%s %z", 1546303600);
date_default_timezone_set("America/Vancouver");
echo strftime("%s %z", 1546303600);

The code 似乎应用了从系统时区派生的偏移量,因此您可以尝试这样做:

putenv("TZ=UTC");
echo strftime("%s %z", 1546303600);

它应该可以工作。根据the documentation they've provided 的说法,这绝对是不正确的行为。

【讨论】:

  • php 文档说,%s 返回与time() 相同。这与时区无关(自纪元以来的秒数)。顺便说一句,命令行工具date 工作正常。
  • 我添加了一个 bash/date 示例来证明,这不是底层 C 函数的问题strftime()
  • 我明白你在说什么。至少绝对是一个文档问题。 %s 格式不是 Open Group specification 的一部分,因此没有关于它应该如何表现的官方消息。 Looking at the code,肯定存在与 PHP 文档所说的相矛盾的偏移量。
  • 奇怪的是,即使 gmstrftime() 应该在 UTC/GMT 下工作,它也会返回错误的结果。所以这不是文档错误,而是实现错误。
  • 关于提交错误报告的问题!
猜你喜欢
  • 2019-01-02
  • 1970-01-01
  • 2021-05-05
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多