web-dev-qa-db-ja.com

UTCオフセットをタイムゾーンまたは日付に変換する

あなたのための頭のスクラッチャー。

IPInfoDB のAPIからgeo IPデータを取得すると、UTCからのタイムゾーンオフセットが返されますincludeDST(現在反映されている場合) )。

たとえば、私はEST(-5)に住んでいて、現在はDSTなので、geo IP APIはオフセットとして(_-04:00_)を返します。

DSTはひどい頭痛の種なので、これは素晴らしいことです。しかし、驚いたことに、それは別の頭痛の種を引き起こしました。

このデータをPHP=アプリケーション経由で渡されるAJAXにロードします。アプリのIPアドレスのライブのローカル時間を取得したいと思います。

すべてを完璧に設定しましたが、PHPタイムゾーンをオフセットに一致させるように設定して、現在の時間を取得できるようにする方法を理解しようとしています。date('H');そして、AJAX経由で渡される分date('i');

そのオフセットに基づいて現在の時間と分を単に与えることができる特定の関数があるのか​​、またはオフセットに基づいてタイムゾーンを設定する実用的な方法があるのか​​わかりません(DSTが有効になっている場合は、すでに適用されています)。 。

私はこれに対する答えを見つけるためにGoogleを検索して検索してきましたが、DSTがすでに適用されているので、私がやっていることはより具体的です。

私は PHP.net にあるトリックを見つけました(私のタイムゾーンで機能し、正しい時間を返します)。ただし、PSTなどの他のタイムゾーンでは、本来の時間よりも1時間遅れて戻ります。オフセットは正しいですが(DSTでの_-07:00_)。

関数から返されるタイムゾーンは_Chile/EasterIsland_で、これが原因だと感じています。できれば、これは米国でのみ機能しますが、世界規模である必要があります。

これが今持っている機能です。非常に厄介なコードを許しなさい。私は過去数時間にわたって解決策を理解するためにたくさんのことを試してきました。

機能のほとんどはオンラインで見つかりました。

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

_:30_および_:45_の特定のタイムゾーンのスイッチ/ケースをそこに含めました。スイッチ/ケースを必要とせずにそれを含める方法があるかもしれません。

注:オフセットは常にgeo IP APIから_+00:00_または_-00:00_として返されます。

私はどんな助けや正しい方向へのポイントにも感謝します。私はPHPの初心者ではありませんが、オフセットは私にとって新しい話です。ありがとう!

16
Kyle Ross

オフセットを秒にして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の3番目のパラメーターは、夏時間を調整するかどうかを制御します。

バグ#4478

timezone_name_from_abbr()は、一部のタイムゾーンオフセットでfalseを返します。特に、GMTオフセットから-10、-36000秒のハワイ。

参照:

52
uınbɐɥs
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;
    }
}

誤解している部分もあるかもしれませんが、お役に立てば幸いです。具体的にお答えいただければ助かります。

チリの場合:

-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

これは私のタイムゾーンを釘付けにします。

4
$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"
}
3
Aurel

時間帯オフセットを時間帯識別子にマッピングすることはお勧めしません。多くのタイムゾーンは同じオフセットを共有しています。

これは単一の国でも問題があります。米国では、-5オフセットが中央標準時(America/Chicago)および東部夏時間(America/New_York)年間のさまざまな時期。

また、これらのタイムゾーンの両方が同時に-5を使用する場合があることも考慮してください。たとえば、UTC-5の2013年11月3日日曜日の午前1時は、CDTまたはESTのいずれかになります。どのタイムゾーンであるかを-5だけで区別する方法はありません。

詳細はこちら

2

現在、DateTimeZoneコンストラクターはUTCオフセットを明示的に受け入れることができます。

これだけ:

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

ドキュメンテーション:

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

注:このドキュメントリンクによると、この新しいコンストラクタの使用法はPHPバージョン5.5.10。以降利用可能です)

1

DateTime PHP extension(これは有効になっており、デフォルトですべてのPHPバージョン> = 5.2.0に含まれています)に含まれています。 、コンパイル時に明示的に無効にされていない限り)。

ここで必要なすべてのことをうまく実行します。

1
c2h5oh

私にとってこの作品:

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

これを使用するには、これを呼び出して現在の時刻を取得します。

echo Get_Offset_Date('+2:00');

そして、これはオフセット日付を取得するためです(入力はunixtimeです)

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

GMT時間も使用でき、後で要件に変換できます

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

GMTは、世界中で一般的なグリニッジ標準時を指します。

0
Gaurav Singh