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 (profile)
Status: Not a bug Package: Date/time related
PHP Version: 5.2.9 OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: energie at eox dot hu
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Mon Feb 03 06:01:30 2025 UTC