问题
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