php 将 UTC 偏移量转换为时区或日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11820718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:11:58  来源:igfitidea点击:

Convert UTC offset to timezone or date

phpgeolocationtimezonetimezone-offset

提问by Kyle Ross

A head scratcher for you.

给你一个头疼的问题。

I am grabbing geo IP data from IPInfoDB's API and it returns a timezone offset from UTC includingDST (if currently reflected).

我正在从IPInfoDB的 API获取地理 IP 数据,它从 UTC 返回一个时区偏移量,包括DST(如果当前反映)。

For example, I live in EST (-5) and currently it's DST, so the geo IP API returns (-04:00) as the offset.

例如,我住在 EST (-5) 并且当前是 DST,因此地理 IP API 返回 ( -04:00) 作为偏移量。

This is wonderful since DST is a freaking headache. But to my surprise, it caused another headache.

这很棒,因为 DST 令人头疼。但令我惊讶的是,它又引起了另一个头痛。

I load this data in PHP to be passed via AJAX to the application. I would like to have the live local time of the IP address on the app.

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

I have that all set perfectly, but I am going crazy trying to figure out how to set the PHP timezone to match the offset so I can just grab the current hours date('H');and minutes date('i');to pass to via AJAX.

我已经完美地设置了所有这些,但是我疯狂地想弄清楚如何设置 PHP 时区以匹配偏移量,这样我就可以通过 AJAX获取当前的小时date('H');和分钟date('i');

I am unsure if there is a specific function that can just give me the current hours and minutes based on that offset or if there is a practical way to set the timezone based on the offset (which will have DST already applied if is in effect).

我不确定是否有一个特定的函数可以根据该偏移量给我当前的小时和分钟,或者是否有一种实用的方法可以根据偏移量设置时区(如果有效,DST 已经应用) .

I've been searching and searching Google to find an answer to this, but what I am doing is more specific since DST is already applied.

我一直在搜索和搜索谷歌以找到答案,但我所做的更具体,因为已经应用了夏令时。

I found one function on PHP.netthat seems to do the trick (it works for my timezone and returns the correct time) although for other timezones such as PST, it's returning 1 hour later than it should be even though the offset is correct (-07:00with DST).

我在PHP.net上发现了一个似乎可以解决问题的函数(它适用于我的时区并返回正确的时间),尽管对于 PST 等其他时区,它返回的时间比它应该晚 1 小时,即使偏移量是正确的(-07:00与夏令时)。

The timezone returned from the function is Chile/EasterIslandwhich I have a feeling is the cause. If I could, I would make this only work for the USA, but I do need it to be worldwide.

从函数返回的时区是Chile/EasterIsland我觉得是原因。如果可以的话,我会让它只对美国有效,但我确实需要它在全球范围内使用。

This is the function I have now. Please excuse the extremely messy code. I have been playing around with tons of things over the last few hours trying to figure out a solution.

这就是我现在拥有的功能。请原谅极其凌乱的代码。在过去的几个小时里,我一直在玩很多东西,试图找出解决方案。

Most of the functionality was found online.

大多数功能都是在网上找到的。

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; 
}

I included the switch/case for certain timezones that are :30and :45out there. There may be a way to include that also without the need of the switch/case.

我包括用于某些时区是开关/壳体:30:45在那里。可能有一种方法可以在不需要开关/外壳的情况下包含它。

NOTE:The offsets are always returned as such +00:00or -00:00from the geo IP API.

注意:偏移量始终如此+00:00-00:00从地理 IP API 返回。

I would appreciate any help or a point in the right direction. I'm not very novice with PHP, but offsets are a new story for me. Thanks!

我将不胜感激任何帮助或正确方向的观点。我对 PHP 不是很陌生,但偏移量对我来说是一个新故事。谢谢!

回答by u?nb??s

It can be done quite simply, by turning the offset into seconds and passing it to timezone_name_from_abbr:

它可以很简单地完成,通过将偏移量转换为秒并将其传递给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');

