phpdatetimeintldateformatter

php - IntlDateFormatter() wrong/weird timestamp in comparison to DateTime() output


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?


Solution

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