php / php-src

The PHP Interpreter
https://www.php.net
Other
38.08k stars 7.74k forks source link

DateTime modify function not respect Time Zone #14661

Open piotrek-lifeinmobile opened 3 months ago

piotrek-lifeinmobile commented 3 months ago

Description

The following code:

<?php
var_dump((new DateTime())->modify("2024-06-21T13:03:20-04:00"));

Resulted in this output(php >=8.2.5; >=8.3.0):

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2024-06-21 13:03:20.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}

But I expected this output instead(this works on php 8.2.4, 8.2.3, 8.2.2):

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2024-06-21 13:03:20.000000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "-04:00"
}

PHP Version

=8.2.5; >=8.3.0;

Operating System

Any Linux or Windows

damianwadley commented 3 months ago

Agreed that modification of the date/time portion is incorrect, however IMO it shouldn't have the side effect of also changing the timezone. The one specified in the string should determine how to interpret its own date and time, but the DateTime instance's own timezone should be preserved. The reasoning being that the date/time and the timezone are managed separately in the object - as seen in the var_dump output. After all, if you wanted to use that whole string as the new value then why not just make yourself a brand-new DateTime object instead?

In other words,

$dt = new DateTime("2024-06-21T12:00:00+00:00");
var_dump($dt);
$dt->modify("2024-06-22T12:00:00+01:00");
var_dump($dt);

should output 06-21 12:00 +00 and then 06-22 11:00 +00. https://3v4l.org/KnTnu

piotrek-lifeinmobile commented 3 months ago

If all php versions would work this way, it won't be a problem. But if someone has php 8.2.4 and use Carbon library createFromTimeString function (which internally use modify function) this way:

<?php
$date = "2024-06-22T23:00:00-04:00";
$dateObject = Carbon::createFromTimeString($date);

It will work on php 8.2.4, but when changes were deployed to server with php 8.2.5, this will be problematic :-)

I agree we should use brand new DateTime object :

<?php

$date = "2024-06-22T23:00:00-04:00";
$dateObject = new DateTime($date);
// OR better
$dateObject = DateTime::createFromFormat(DateTimeInterface::ATOM, $date);
var_dump($dateObject );

Output:

object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2024-06-22 23:00:00.000000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "-04:00"
}
hormus commented 3 months ago

Currently DateTime::modify sets UTC for syntax @ unixtimestamp from PHP 8.1.15 > and later PHP 8.2.2 > and later.

Later... Other fix (PHP 8.2.5) modify('+1 s') https://github.com/php/php-src/issues/9891#issuecomment-1481025337