Demo

演示

The third parameter of timezone_name_from_abbrcontrols whether to adjust for daylight saving time or not.

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

Bug #44780:

错误 #44780

timezone_name_from_abbr() will return false on some time zone offsets. In particular - Hawaii, which has a -10 from GMT offset, -36000 seconds.

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

References:

参考:

回答by Dejan Marjanovic

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('Y-m-d H:i:s'), PHP_EOL;

foreach($timezones as $timezone)
{
    if($timezone['offset'] == $offset)
    {
        echo $timezone['timezone_id'], PHP_EOL;
    }
}

I might have misunderstood you in some parts, but I hope it helps, if you could be more specific, I might be more helpful.

我可能在某些方面误解了你,但我希望它有所帮助,如果你能更具体,我可能会更有帮助。

For Chile I get:

对于智利,我得到:

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

Output of the example above:

上面例子的输出:

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

Which nails my timezone.

这决定了我的时区。

回答by Aurel

$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);

Results:

结果:

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"
}

回答by Matt Johnson-Pint

It is unadvised to map time zone offsets back to a time zone identifier. Many time zones share the same offset.

不建议将时区偏移量映射回时区标识符。许多时区共享相同的偏移量。

Even within a single country, this is problematic. Consider that in the United States, the -5 offset is used by both Central Standard Time (America/Chicago) and Eastern Daylight Time (America/New_York) at different times of the year.

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

Also consider that there are times where BOTH of those time zones use -5 at the same time. For example, Sunday November 3rd 2013 at 1:00 AM in UTC-5 could be either in CDT or EST. You'd have no way to distinguish just by -5 which time zone it was.

还要考虑到有时这两个时区同时使用 -5。例如,UTC-5 的 2013 年 11 月 3 日星期日凌晨 1 点可以是 CDT 或 EST。您无法仅通过 -5 来区分它是哪个时区。

Details here.

详情在这里。

回答by c2h5oh

You might want to have a look at DateTimePHP extension (it's enabled & included by default in all PHP versions >= 5.2.0, unless it was specifically disabled at compile time).

你可能想看看DateTimePHP 扩展(它在所有 PHP 版本>= 5.2.0 中默认启用并包含,除非它在编译时被明确禁用)。

It does everything you need here quite well.

它可以很好地完成您在这里需要的一切。

回答by William Entriken

Nowadays the DateTimeZoneconstructor can explicitly accept a UTC offset, which I understand you have.

如今,DateTimeZone构造函数可以明确接受 UTC 偏移量,我知道你有。

So just:

所以就:

$timeZone = new DateTimeZone('+0100');

Documentation:

文档:

http://php.net/manual/en/datetimezone.construct.php

http://php.net/manual/en/datetimezone.construct.php

Note: per that documentation link, this new constructor usage has been available since PHP version 5.5.10.

注意:根据该文档链接,自 PHP 5.5.10 版起就可以使用这种新的构造函数用法。

回答by Mohamad Hamouday

This work for me:

这对我有用:

function Get_Offset_Date($Offset, $Unixtime = false, $Date_Format = 'Y.m.d,H:i')
{
    try
    {
        $date   = new DateTime("now",new DateTimeZone($Offset));
        if($Unixtime)
        {
            $date->setTimestamp($Unixtime);
        }

        $Unixtime = $date->getTimestamp();
        return $date->format($Date_Format);
    }

    catch(Exception $e)
    {
        return false;
    }
}

To use it just call this to get current time:

要使用它,只需调用它来获取当前时间:

echo Get_Offset_Date('+2:00');

And this for get Offset date (input is unixtime)

这用于获取偏移日期(输入为 unixtime)

echo Get_Offset_Date('+2:00',1524783867);

回答by Gaurav Singh

You can use GMT time also and convert it to your requirement afterwards

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

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

GMT refers Greenwich Mean Time which is common all over the world.

GMT 是指格林威治标准时间,在世界范围内通用。