简体   繁体   中英

Why is DateTime altering timezone in PHP?

$datetime = new DateTime( gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC') );
$past_time = $datetime->createFromFormat( 'Y-m-d H:i:s', $past_time )->getTimestamp();
echo 'Past formed: ' . gmdate('H:i:s', $past_time ) . '<br><br>';

Is outputting:

2016-09-09 14:42:50
Past formed: 12:42:50


$past_time = $row->date_added;

Where date added is in a MySQL database and is equal to:

2016-09-09 14:42:50

I'm not changing the timezone, I'm merely converting a timestamp back into gmdate()

At which point is the time having 2 hours taken off it and how do I prevent it?

Edit

$datetime = new DateTime( gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC') );
$past_time = $datetime->createFromFormat( 'Y-m-d H:i:s', $past_time, new DateTimeZone('UTC') )->getTimestamp();
echo 'Past formed: ' . gmdate('H:i:s', $past_time ) . '<br><br>';

This was the solution, I had to set the timezone despite never changing it

It must make sense in a round-a-bout way, but I still don't really understand where DateTime is getting its "from and to"

2016-09-09 14:42:50 is an incomplete timestamp, it is missing the timezone information. Without timezone information, this timestamp could refer to any of over 24 different absolute points in time. 14:42:50 in London, England occurs several hours after 14:42:50 in Tokyo, Japan.

DateTime instances and UNIX timestamps (created with time() or strtotime() ) are absolute points in time, they don't have and aren't influenced by timezones. When converting 2016-09-09 14:42:50 into one of these absolute timestamps, PHP needs to infer the missing information (the timezone) from somewhere. If you do not supply the information explicitly, it takes it from date_default_timezone_get .

$datetime = new DateTime( gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC') );
$past_time = $datetime->createFromFormat( 'Y-m-d H:i:s', $past_time )->getTimestamp();

Let's get rid of the completely superfluous $datetime instance here for simplicity…

$past_time = DateTime::createFromFormat('Y-m-d H:i:s', $past_time)->getTimestamp();

createFromFormat here is reading the incomplete timestamp and infers its timezone. That is where the mismatch is happening, it assumes a timezone other than what the timestamp actually represents. Hence the result is offset by a few hours. getTimestamp than merely reformats that into a different, but still absolute, format of a UNIX timestamp.

echo 'Past formed: ' . gmdate('H:i:s', $past_time) . '<br><br>';

gmdate reads the UNIX timestamp and outputs it converted to the GMT timezone. date uses the date_default_timezone_get timezone, gmdate always uses GMT.

You've got a whole lot of unnecessary conversions going on here. The only thing you really need is:

$timestamp = DateTime::createFromFormat('Y-m-d H:i:s', $past_time, new DateTimeZone('UTC'));
echo 'Past formed: ', $timestamp->format('H:i:s');
  1. Ensure you complete the correct timezone information when converting from 2016-09-09 14:42:50 to a DateTime instance.
  2. Format the DateTime instance in the desired format.

Thing the issue is, when calling this line:

echo 'Past formed: ' . gmdate('H:i:s', $past_time ) . '<br><br>';

gmdate() looks up the current DateTimeZone in your PHP script, and acts on that.

So you have to use this first for the global timezone:

date_default_timezone_set()

Test what you have set up print date_default_timezone_get();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM