将UTC偏移量转换为时区或date

一个头刮你的。

我从IPInfoDB的API中获取地理IP数据,并从UTC返回包含 DST(如果当前已反映)的时区偏移量。

例如,我住在EST(-5),目前是DST,所以地理IP API返回( -04:00 )作为抵消。

因为DST是一个令人头疼的事情,所以这真是太好了。 但令我惊讶的是,这又令人头痛。

我加载这个数据在PHP中通过AJAX传递给应用程序。 我想在应用程序的IP地址的本地时间。

我已经完全设置,但我疯了试图找出如何设置PHP时区匹配的偏移量,所以我可以抓住当前的小时date('H'); 和分钟date('i'); 通过AJAX传递给

我不确定是否有一个特定的函数可以根据偏移量给出当前的小时数和分钟数,或者有一个实际的方法来设置基于偏移量的时区(如果有效,将会应用DST) 。

我一直在search和search谷歌find一个答案,但我所做的更具体,因为已经应用了DST。

我发现PHP.net上的一个函数似乎有效(它适用于我的时区并返回正确的时间),虽然对于其他时区(如PST),即使偏移量正确,它也会在1小时后返回-07:00与DST)。

从function返回的时区是Chile/EasterIsland ,我有一个感觉是原因。 如果可以的话,我会让这只对美国有用,但我确实需要它在全世界。

这是我现在的function。 请原谅非常混乱的代码。 在过去的几个小时里,我一直在玩弄很多东西,试图找出一个解决scheme。

大部分的function都是在网上find的。

 function offsetToTZ($offset) { switch((string) $offset) { case '-04:30' : return 'America/Caracas'; break; case '-03:30' : return 'Canada/Newfoundland'; break; case '+03:30' : return 'Asia/Tehran'; break; case '+04:30' : return 'Asia/Kabul'; break; case '+05:30' : return 'Asia/Kolkata'; break; case '+05:45' : return 'Asia/Kathmandu'; break; case '+09:30' : return 'Australia/Darwin'; break; } $offset = (int) str_replace(array('0',0,':00',00,'30',30,'45',45,':','+'),'', (string) $offset); $offset = $offset*60*60; $abbrarray = timezone_abbreviations_list(); foreach ($abbrarray as $abbr) { foreach($abbr as $city) { if($city['offset'] == $offset) { return $city['timezone_id']; } } } return false; } 

我在一些时间区域包括了开关/shell:30:45 。 可能还有一种方法可以包括,也不需要开关/情况。

注意:偏移总是从地理IP API返回+00:00-00:00

我将不胜感激任何帮助或点正确的方向。 我并不是PHP的新手,但补偿对我来说是一个新的故事。 谢谢!

它可以很简单地完成,通过将偏移量转换为秒并将其传递给timezone_name_from_abbr

 <?php $offset = '-7:00'; // Calculate seconds from offset list($hours, $minutes) = explode(':', $offset); $seconds = $hours * 60 * 60 + $minutes * 60; // Get timezone name from seconds $tz = timezone_name_from_abbr('', $seconds, 1); // Workaround for bug #44780 if($tz === false) $tz = timezone_name_from_abbr('', $seconds, 0); // Set timezone date_default_timezone_set($tz); echo $tz . ': ' . date('r'); 

演示

timezone_name_from_abbr的第三个参数控制是否调整夏令时。

错误#44780 :

timezone_name_from_abbr()将在某些时区偏移量上返回false。 特别是 – 夏威夷,从GMT偏移-10,-36000秒。

参考文献:

  • timezone_name_from_abbr
  • date_default_timezone_set
  • date
 date_default_timezone_set('UTC'); $timezones = array(); foreach (DateTimeZone::listAbbreviations() as $key => $array) { $timezones = array_merge($timezones, $array); } $utc = new DateTimeZone('UTC'); $timezone_offset = '+02:00'; # 2H $sign = substr($timezone_offset, 0, 1) == '+'? '': '-'; $offset = substr($timezone_offset, 1, 2) . 'H' . substr($timezone_offset, 4, 2) . 'M'; $operation = $sign == ''? 'add': 'sub'; $start = new DateTime('', $utc); $date = new DateTime('', $utc); $date->{$operation}(new DateInterval("PT{$offset}")); $offset = $start->diff($date)->format('%r') . ($start->diff($date)->h * 3600 + $start->diff($date)->m * 60 + $start->diff($date)->s); # 7200 (2H) echo $offset, PHP_EOL; echo $date->format('Ymd H:i:s'), PHP_EOL; foreach($timezones as $timezone) { if($timezone['offset'] == $offset) { echo $timezone['timezone_id'], PHP_EOL; } } 

