You get the same value if you use new DateTimeZone('GMT-5')
. GMT-5 +DST
is not a valid value for a timezone name and probably the constructor of class DateTimeZone
uses as much as it can successfully parse from the argument provided to it.
I think you should parse the value of Timezone:
"by hand" and adjust the offset by 1 hour if the string ends with +DST
.
If you know that the returned timezone is always GMT-5
then you can simply check if the string is GMT-5 +DST
and use GMT-4
instead.
Otherwise you can try to parse the received timezone using regular expressions:
// The timezone received from the API
$timezone = 'GMT-5 +DST';
$m = array();
if (preg_match('/^GMT([+-]\d+)( \+DST)?$/', $timezone, $m)) {
if ($m[2] == ' +DST') {
// Compute the correct offset using DST
$tz = sprintf('Etc/GMT%+d', -(intval($m[1])+1));
} else {
// No DST; use the correct name of the time zone
$tz = sprintf('Etc/GMT%+d', -intval($m[1]));
}
} else {
// The timezone name has a different format; use it as is
// You should do better checks here
$tz = $timestamp;
}
$date = new DateTime('2015-05-31 21:00', new DateTimeZone($tz));
$date->setTimezone(new DateTimeZone('Europe/Rome'));
echo $date->format('Y-m-d H:i:s');
Update: As @matt-johnson notices, the correct name of the GMT
time zones is Etc/GMT
followed by the offset.
PHP 5.5
and PHP 5.6
accept and correctly interpret the GMT
timezones without the Etc/
prefix. Older versions (5.3
, 5.4
) throw an exception with message 'DateTimeZone::__construct(): Unknown or bad timezone (GMT-4)'
I updated the code above to use the correct names. There are some things you must notice in the line:
$tz = sprintf('Etc/GMT%+d', -(intval($m[1])+1));
- the
+
sign on the sprintf()
format string forces the +
sign to be produced in front of the number (if the number is positive); for negative numbers a -
sign is produced with or without it;
- the
+1
in the intval($m[1])+1
does the DST
correction;
- the sign of the computed value is changed (notice the
-
in front of it) because of a strange behaviour of the timezone database used by PHP; the behaviour is explained in the documentation:
Warning:
Please do not use any of the timezones listed here (besides UTC), they only exist for backward compatible reasons.
Warning
If you disregard the above warning, please also note that the IANA timezone database that provides PHP's timezone support uses POSIX style signs, which results in the Etc/GMT+n and Etc/GMT-n time zones being reversed from common usage.
This means
GMT-5
is converted by the code above to
Etc/GMT+5
and
GMT-5 +DST
is converted to
Etc/GMT+4
.