php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79863 Timezone conversion result depends on environment
Submitted: 2020-07-15 09:01 UTC Modified: 2020-07-25 20:31 UTC
From: bassjoe at web dot de Assigned:
Status: Open Package: Date/time related
PHP Version: 7.4.8 OS: CentOS Linux 7
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: bassjoe at web dot de
New email:
PHP Version: OS:

 

 [2020-07-15 09:01 UTC] bassjoe at web dot de
Description:
------------
WordPress uses (in wp-includes/formatting.php) the following PHP function calls to convert Date/Time objects to a different timezone (simplified):

    function get_gmt_from_date( $string ) {
        $datetime = date_create( $string, wp_timezone() );
        return $datetime->setTimezone( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' );
    }

This fails on my Strato/CentOS7 Server (PHP 7.4.8) because get_gmt_from_date() returns the same value that is given as $string argument.  I can easily reproduce this with the following command on the console:

    php -r '$datetime = date_create("2020-07-13 10:38:15", new DateTimeZone("Europe/Berlin"));  echo $datetime->setTimezone( new DateTimeZone( "UTC" ) )->format( "Y-m-d H:i:s\n" );'
    
    2020-07-13 10:38:15

On my Fedora 31 workstation (also PHP 7.4.8) the same command returns the correct result:

    2020-07-13 08:38:15

I installed CentOS 7 on a VM but could not reproduce the error.  This means the result of these PHP functions depends on the server configuration.

The result of a timezone conversion obviously should not depend on the environment.

The effect I have noticed in WordPress is that changes in the Customizer can't be published immediately.

Test script:
---------------
php -r '$datetime = date_create("2020-07-13 10:38:15", new DateTimeZone("Europe/Berlin"));  echo $datetime->setTimezone( new DateTimeZone( "UTC" ) )->format( "Y-m-d H:i:s\n" );'

Expected result:
----------------
2020-07-13 08:38:15

Actual result:
--------------
2020-07-13 10:38:15

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-07-15 09:10 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2020-07-15 09:10 UTC] requinix@php.net
What is the value being returned by wp_timezone()?
 [2020-07-15 09:17 UTC] bassjoe at web dot de
-Status: Feedback +Status: Open
 [2020-07-15 09:17 UTC] bassjoe at web dot de
"Europe/Berlin"
 [2020-07-15 09:22 UTC] bassjoe at web dot de
wp_timezone()->getName() is what I logged and it was "Europe/Berlin"
 [2020-07-17 13:37 UTC] antonino dot spampinato86 at gmail dot com
<?php
$datetime = date_create("2020-07-13 10:38:15", timezone_open("Europe/Berlin")); date_timezone_set( $datetime, timezone_open( "UTC" ) ); date_format( $datetime, "Y-m-d H:i:s" ); var_dump($datetime);

Expected result:
----------------
object(DateTime)#5 (3) {
  ["date"]=>
  string(26) "2020-07-13 08:38:15.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
timezone now is UTC?
 [2020-07-17 19:21 UTC] bassjoe at web dot de
The result is the same with this command sequence.

Workstation (correct):

    $ php -r '$datetime = date_create("2020-07-13 10:38:15", timezone_open("Europe/Berlin")); date_timezone_set( $datetime, timezone_open( "UTC" ) ); date_format( $datetime, "Y-m-d H:i:s" ); var_dump($datetime);'
    Command line code:1:
    class DateTime#2 (3) {
      public $date =>
      string(26) "2020-07-13 08:38:15.000000"
      public $timezone_type =>
      int(3)
      public $timezone =>
      string(3) "UTC"
    }

Server (wrong):

    $ php -r '$datetime = date_create("2020-07-13 10:38:15", timezone_open("Europe/Berlin")); date_timezone_set( $datetime, timezone_open( "UTC" ) ); date_format( $datetime, "Y-m-d H:i:s" ); var_dump($datetime);'
    object(DateTime)#2 (3) {
      ["date"]=>
      string(26) "2020-07-13 10:38:15.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(3) "UTC"
    }
 [2020-07-25 20:31 UTC] bassjoe at web dot de
Now this is very strange.  I get the correct result if I check out PHP 7.4.8 (same version as the REMI packages) from Git, compile it on CentOS 7, and run this php executable on the server. So in the same environment and while ignoring php.ini (with -n) I get different results for the same version.

# installed from remi repo:
# php-cli-7.4.8-2.el7.remi.x86_64
# php-7.4.8-2.el7.remi.x86_64

$ php --version
PHP 7.4.8 (cli) (built: Jul  9 2020 08:57:23) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies


$ php -n -r '$datetime = date_create("2020-07-13 10:38:15", new DateTimeZone("Europe/Berlin")); var_dump($datetime); $datetime->setTimezone( new DateTimeZone( "UTC" ) ); var_dump($datetime);'

object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2020-07-13 10:38:15.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Berlin"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2020-07-13 10:38:15.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}


# self-compiled on centos 7 => correct result

$ sapi/cli/php --version
PHP 7.4.8 (cli) (built: Jul 25 2020 22:12:24) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies


$ sapi/cli/php -n -r '$datetime = date_create("2020-07-13 10:38:15", new DateTimeZone("Europe/Berlin")); var_dump($datetime); $datetime->setTimezone( new DateTimeZone( "UTC" ) ); var_dump($datetime);'

object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2020-07-13 10:38:15.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Berlin"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2020-07-13 08:38:15.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
 [2020-12-04 13:46 UTC] smeyer dot ilias at gmx dot de
I observed a similar issue with PHP 7.2.5 on SLES 12 SP 5: 

<?php

date_default_timezone_set('UTC');
echo date('Y-m-d: H:i:s e');
date_default_timezone_set('Europe/Berlin');
echo date('Y-m-d: H:i:s e');
date_default_timezone_set('Asia/Irkutsk');
echo date('Y-m-d: H:i:s e');

Returns: 
2020-12-04: 12:43:34 UTC
2020-12-04: 12:43:34 Europe/Berlin
2020-12-04: 12:43:34 Asia/Irkutsk

Changes in /etc/php/cli/php.ini date.timezone did not make difference. 
I have no direct access to the server, but could provide more information regarding the server environment.
 [2021-01-09 23:10 UTC] antonino dot spampinato86 at gmail dot com
From php 5.4+ it retrieves the time zone if set via date_default_timezone_get or from the php.ini date.timezone setting or set to UTC if absent date.timezone and date_default_timezone_get. From php 7 if date.timezone is not set it does not show warning. for more information read here https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone

https://3v4l.org/0enPY
I don't think it's a php bug but maybe it doesn't do that php expects and therefore it's an error even with date_default_timezone_get https://www.php.net/manual/en/function.date-default-timezone-get.php#113202

Note* WordPress set date_default_timezone_set("UTC"); https://github.com/WordPress/WordPress/blob/5.6-branch/wp-settings.php#L68
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Sat Jan 16 15:01:23 2021 UTC