23 Stimmen

UTC-Offset in Zeitzone oder Datum umrechnen

Ein Denkanstoß für Sie.

Ich greife auf geografische IP-Daten aus IPInfoDB API und gibt eine Zeitzonenabweichung von der UTC zurück einschließlich Sommerzeit (falls derzeit berücksichtigt).

Ich lebe zum Beispiel in EST (-5) und derzeit ist Sommerzeit, also gibt die geo IP API ( -04:00 ) als Offset.

Das ist wunderbar, denn die Sommerzeit bereitet uns verdammte Kopfschmerzen. Aber zu meiner Überraschung verursachte es noch weitere Kopfschmerzen.

Ich lade diese Daten in PHP, damit sie über AJAX an die Anwendung weitergegeben werden können. Ich möchte die Live-Lokalzeit der IP-Adresse in der Anwendung haben.

Ich habe das alles perfekt eingestellt, aber ich werde verrückt, wenn ich versuche herauszufinden, wie ich die PHP-Zeitzone so einstellen kann, dass sie mit dem Offset übereinstimmt, damit ich einfach die aktuellen Stunden abrufen kann date('H'); und Minuten date('i'); über AJAX zu übergeben.

Ich bin unsicher, ob es eine spezifische Funktion gibt, die mir nur die aktuellen Stunden und Minuten auf der Grundlage dieses Offsets geben kann, oder ob es eine praktische Möglichkeit gibt, die Zeitzone auf der Grundlage des Offsets einzustellen (bei der die Sommerzeit bereits angewendet wird, wenn sie in Kraft ist).

Ich habe Google durchforstet, um eine Antwort auf diese Frage zu finden, aber was ich tue, ist spezifischer, da die Sommerzeit bereits angewendet wird.

Ich habe eine Funktion gefunden unter PHP.net das scheint zu funktionieren (es funktioniert für meine Zeitzone und liefert die korrekte Zeit), obwohl es für andere Zeitzonen wie PST 1 Stunde später kommt als es sein sollte, obwohl der Offset korrekt ist ( -07:00 mit Sommerzeit).

Die von der Funktion zurückgegebene Zeitzone ist Chile/EasterIsland Ich habe das Gefühl, dass das die Ursache ist. Wenn ich könnte, würde ich es nur für die USA funktionieren lassen, aber ich brauche es weltweit.

Das ist die Funktion, die ich jetzt habe. Bitte entschuldigen Sie den extrem unordentlichen Code. Ich habe herumspielen mit Tonnen von Dingen in den letzten Stunden versucht, eine Lösung herauszufinden.

Der größte Teil der Funktionalität wurde online gefunden.

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

Ich habe den Schalter/Koffer für bestimmte Zeitzonen, die :30 y :45 da draußen. Vielleicht gibt es eine Möglichkeit, das auch ohne den Schalter/das Gehäuse einzubauen.

HINWEIS: Die Offsets werden immer als solche zurückgegeben +00:00 o -00:00 von der geo IP API.

Ich wäre dankbar für jede Hilfe oder einen Hinweis auf die richtige Richtung. Ich bin nicht sehr Anfänger mit PHP, aber Offsets sind eine neue Geschichte für mich. Danke!

58voto

uınbɐɥs Punkte 6968

Dies kann ganz einfach geschehen, indem man den Offset in Sekunden umwandelt und ihn an 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

Der dritte Parameter von timezone_name_from_abbr steuert, ob die Sommerzeit eingestellt werden soll oder nicht.

Fehler #44780 :

timezone_name_from_abbr() gibt bei einigen Zeitzonen false zurück Offsets zurück. Insbesondere bei Hawaii, das eine Abweichung von -10 von GMT hat, -36000 Sekunden.

Referenzen:

4voto

Dejan Marjanović Punkte 18984
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;
    }
}

Vielleicht habe ich Sie an einigen Stellen missverstanden, aber ich hoffe, es hilft Ihnen, wenn Sie etwas genauer werden könnten.

Für Chile bekomme ich:

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

Ausgabe des obigen Beispiels:

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

Das passt zu meiner Zeitzone.

3voto

Aurel Punkte 3454
$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);

Ergebnisse:

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

3voto

William Entriken Punkte 33360

Heutzutage ist die DateTimeZone Konstruktor kann explizit einen UTC-Offset akzeptieren, den Sie meines Wissens haben.

Also einfach:

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

Dokumentation:

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

Anmerkung: Laut diesem Dokumentationslink ist diese neue Konstruktorverwendung seit PHP Version 5.5.10 verfügbar.

2voto

Matt Johnson-Pint Punkte 212496

Es ist nicht ratsam, Zeitzonen-Offsets auf eine Zeitzonen-Kennung zurückzuführen. Viele Zeitzonen haben den gleichen Versatz.

Selbst innerhalb eines einzelnen Landes ist dies problematisch. Bedenken Sie, dass in den Vereinigten Staaten der Offset von -5 sowohl von der Central Standard Time ( America/Chicago ) und Eastern Daylight Time ( America/New_York ) zu verschiedenen Zeiten des Jahres.

Bedenken Sie auch, dass es Zeiten gibt, in denen BEIDE Zeitzonen gleichzeitig -5 verwenden. Zum Beispiel könnte Sonntag, der 3. November 2013 um 1:00 Uhr morgens in UTC-5 entweder in CDT oder EST sein. Sie hätten keine Möglichkeit, nur durch -5 zu unterscheiden, welche Zeitzone es war.

Details hier.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X