I am having difficulty using PHP DateTime
to convert a date received with a GMT -8 timezone (PST) to a human readable format with timezone GMT -7 (PDT).
Here's an example:
$tz = new DateTimeZone('America/Los_Angeles');
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00");
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');
The output of the above code is: 2016-11-07 17:30:00. However, it should display 2016-11-07 18:30:00 because America/Los_Angeles
is now in daylight savings (GMT -7, PDT).
From what I've read in the DateTime docs, the new DateTime
command should be able to interpret that the string 2016-11-07T17:30:00-08:00
has a GMT -8 timezone:
The timezone parameter and the current timezone are ignored when the time parameter either contains a UNIX timestamp (e.g. 946684800) or specifies a timezone (e.g. 2010-01-28T15:00:00+02:00).
Even so, I do not think DateTime
is recognizing GMT -8 correctly.
Does anyone know what approach is necessary to convert between timezones correctly?
Update:
I've also tried passing in a DateTimeZone
as the second parameter to the DateTime
constructor, but also to no avail:
$tz = new DateTimeZone('America/Los_Angeles');
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00", new DateTimeZone("America/Los_Angeles"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');
Also does not work:
$tz = new DateTimeZone('America/Los_Angeles');
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');
Also does not work:
$tz = new DateTimeZone("PDT");
$saleEndDate = new DateTime("2016-11-07T17:30:00", new DateTimeZone("PST"));
$saleEndDate->setTimezone($tz);
echo $saleEndDate->format('Y-m-d H:i:s');
Not the greatest but it's the only way I can think of to do this
$tz = new DateTimeZone('America/Los_Angeles');
$saleEndDate = new DateTime("2016-11-07T17:30:00-08:00");
$saleEndDate->setTimezone($tz);
$stamp = $saleEndDate->format('U');
$zone = $tz->getTransitions($stamp, $stamp);
if(!$zone[0]['isdst']) $saleEndDate->modify('+1 hour');
echo $saleEndDate->format('Y-m-d H:i:s');
What I'm doing here is using the DateTimeZone::getTransitions function to determine if the date you provided is DST or not. If it isn't, we add one hour. Note that this does not change the time zone, it just corrects for the DST shift
You can see it in action here
The DateTime
is functioning as it should. Unless you're in an area that observed different DST to the greater area, America/Los_Angeles
left DST (PDT->PST) on the 6th of November (in 2016).
https://www.timeanddate.com/news/time/usa-canada-end-dst-2016.html
From the timezeonedb
you can inspect the dates it uses by searching the array for your particular Date/Time (which Machavity did) and got the fact that it isn't in DST and then went on to modify it manually. Which is not an answer as it will eventually fail unless you manually add a cut-off time for the manual correction to stop.
Inspecting the transition dates around your date reveals:
date_default_timezone_set('America/Los_Angeles');
$theDate = new DateTime("2016-11-07T17:30:00",new DateTimeZone("America/Los_Angeles"));
$theDateBefore = new DateTime("2016-03-01");
$theDateAfter = new DateTime("2017-03-15");
echo "<pre>";
print_r( $theDate->getTimezone()->getTransitions(
$theDateBefore->getTimestamp(),$theDateAfter->getTimestamp()));
echo "</pre>";
resulting in an array of 4:
Array
(
[0] => Array
(
[ts] => 1456819200
[time] => 2016-03-01T08:00:00+0000
[offset] => -28800
[isdst] =>
[abbr] => PST
)
[1] => Array
(
[ts] => 1457863200
[time] => 2016-03-13T10:00:00+0000
[offset] => -25200
[isdst] => 1
[abbr] => PDT
)
[2] => Array
(
[ts] => 1478422800
[time] => 2016-11-06T09:00:00+0000
[offset] => -28800
[isdst] =>
[abbr] => PST
)
[3] => Array
(
[ts] => 1489312800
[time] => 2017-03-12T10:00:00+0000
[offset] => -25200
[isdst] => 1
[abbr] => PDT
)
)
Array[0] is the timezone in effect as at theDateBefore
and you can see the dates changes are in effect for your timezeone.
Your sale date falls after the change from PDT to PST.
To have the code return an adjusted date/time you would need to manually change it. Doing it the way that's been accepted would yield false results. As I mention, you would need to surround that with the dates you want the custom time zone to be enforced.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With