我正在努力改变电视连续剧的播出日期。我使用的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)播出。
所以我做得对吗,我比较结果的网站错了吗?
发布于 2015-06-01 18:54:25
如果使用new DateTimeZone('GMT-5'),则得到相同的值。GMT-5 +DST不是一个时区名称的有效值,类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注意到,GMT时区的正确名称是Etc/GMT,后面跟着偏移量。
PHP 5.5和PHP 5.6接受并正确解释没有Etc/前缀的GMT时区。旧版本(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校正;- ),因为PHP使用的时区数据库有一种奇怪的行为;这种行为在文档中解释:
警告:
请不要使用这里列出的任何时区(UTC之外),它们只存在于向后兼容的原因。
警告
如果您无视上述警告,还请注意,提供PHP时区支持的IANA时区数据库使用POSIX样式标志,这将导致Etc/GMT+n和Etc/GMT时区与常用时区相反。这意味着GMT-5由上面的代码转换为Etc/GMT+5,GMT-5 +DST被转换为Etc/GMT+4。
发布于 2015-06-01 19:29:15
这应该能行。它解析您提供的值,将输入时区手动调整为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');https://stackoverflow.com/questions/30580466
复制相似问题