我正在尝试转换电视剧集的播出日期时间。我使用的API会返回这个确切的值:
Datetime: 2015-05-31 21:00
Country: US
Timezone: GMT-5 +DST
现在我正在尝试使用给定的数据检索我的时区(欧洲/罗马)的播出日期时间。我正在做的是:
$date = new DateTime('2015-05-31 21:00', new DateTimeZone('GMT-5 +DST'));
$date->setTimezone(new DateTimeZone('Europe/Rome'));
echo $date->format('Y-m-d H:i:s');
打印哪些:
2015-06-01 04:00:00
我有一些疑问是正确的方法,因为提供相同信息的其他网站说我的国家(IT /意大利)的上一集已于6月1日03:00播出(而不是04: 00)。
我正在做得正确,我正在比较结果的网站是错误的吗?
答案 0 :(得分:2)
如果您使用new DateTimeZone('GMT-5')
,则会获得相同的值。 GMT-5 +DST
不是valid value for a timezone name,并且类DateTimeZone
的构造函数可能会使用从提供给它的参数中成功解析的内容。
我认为你应该手工解析Timezone:
"的价值"如果字符串以+DST
结尾,则将偏移量调整1小时。
如果您知道返回的时区总是GMT-5
,那么您只需检查字符串是否为GMT-5 +DST
并改为使用GMT-4
。
否则,您可以尝试使用正则表达式解析收到的时区:
// 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');
更新:@ matt-johnson注意到,GMT
时区的正确名称为Etc/GMT
,后跟偏移量。
PHP 5.5
和PHP 5.6
接受并正确解释没有GMT
前缀的Etc/
时区。旧版本(5.3
,5.4
)会抛出一条带有消息'DateTimeZone::__construct(): Unknown or bad timezone (GMT-4)'
我更新了上面的代码以使用正确的名称。你必须注意到一些事情:
$tz = sprintf('Etc/GMT%+d', -(intval($m[1])+1));
sprintf()
格式字符串上的+
符号强制在数字前面生成+
符号(如果数字为正数);对于负数,无论有没有生成-
符号; +1
中的intval($m[1])+1
执行DST
更正; -
;行为在documentation:中解释
警告强>:
请不要使用此处列出的任何时区(除了UTC),它们仅出于向后兼容的原因而存在。
警告强>
如果您忽略上述警告,请注意,提供PHP时区支持的IANA时区数据库使用POSIX样式标志,这导致Etc / GMT + n和Etc / GMT-n时区为与普通用法相反。
GMT-5
由上面的代码转换为Etc/GMT+5
,GMT-5 +DST
转换为Etc/GMT+4
。
答案 1 :(得分:2)
这应该有效。它会解析您提供的值,手动将输入时区调整为UTC。然后使用PHP的时区(即IANA时区)转换为所需的目标时区。
// The values received from the API
$datetime = '2015-05-31 21:00';
$timezone = 'GMT-5 +DST';
// Parse the time zone
$m = array();
preg_match('/GMT([+-]\d+)( \+DST)?/', $timezone, $m);
$offset = intval($m[1]);
$dst = sizeof($m) == 3;
// Adjust for the DST flag
if ($dst) $offset++;
// Apply the offset to the datetime given
$dt = new DateTime($datetime, new DateTimeZone("UTC"));
$dt->setTimestamp($dt->getTimestamp() - ($offset * 3600));
// Convert it to whatever time zone you like
$dt->setTimezone(new DateTimeZone('Europe/Rome'));
echo $dt->format('Y-m-d H:i:s');