PHP IntlDateFormatter 错误的日期/时间转换

标签 php timezone php-7 date-formatting

我最近偶然发现了 PHP v7.0.4 的一个问题。当尝试格式化过去的一些日期时。

我从事一个项目,其中有一个叫做“空日期”的东西,基本上是“1800-01-01”(用来代替 NULL 值)。我使用的是 GMT+1,“欧洲/柏林”。

在处理它的过程中,由于涉及日期本地化,IntlDateFormatter 开始出现一些问题,我追查到如果日期 <= 1893-04-01(四月初的傻事?),就会出现异常。

您可以在下面看到一些有趣的示例。有人可以确认他们的系统上遇到了同样的问题吗?它应该可以重现:

$formatter = new \IntlDateFormatter('en_US', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::LONG);
echo $formatter->format(new \DateTime("1893-04-01 00:00:00")) . '<br />';
echo $formatter->format(new \DateTime("1893-04-02 00:00:00")) . '<br />';

应该返回:

"Mar 31, 1893, 11:53:28 PM GMT+0:53:28" and 
"Apr 2, 1893, 12:00:00 AM GMT+1"

或者对于更明显的行为“改变”:

echo $formatter->format(new \DateTime("1893-04-01 00:06:31")) . '<br />';
echo $formatter->format(new \DateTime("1893-04-01 00:06:32")) . '<br />';

应该返回:

"Mar 31, 1893, 11:59:59 PM GMT+0:53:28" and
"Apr 1, 1893, 12:06:32 AM GMT+1"

我认为这与时区的历史变化有关(类似于: https://github.com/eggert/tz/blob/2017b/asia#L891 ,尽管这是关于亚洲的,而且我使用的是 GMT+1)。

如果我们假设我实际上需要使用这个日期,01.01.1800 - 有人会看到解决这个“问题”的任何“正常”方法吗?

最佳答案

你是对的,它与 historical change of the timezone 有关。 。欧洲/柏林的 GMT 偏移量为 +0:53:28,直到 1893 年 4 月,它才会跳至完整的 +1。

因此它的第一个 GMT+1 是:

  • 1893 年 4 月 1 日凌晨 12:06:32 GMT+1

之前的第二个是:

  • 1893 年 3 月 31 日晚上 11:59:59 GMT+00:53:28。

基本上这意味着 1893 年 4 月 1 日 00:00:00 到 00:06:31 不存在。


避免围绕此类问题产生大量困惑的正常方法是仅在 UTC 中工作并处理仅用于显示的时区转换。例如:

date_default_timezone_set('UTC');

$formatter = new \IntlDateFormatter(
    'en_US',
    \IntlDateFormatter::MEDIUM,
    \IntlDateFormatter::LONG,
    'Europe/Berlin'
);
echo $formatter->format(new \DateTime("1800-01-01 00:00:00")) , "\n";
echo $formatter->format(new \DateTime("1893-03-31 23:06:31")) , "\n";
echo $formatter->format(new \DateTime("1893-03-31 23:06:32")) , "\n";
echo $formatter->format(new \DateTime("1893-04-01 00:00:00")) , "\n";

输出:

Jan 1, 1800, 12:53:28 AM GMT+0:53:28
Mar 31, 1893, 11:59:59 PM GMT+0:53:28
Apr 1, 1893, 12:06:32 AM GMT+1
Apr 1, 1893, 1:00:00 AM GMT+1

如果您愿意,也可以强制 IntlDateFormatter 使用 GMT+1 而不是您的时区:

$formatter = new \IntlDateFormatter(
    'en_US',
    \IntlDateFormatter::MEDIUM,
    \IntlDateFormatter::LONG,
    'GMT+01:00'
);

关于PHP IntlDateFormatter 错误的日期/时间转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45227012/

相关文章:

对 Coinbase Exchange 私有(private) API 的 PHP 身份验证

PHP foreach 遍历json数据

php - 使用php Auth0 mysql连接错误

python - 如何仅使用标准库将 UTC 日期时间转换为本地日期时间?

php - 这个 php/mysql 表达式(设置连接时区)是否足够安全?

mysql - 如何解决错误驱动程序: SQLSTATE[HY000] [2002] Connection timed out error in symfony 4 project deployed on amazon aws中发生异常

php - 在 phpmyadmin 中创建触发器

php - 当我们有各自地点的当前时间和时区时,两个城市/国家之间的时差

PHP fatal error : Class 'PHPUnit\Framework\TestCase' not found with PHPUnit 6 and PHP 7. 0

docker - 在 ubuntu 16.04 上安装 php7.4 - Dockerfile