PHP IntlDateFormatter wrong date/time conversion

女生的网名这么多〃 提交于 2019-12-12 19:38:47

问题


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

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

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 />';

Which should return:

"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 />';

which should return:

"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).

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


回答1:


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.

Thus its very first GMT+1 was:

  • Apr 1, 1893, 12:06:32 AM GMT+1

as the second before that was:

  • Mar 31, 1893, 11:59:59 PM GMT+00:53:28.

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


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

Outputs:

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

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'
);


来源:https://stackoverflow.com/questions/45227012/php-intldateformatter-wrong-date-time-conversion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!