web-dev-qa-db-fra.com

Convertir le décalage UTC en fuseau horaire ou en date

Un gratte-tête pour vous.

J'attrape les données IP géographiques de IPInfoDB 'API et il retourne un décalage de fuseau horaire par rapport à UTC y compris DST (si actuellement reflété ).

Par exemple, je vis dans EST (-5) et actuellement c'est DST, donc l'API geo IP renvoie (-04:00) Comme décalage.

C'est merveilleux car DST est un mal de tête flippant. Mais à ma grande surprise, cela a causé un autre mal de tête.

Je charge ces données dans PHP à transmettre via AJAX à l'application. Je voudrais avoir l'heure locale en direct de l'adresse IP sur l'application.

J'ai tout réglé parfaitement, mais je deviens fou d'essayer de comprendre comment définir le fuseau horaire PHP pour qu'il corresponde au décalage afin que je puisse simplement saisir les heures actuelles date('H'); et minutes date('i'); pour passer via AJAX.

Je ne sais pas s'il existe une fonction spécifique qui peut simplement me donner les heures et les minutes actuelles en fonction de ce décalage ou s'il existe un moyen pratique de définir le fuseau horaire en fonction du décalage (qui aura déjà l'heure d'été appliquée si elle est en vigueur) .

J'ai cherché et cherché sur Google pour trouver une réponse à cela, mais ce que je fais est plus spécifique car l'heure d'été est déjà appliquée.

J'ai trouvé une fonction sur PHP.net qui semble faire l'affaire (cela fonctionne pour mon fuseau horaire et renvoie l'heure correcte) bien que pour d'autres fuseaux horaires tels que PST, il revient 1 heure plus tard qu'il ne devrait l'être même si le décalage est correct (-07:00 avec DST).

Le fuseau horaire renvoyé par la fonction est Chile/EasterIsland Dont j'ai l'impression que c'est la cause. Si je pouvais, je ferais en sorte que cela ne fonctionne que pour les États-Unis, mais j'ai besoin que ce soit dans le monde entier.

C'est la fonction que j'ai maintenant. Veuillez excuser le code extrêmement salissant. J'ai joué avec des tonnes de choses au cours des dernières heures en essayant de trouver une solution.

La plupart des fonctionnalités ont été trouvées en ligne.

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

J'ai inclus le commutateur/boîtier pour certains fuseaux horaires qui sont :30 Et :45 Là-bas. Il peut y avoir un moyen de l'inclure également sans avoir besoin du commutateur/boîtier.

REMARQUE: Les décalages sont toujours renvoyés tels quels +00:00 Ou -00:00 À partir de l'API geo IP.

J'apprécierais toute aide ou un point dans la bonne direction. Je ne suis pas très novice avec PHP, mais les compensations sont une nouvelle histoire pour moi. Merci!

16
Kyle Ross

Cela peut être fait tout simplement, en transformant le décalage en secondes et en le passant à 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');

Démo

Le troisième paramètre de timezone_name_from_abbr contrôle s'il faut ajuster l'heure d'été ou non.

Bogue n ° 4478 :

timezone_name_from_abbr () retournera false sur certains décalages de fuseau horaire. En particulier - Hawaii, qui a un décalage de -10 par rapport au GMT, -36000 secondes.

Références:

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

Je vous ai peut-être mal compris dans certaines parties, mais j'espère que cela aide, si vous pouvez être plus précis, je pourrais être plus utile.

Pour le Chili, je reçois:

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

Sortie de l'exemple ci-dessus:

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

Qui cloue mon fuseau horaire.

4
Dejan Marjanovic
$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);

Résultats:

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

Il n'est pas conseillé de mapper les décalages de fuseau horaire sur un identifiant de fuseau horaire. De nombreux fuseaux horaires partagent le même décalage.

Même dans un seul pays, cela est problématique. Sachez qu'aux États-Unis, le décalage de -5 est utilisé par les deux Central Standard Time (America/Chicago) et heure avancée de l'Est (America/New_York) à différents moments de l'année.

Considérez également qu'il y a des moments où les DEUX de ces fuseaux horaires utilisent -5 en même temps. Par exemple, le dimanche 3 novembre 2013 à 1 h 00 en UTC-5 pourrait être en CDT ou en EST. Vous n'auriez aucun moyen de distinguer juste -5 de quel fuseau horaire il s'agissait.

Détails ici.

2
Matt Johnson-Pint

De nos jours, le constructeur DateTimeZone peut accepter explicitement un décalage UTC, ce que je crois comprendre.

Alors juste:

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

Documentation:

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

Remarque: par ce lien de documentation, cette nouvelle utilisation du constructeur est disponible depuis PHP version 5.5.10.

1
William Entriken

Vous voudrez peut-être jeter un œil à DateTime PHP (elle est activée et incluse par défaut dans toutes les versions PHP versions> = 5.2.0) , sauf s'il a été spécifiquement désactivé lors de la compilation).

Il fait tout ce dont vous avez besoin ici assez bien.

1
c2h5oh

Ce travail pour moi:

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

Pour l'utiliser, il suffit d'appeler ceci pour obtenir l'heure actuelle:

echo Get_Offset_Date('+2:00');

Et ceci pour obtenir la date de décalage (l'entrée est unixtime)

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

Vous pouvez également utiliser l'heure GMT et la convertir ensuite en fonction de vos besoins

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

GMT fait référence à l'heure de Greenwich, qui est courante dans le monde entier.

0
Gaurav Singh