PHP IntlDateFormatter错误的日期/时间转换 [英] PHP IntlDateFormatter wrong date/time conversion

查看:96
本文介绍了PHP IntlDateFormatter错误的日期/时间转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I recently stumbled on a problem with PHP v7.0.4. when trying to format some dates in the past.

我在一个项目中工作,其中有一个叫做空日期"的东西,基本上是"1800-01-01"(用于代替NULL值).我正在使用GMT + 1,欧洲/柏林".

I work on a project, in which there is a thing called "empty date", basically a "1800-01-01" (used instead of the NULL value). I'm using GMT+1, "Europe/Berlin".

在处理它的过程中,并涉及到日期的本地化,IntlDateFormatter开始产生一些问题,如果日期是< = 1893-04-01(4月初的愚人节?),我就追究它们的例外.

In process of handling it, and with the Date localization involved, the IntlDateFormatter started making some issues and I chased them down to having exceptions if the dates are <= 1893-04-01 (an early April fool thing?).

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

You can see some interesting examples below. Could someone please confirm that they get the same issue on their system? It should be reproducible with:

$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"

或者对于更明显的行为更改":

Or for even more visible behavior "change":

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"

我认为这与时区的历史变化有关(如下所示:

I presume it has something to do with historical changes of the timezones (something like this: https://github.com/eggert/tz/blob/2017b/asia#L891, although that is about Asia, and I'm using the GMT+1).

如果我们假设我实际上需要使用这个日期,即01.01.1800-有人会看到围绕这个问题"的任何正常"方式吗?

If we assume that I would actually need to use this date, 01.01.1800 - would anyone see any "normal" way around this "problem"?

推荐答案

您是正确的,它与

You're correct, it has to do with a historical change of the timezone. The GMT offset for Europe/Berlin is +0:53:28 until April of 1893 when it jumps to a full +1.

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

Thus its very first GMT+1 was:

  • 1893年4月1日,格林尼治标准时间+1

在此之前的第二个是:

  • 1893年3月31日,格林尼治标准时间+00:53:28.

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

Basically this means that Apr 1 1893 00:00:00 through 00:06:31 didn't exist.

避免这种混乱的正常方法是仅在UTC中工作,并处理时区转换(仅用于显示).例如:

The normal way of avoiding a lot of confusion around this sorta thing is to work only in UTC and deal with timezone conversions just for display. For example:

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而不是您的时区:


If you'd rather you can also force IntlDateFormatter to use GMT+1 instead of your timezone:

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

这篇关于PHP IntlDateFormatter错误的日期/时间转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