我可能在某些地方误会了你,但是我希望它有帮助,如果你可以更具体一些,我可能会更有帮助。

对于智利我得到:

 -25200 (-7h) 2012-08-07 18:05:24 (current time 2012-08-08 01:05:24) Chile/EasterIsland 

上面的例子的输出:

 7200 2012-08-08 02:49:56 Europe/London Europe/Belfast Europe/Gibraltar Europe/Guernsey Europe/Isle_of_Man Europe/Jersey GB Africa/Khartoum Africa/Blantyre Africa/Bujumbura Africa/Gaborone Africa/Harare Africa/Kigali Africa/Lubumbashi Africa/Lusaka Africa/Maputo Africa/Windhoek Europe/Berlin Africa/Algiers Africa/Ceuta Africa/Tripoli Africa/Tunis Arctic/Longyearbyen Atlantic/Jan_Mayen CET Europe/Amsterdam Europe/Andorra Europe/Athens Europe/Belgrade Europe/Bratislava Europe/Brussels Europe/Budapest Europe/Chisinau Europe/Copenhagen Europe/Gibraltar Europe/Kaliningrad Europe/Kiev Europe/Lisbon Europe/Ljubljana Europe/Luxembourg Europe/Madrid Europe/Malta Europe/Minsk Europe/Monaco Europe/Oslo Europe/Paris Europe/Podgorica Europe/Prague Europe/Riga Europe/Rome Europe/San_Marino Europe/Sarajevo Europe/Simferopol Europe/Skopje Europe/Sofia Europe/Stockholm Europe/Tallinn Europe/Tirane Europe/Tiraspol Europe/Uzhgorod Europe/Vaduz Europe/Vatican Europe/Vienna Europe/Vilnius Europe/Warsaw Europe/Zagreb Europe/Zaporozhye Europe/Zurich WET Europe/Kaliningrad Europe/Helsinki Africa/Cairo Africa/Tripoli Asia/Amman Asia/Beirut Asia/Damascus Asia/Gaza Asia/Istanbul Asia/Nicosia EET Europe/Athens Europe/Bucharest Europe/Chisinau Europe/Istanbul Europe/Kaliningrad Europe/Kiev Europe/Mariehamn Europe/Minsk Europe/Moscow Europe/Nicosia Europe/Riga Europe/Simferopol Europe/Sofia Europe/Tallinn Europe/Tiraspol Europe/Uzhgorod Europe/Vilnius Europe/Warsaw Europe/Zaporozhye Asia/Jerusalem Asia/Gaza Asia/Tel_Aviv MET Africa/Johannesburg Africa/Maseru Africa/Mbabane Africa/Windhoek Africa/Windhoek Africa/Ndjamena Europe/Lisbon Europe/Madrid Europe/Monaco Europe/Paris WET Europe/Luxembourg 

哪个钉我的时区。

 $UTC_offset = '+03:00'; $date = new \DateTime('now', 'UTC'); var_dump($date); $timezone = new \DateTimeZone(str_replace(':', '', $UTC_offset)); $date->setTimezone($timezone); var_dump($date); 

结果:

 class DateTime#205 (3) { public $date => string(26) "2015-01-20 06:00:00.000000" public $timezone_type => int(3) public $timezone => string(3) "UTC" } class DateTime#205 (3) { public $date => string(26) "2015-01-20 09:00:00.000000" public $timezone_type => int(1) public $timezone => string(6) "+03:00" } 

您可能需要查看DateTime PHP扩展(在所有PHP版本中默认启用&包含> = 5.2.0,除非它在编译时被明确禁用)。

它在这里完成你所需要的一切。

将时区偏移映射回时区标识符是没有意义的。 许多时区共享相同的偏移量。

即使在一个国家内,这也是有问题的。 考虑到在美国,中央标准时间( America/Chicago )和东部夏令时( America/New_York )在一年的不同时间使用-5偏移量。

还要考虑到有时候这两个时区的BOTH同时使用-5。 例如,2013年11月3日星期日UTC-5上午1:00可能是CDT或EST。 你无法区分只是它是哪个时区。

详情在这里。

您也可以使用GMT时间,然后将其转换为您的要求

 <?php echo gmdate("M d YH:i:s", mktime(0, 0, 0, 1, 1, 1998)); ?> 

格林尼治标准时间是世界各地常见的格林尼治标准时间。