45 votes

Comment obtenir le temps moyen de Greenwich en PHP ?

J'ai un serveur qui est réglé sur EST, et tous les enregistrements de la base de données sont réglés sur EST. J'aimerais savoir comment le régler sur GMT. Je veux offrir une option de fuseau horaire à mes utilisateurs.

70voto

nickf Points 185423

Je voudrais fortement suggère d'éviter de jouer avec les timestamps UNIX pour faire croire à un fuseau horaire différent. C'est une leçon que j'ai apprise à mes dépens, bien trop souvent.

Un horodatage est le nombre de secondes écoulées depuis minuit le 1er janvier 1970, heure GMT. Peu importe où vous vous trouvez dans le monde, un horodatage donné représente exactement le même moment dans le temps, indépendamment des fuseaux horaires. Oui, l'horodatage "0" signifie 10 h 1/1/70 en Australie, minuit 1/1/70 à Londres et 17 h 31/12/69 à Los Angeles, mais cela ne signifie pas que vous pouvez simplement ajouter ou soustraire des valeurs et garantir l'exactitude.

L'exemple le plus frappant, qui m'a fait perdre la tête chaque année pendant bien trop longtemps, est celui de l'heure d'été. L'heure d'été signifie qu'il y a des "heures d'horloge" qui n'existent pas dans certaines parties du monde. Par exemple, dans la plupart des régions des États-Unis, l'heure de 2 h 01 du matin le 2 avril 2006 n'existait pas.

Assez de divagations quasi-intelligibles. Mon conseil est de stocker vos dates dans la base de données en tant qu'horodatage, et ensuite...

  • Si vous avez besoin de l'heure locale du serveur, utilisez date()
  • Si vous avez besoin d'obtenir le GMT, alors utilisez gmdate()
  • Si vous avez besoin d'obtenir un fuseau horaire différent, utilisez date_default_timezone_set() et ensuite date()

Par exemple,

$timestamp = time();

echo "BRISBANE: " . date('r', $timestamp) . "\n";
echo "     UTC: " . gmdate('r', $timestamp) . "\n";
date_default_timezone_set('Africa/Johannesburg');
echo "  JOBURG: " . date('r', $timestamp) . "\n";

// BRISBANE: Tue, 12 May 2009 18:28:20 +1000
//      UTC: Tue, 12 May 2009 08:28:20 +0000
//   JOBURG: Tue, 12 May 2009 10:28:20 +0200

Vos valeurs resteront ainsi propres (vous n'aurez pas à vous soucier d'ajouter des décalages, puis de les soustraire avant de les enregistrer), elles respecteront toutes les règles relatives à l'heure d'été et vous n'aurez même pas à rechercher le fuseau horaire de l'endroit souhaité.

49voto

p01nd3xt3r Points 340

Quel que soit le fuseau horaire GMT dans lequel se trouve le serveur, voici un moyen extrêmement simple d'obtenir l'heure et la date pour n'importe quel fuseau horaire. Cela se fait à l'aide de la fonction time() y gmdate() fonctions. Le site gmdate() nous donne normalement le temps GMT, mais en faisant un tour avec la fonction time() nous pouvons obtenir GMT+N ou GMT-N, ce qui signifie que nous pouvons obtenir l'heure pour n'importe quel fuseau horaire GMT.

Par exemple, si vous devez obtenir l'heure pour GMT+5, vous pouvez procéder comme suit

<?php 
  $offset=5*60*60; //converting 5 hours to seconds.
  $dateFormat="d-m-Y H:i";
  $timeNdate=gmdate($dateFormat, time()+$offset);
?>

Maintenant, si vous devez obtenir l'heure de GMT-5, vous pouvez simplement soustraire le décalage de l'heure de l'horloge. time() au lieu de l'ajouter, comme dans l'exemple suivant où nous obtenons l'heure de GMT-4

<?php 
  $offset=4*60*60; //converting 4 hours to seconds.
  $dateFormat="d-m-Y H:i"; //set the date format
  $timeNdate=gmdate($dateFormat, time()-$offset); //get GMT date - 4
?>

4voto

Alistair Burns Points 41

Il est important de noter que si vous utilisez date('Z') pour convertir une date qui est stockée dans une base de données, vous devez donner à la date l'horodatage comme deuxième argument, sinon votre résultat ne sera pas précis.

par exemple

Au Royaume-Uni, parfois la date('Z') donnera 3600, parfois elle donnera 0.

