php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48097 date_timezone_set function produces wrong datetime result
Submitted: 2009-04-28 09:02 UTC Modified: 2009-05-03 14:37 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: energie at eox dot hu Assigned: derick
Status: Not a bug Package: Date/time related
PHP Version: 5.2.9 OS: *
Private report: No CVE-ID:
 [2009-04-28 09:02 UTC] energie at eox dot hu
Description:
------------
Result of "date_create" with timezon given:
"Mon, 23 May 1955 00:00:00 +0200"
After calling "date_timezone_set" for this date the expected result would be the same but instead the result is:
"Mon, 23 May 1955 01:00:00 +0200"

In case of "Europe/Budapest" timezone 3 dates are affected between 1900.01.01 and 1999.12.31:
[0] => Sun, 23 May 1954 00:00:00 +0200
[0] => Mon, 23 May 1955 00:00:00 +0200
[0] => Sun, 03 Jun 1956 00:00:00 +0200

There are timezones where everything works fine, and many ohters that have date inputs that cause this mis-calculation. Thers is no relation between the dates in different timezones but the wrong dates are always the same in a given timezone, so there are no "random" errors.

Reproduce code:
---------------
$errors = array();
$timezones = array('Europe/Budapest');
// Uncomment the following line to run on all timezones
// $timezones = timezone_identifiers_list();

function generate_dates($timezone) {
  $dates = array();
  for($y = 1900; $y <= 1999; $y++) {
    for($m = 1; $m <= 12; $m++) {
      for($d = 1; $d <= 31; $d++) {
        $date = date_create(sprintf('%s-%s-%s 00:00:00', $y, $m, $d), timezone_open($timezone));
        if ($date) {
          $dates[] = $date;
        }
      }
    }
  }
  return $dates;
}

foreach($timezones as $timezone) {
  $dates = generate_dates($timezone);
  foreach($dates as $date) {
    $test = date_format($date, 'r');
    date_timezone_set($date, timezone_open($timezone));
    if ($test != date_format($date, 'r')) {
      $errors[$timezone][] = array($test, date_format($date, 'r'));
    }
  }
  print('Timezone: '. $timezone . ', errors: '. count($errors[$timezone]) . "\n");
  // Uncomment the following line to display all dates that calculated "wrong"
  // print_r($errors[$timezone]);
  // print "\n";
}

Expected result:
----------------
Timezone: Europe/Budapest, errors: 0

Actual result:
--------------
Timezone: Europe/Budapest, errors: 3

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-05-03 14:37 UTC] derick@php.net
This is not a bug, the following happens:

date_create() creates a timezone agnostic date (only with a UTC offset). Once you set the timezone to Europe/Budapest, it uses the Unix timestamp contained in the DateTIme object (-461124000) and converts that to a date/time representation for the Europe/Budapest timezone. However, at this timestamp (1955-05-22T22:00:00 UTC) the UTC offset in Budapest is only +1 (as it only becomes +2 an hour later at 1955-05-22T23:00:00 UTC). Because the UTC-offset is only 1, and not 2, the correct offset is indeed UTC+1 which makes the time "23:00:00" in Budapest.

The differences that you are seeing for those 3 years is because in those 3 years, the DST switch from UTC+1 to UTC+2 makes 00:00:00 not exist for those days, as the time goes from 23:59:59 directly to 01:00:00. 
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sat Apr 19 12:01:52 2014 UTC