0

I noticed that IntlDateFormatter() function returns wrong timestamp in comparison to same type of output from DateTime() function.

PHP:

    $formatter = new IntlDateFormatter(
        'en_GB', 
        IntlDateFormatter::SHORT, 
        IntlDateFormatter::SHORT, 
        'Europe/London', 
        IntlDateFormatter::GREGORIAN,
        'dd MMMM YYYY, HH:mm'
    );

    $now = new DateTime('01-03-2023 17:00');                        
    echo '<b>DateTime() String:</b> ' . $now->format('d F Y, H:i') . '<br/>';
    echo '<b>IntlDateFormatter() String:</b> ' . $formatter->format( $now ) . '<br/><br/>';
    echo '<b>DateTime() Timestamp:</b> ' . $now->getTimestamp() . '<br/>';
    echo '<b>IntlDateFormatter() Timestamp:</b> ' . $formatter->parse( $formatter->format( $now ) );

OUTPUT:

DateTime() String: 01 March 2023, 17:00

IntlDateFormatter() String: 01 March 2023, 17:00

DateTime() Timestamp: 1677690000

IntlDateFormatter() Timestamp: 1672074000

As is visible above, IntlDateFormatter() returns good string, but a bad timestamp value from the same source. Why is that happen?

X9DESIGN
  • 774
  • 1
  • 10
  • 23
  • Worth noting that `1672074000` is `Monday, December 26, 2022 5:00:00 PM`, a full 65 _days_ off what it should be. – Sammitch Mar 04 '23 at 00:01
  • 1
    The format YYYY does not exist in the ICU documentation https://unicode-org.github.io/icu/userguide/format_parse/datetime/. There are only y, yy, yyyy and Y. This fact combined with a misinterpretation of YYYY by the IntlDateFormatter produces the wrong timestamp. – jspit Mar 05 '23 at 15:12
  • @jspit It was not obvious for me that using of that format will not output error message. – X9DESIGN Mar 06 '23 at 00:03

1 Answers1

1

When call $formatter->parse($formatter->format($now)), the parse method is interpreting the week year value as the year value, resulting in a different timestamp value than the DateTime object's timestamp.

To get consistent output, you can use lowercase yyyy instead of uppercase YYYY in IntlDateFormatter.

$formatter = new IntlDateFormatter(
    'en_GB', 
    IntlDateFormatter::SHORT, 
    IntlDateFormatter::SHORT, 
    'Europe/London', 
    IntlDateFormatter::GREGORIAN,
    'dd MMMM yyyy, HH:mm'
);

$now = new DateTime('01-03-2023 17:00', new DateTimeZone('Europe/London'));

echo '<b>DateTime() String:</b> ' . $now->format('d F Y, H:i') . '<br/>';
echo '<b>IntlDateFormatter() String:</b> ' . $formatter->format( $now ) . '<br/><br/>';

echo '<b>DateTime() Timestamp:</b> ' . $now->getTimestamp() . '<br/>';
echo '<b>IntlDateFormatter() Timestamp:</b> ' . $formatter->parse( $formatter->format( $now ) ) . '<br/><br/>';

echo '<b>Default Timezone:</b> ' . date_default_timezone_get() . '<br/>';
echo '<b>DateTime() Timezone:</b> ' . $now->getTimezone()->getName() . '<br/>';
echo '<b>IntlDateFormatter() Timezone:</b> ' . $formatter->getTimeZone()->getID() . '<br/>';
iamafish
  • 817
  • 3
  • 13
  • 24
  • Sorry my bad. I just updated – iamafish Mar 04 '23 at 00:27
  • 2
    You also should explicitly note that you changed the format string from `YYYY` to `yyyy` which is a very significant part of the issue. Eg: Link the [format reference](https://unicode-org.github.io/icu/userguide/format_parse/datetime/#parsing-dates) and note the difference between `Y` "year of 'week of year'" and `y` which is the actual calendar year. – Sammitch Mar 04 '23 at 00:31
  • Thank You for helping me. I would never discover what you did explain. I was sure there should be some error in case of wrong format of year. When was not, I simply had emptiness in my mind and could't figure out by checking any options what is wrong. – X9DESIGN Mar 06 '23 at 00:12