echo date('Z', strtotime('2012-01-01'));

Donne 0

echo date('Z', strtotime('2012-07-01'));

Donne 3600

Ainsi, l'utilisation de strtotime($dbDateValue) - date('Z') peut être erronée.

Utilisez plutôt :

$dbDateTimestamp = strtotime($dbDateValue); // where $dbDateValue something like 2012-01-01 22:34:00

$utcTimestamp = strtotime($dbDateTimestamp) - date('Z', $dbDateTimestamp);

Cela dépend bien sûr du fait que PHP et la base de données soient tous deux réglés sur le même fuseau horaire.

4voto

Ahmad Tahboub Points 50

Voici une liste des fuseaux horaires qui diffèrent de l'heure GMT, j'espère que cela vous sera utile !

echo '<pre>';
$zones_array = array();        
$timestamp = time();         
# to maintain the original timezone, store before
$default_timezone = date_default_timezone_get();
foreach (timezone_identifiers_list() as $key => $zone) {    
    date_default_timezone_set($zone);
    $zones_array[$key]['zone'] = $zone;
    $zones_array[$key]['diff_from_GMT'] = date('P', $timestamp);
}
# to maintain the original timezone, re-set after
date_default_timezone_set($default_timezone);    
print_r($zones_array);

Merci !

1voto

ihtus Points 539

J'ai été inspiré par cette question pour écrire une fonction alternative pour convertir un timestamp en un fuseau horaire nécessaire.

Donc, les étapes de la procédure CORRECTE pour enregistrer, afficher (convertir) le temps :

1) record timestamp with time()
2) If you need to get a different timezone, use:
   2.1) Class based:
       2.1.1) DateTime class + setTimezone
       or
       2.1.2) date_default_timezone_set() and then date()

       2.1.1) is better and more flexible than 2.1.2)

    Function:

      function getLTime_class($ts, $uTZ, $format_str="Y.m.d H:i", $sTZ="America/Toronto"){
        // $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
        // $uTZ - TZ string (ex: 'America/Toronto'); convert timestamp to this TimeZone
        // $sTZ - TZ string (ex: 'America/Toronto'); convert timestamp from this TimeZone
        $TimeZone_server=new DateTimeZone($sTZ);
        $date_obj=new DateTime("@$ts", $TimeZone_server);
        $TimeZone_local=new DateTimeZone($uTZ);
        $date_obj->setTimeZone($TimeZone_local);
        return $date_obj->format($format_str);
      }

    Usage:

     $date_input=$_POST['date_input']; //read from POST
     $ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
     $userTZ='America/Toronto'; //read from user params
     $result=getLTime_class($ts, $userTZ, 'Y-m-d H:i:s');

   2.2) Non-Class based:

Function:

      //this function replaces the function with DateTime class. It's faster. $uTZoffset is integer.
      function getLTime_nonclass($ts, $uTZoffset, $format_str="Y.m.d H:i"){
        // $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
        // $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
        $ts_offset=date('Z',$ts);
        if ($uTZoffset) $add_offset=$ts_offset-date('Z'); //when not UTC
        else $add_offset=0; //when UTC
        return date($format_str,$ts-$ts_offset+$uTZoffset*3600+$add_offset);
      }

    Usage:

     $date_input=$_POST['date_input']; //read from POST
     $ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
     $uTZoffset=-4; //read from user params. $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
     $result=getLTime_nonclass($ts, $uTZoffset, 'Y-m-d H:i:s');

Résultats :

$date_input = 2012-08-17 12:00:00

Server date: summer (2013-08-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-08-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-4               =>  2012-08-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-08-17 16:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-08-17 16:00:00

Server date: winter (2013-02-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-08-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-5               =>  2012-08-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-08-17 16:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-08-17 16:00:00

$date_input = 2012-02-17 12:00:00

Server date: summer (2013-08-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-02-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-4               =>  2012-02-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-02-17 17:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-02-17 17:00:00

Server date: winter (2013-02-26)    
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-02-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-5               =>  2012-02-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-02-17 17:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-02-17 17:00:00 

J'ai décidé d'utiliser getLTime_nonclass en espérant que la conversion soit plus rapide qu'en utilisant des classes. Tout ce que je demande est de confirmer que getLTime_nonclass est un remplacement valide de getLTime_class. N'hésitez pas à exprimer votre opinion. Merci

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X