从偏移量获取时区位置



我需要在php中设置timezone。我有新timezone的偏移量(以秒为单位),我想使用date_default_timezone_set设置它。我不可能像+0200那样将秒转换为偏移量,但我认为这还不够
根据我阅读手册后的理解,我需要给出类似AmericaNew_York的参数。有没有办法将偏移量转换为特定位置?

您实际上无法可靠地做到这一点。每个命名时区都有多个随时间变化的唯一属性。当前偏移量仅为信息的部分。您还必须考虑夏令时的适用方式,每个时区的夏令时适用方式可能不同(或者根本不适用)。您还必须考虑单个时区如何具有不同值的历史,因为它们可能多次更改偏移量或DST规则。

您还应该考虑,在任何给定的时间,几个不同的时区将使用相同的偏移量。如果你只是随便挑选一个,你就忽略了很多重要的细节!

请阅读时区标签wiki。

这里的其他答案可能会返回一个值,但它们都是基于错误的假设。时区不能仅仅用数字来表示。

您可以在DateTimeZone::listAbbreviations()的输出中搜索与您的偏移量匹配的时区:

function convertTimezoneOffsetToId($offsetSeconds)
{
$ids = array();
foreach (DateTimeZone::listAbbreviations() as $abbrev) {
foreach ($abbrev as $zone) {
if ($zone['offset'] == $offsetSeconds) {
$ids[] = $zone['timezone_id'];
}
}
}
return array_unique($ids);
}

例如:

convertTimezoneOffsetToId(5040);

退货:

Array
(
[0] => Europe/Vilnius
[1] => Europe/Warsaw
)

编辑

正如Matt所指出的,这个函数没有考虑DST的历史变化。

因此,这里有一个改进的功能:

function convertTimezoneOffsetToId($offsetSeconds, $unixTimestamp)
{
$ids = array();
foreach (DateTimeZone::listIdentifiers() as $id) {
$dtz   = new DateTimeZone($id);
$trans = $dtz->getTransitions($unixTimestamp, $unixTimestamp);
if ($trans[0]['offset'] == $offsetSeconds) {
$ids[] = $id;
}    
}
return array_unique($ids);
}

它使用DateTimeZone::getTransitions()来获取历史上特定时刻每个时区的偏移量。

例如:

convertTimezoneOffsetToId(19800, time());

返回当前偏移量为19800秒的时区列表:

Array
(
[0] => Asia/Colombo
[1] => Asia/Kolkata
)

和:

convertTimezoneOffsetToId(19800, gmmktime(0, 0, 0, 1, 1, 2000));

返回2000年1月1日偏移19800秒的时区列表:

Array
(
[0] => Asia/Kolkata
)

请注意,Asia/Colombo已经消失,因为在2000年1月1日,其偏移量为21600秒。

有,是的。我只想引用uınbɐɥs的精彩回答:

$timezone = '+2:00';
$timezone = preg_replace('/[^0-9]/', '', $timezone) * 36;
$timezone_name = timezone_name_from_abbr(null, $timezone, true); //= Europe/Paris
date_default_timezone_set($timezone_name);

我鼓励你详细看看他的答案,因为你可能需要考虑到一个bug。

已编辑(原始答案已完全废弃)

一种方法是创建偏移时间字符串(如+0800)到PHP识别的时区名称的映射。这不是一对一,因为每个偏移都有多个名称。但是,由于您关心的是偏移量而不是名称,因此映射可以为任何给定的偏移量选择任何可用的时区名称。

由于没有成百上千个时区,你最终只会得到大约35个条目的数组(有几个时区在30分钟甚至45分钟标记处)。

这里有一个代码示例,可以满足您的需求:

$timezones = array(
'-1100' =>  'Pacific/Midway',
'-1000' =>  'US/Hawaii',
'-0900' =>  'US/Alaska',
'-0800' =>  'US/Pacific',
'-0700' =>  'US/Arizona',
'-0600' =>  'America/Mexico_City',
'-0500' =>  'US/Eastern',
'-0430' =>  'America/Caracas',
'-0400' =>  'Canada/Atlantic',
'-0330' =>  'Canada/Newfoundland',
'-0300' =>  'America/Buenos_Aires',
'-0200' =>  'Atlantic/Stanley',
'-0100' =>  'Atlantic/Azores',
'-0100' =>  'Atlantic/Cape_Verde',
'+0000' =>  'Europe/London',
'+0100' =>  'Europe/Amsterdam',
'+0200' =>  'Europe/Athens',
'+0300' =>  'Asia/Baghdad',
'+0330' =>  'Asia/Tehran',
'+0400' =>  'Europe/Moscow',
'+0430' =>  'Asia/Kabul',
'+0500' =>  'Asia/Karachi',
'+0530' =>  'Asia/Kolkata',
'+0545' =>  'Asia/Kathmandu',
'+0600' =>  'Asia/Yekaterinburg',
'+0700' =>  'Asia/Novosibirsk',
'+0800' =>  'Asia/Krasnoyarsk',
'+0800' =>  'Asia/Urumqi',
'+0900' =>  'Asia/Irkutsk',
'+0930' =>  'Australia/Adelaide',
'+1000' =>  'Asia/Yakutsk',
'+1000' =>  'Australia/Sydney',
'+1100' =>  'Asia/Vladivostok',
'+1200' =>  'Asia/Magadan'
);
for ($offset_hours = -11; $offset_hours <= 12; $offset_hours++) {
// Convert to a timezone string.  For example, 8 => +0800
$offset_string = sprintf("%+03d", $offset_hours) . "00";
date_default_timezone_set($timezones[$offset_string]);
$dt = new DateTime();
print "OFFSET: $offset_hours hours ($offset_string)n";
print $dt->format(DATE_RFC822) . "n";
print "n";
}

for循环只是演示了基于迭代偏移的几乎所有不同时区的设置(为了简单起见,我排除了30分钟和45分钟标记时区)。

以下是运行上述代码的输出摘录:

OFFSET: -11 hours (-1100)
Tue, 25 Feb 14 04:24:13 -1100
OFFSET: -10 hours (-1000)
Tue, 25 Feb 14 05:24:13 -1000
OFFSET: -9 hours (-0900)
Tue, 25 Feb 14 06:24:13 -0900
...
...
...
OFFSET: -1 hours (-0100)
Tue, 25 Feb 14 14:24:13 -0100
OFFSET: 0 hours (+0000)
Tue, 25 Feb 14 15:24:13 +0000
OFFSET: 1 hours (+0100)
Tue, 25 Feb 14 16:24:13 +0100
...
...
...
OFFSET: 10 hours (+1000)
Wed, 26 Feb 14 02:24:13 +1100
OFFSET: 11 hours (+1100)
Wed, 26 Feb 14 02:24:13 +1100
OFFSET: 12 hours (+1200)
Wed, 26 Feb 14 03:24:13 +1200

感谢@Eugene Manuilov对PHP时区的StackOverflow回答,因为这意味着我不必完全从头开始编写数组。

相关内容

  • 没有找到相关文章

最新更新