web-dev-qa-db-fra.com

Comment obtenir le temps moyen de Greenwich en PHP?

J'ai un serveur qui est défini sur EST, et tous les enregistrements de la base de données sont définis sur EST. Je voudrais savoir comment le régler sur GMT. Je souhaite proposer une option de fuseau horaire à mes utilisateurs.

44
drikoda

Quel que soit le fuseau horaire GMT du serveur, voici un moyen extrêmement simple d'obtenir l'heure et la date pour n'importe quel fuseau horaire. Cela se fait avec les fonctions time() et gmdate(). La fonction gmdate() nous donne normalement l'heure 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 GMT fuseau horaire.

Par exemple, si vous devez obtenir l'heure pour GMT + 5, vous pouvez le faire 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 pour GMT-5, vous pouvez simplement soustraire l'offset de la time() au lieu de l'ajouter, comme dans l'exemple suivant où nous obtenons l'heure pour 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
?>
48
p01nd3xt3r

Je voudrais fortement suggérer d'éviter de jouer avec les horodatages UNIX pour le faire ressembler à un fuseau horaire différent. C'est une leçon que j'ai apprise à la dure, bien trop de fois.

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

L'exemple en or qui me bourrait chaque année depuis trop longtemps était celui de l'heure d'été. L'heure d'été signifie qu'il existe des "heures d'horloge" qui n'existent pas dans certaines parties du monde. Par exemple, dans la plupart des régions des États-Unis, il n'y avait pas d'heure à 2 h 01 le 2 avril 2006.

Assez de diatribes quasi-intelligibles cependant. Mon conseil est de stocker vos dates dans la base de données sous forme d'horodatages, puis ...

  • Si vous avez besoin de l'heure locale sur le serveur, utilisez date()
  • Si vous devez obtenir GMT, utilisez alors gmdate()
  • Si vous devez obtenir un fuseau horaire différent, utilisez date_default_timezone_set() puis 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

Cela gardera vos valeurs propres (vous n'avez pas à vous soucier d'ajouter des décalages, puis de les soustraire avant d'enregistrer), cela respectera toutes les règles de l'heure d'été, et vous n'aurez même pas à rechercher le fuseau horaire de l'endroit tu veux.

69
nickf

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 que vous donnez à 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

Donc, en utilisant uniquement strtotime ($ dbDateValue) - la 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);

Bien sûr, cela repose sur PHP et la base de données étant tous deux définis sur le même fuseau horaire.

4
Alistair Burns

Voici une liste des fuseaux horaires différents de 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!

4
Ahmad Tahboub

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

Ainsi, les étapes de la procédure CORRECT 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'obtenir getLTime_nonclass dans l'espoir de rendre la conversion plus rapide que d'utiliser des classes. Tout ce que je demande, c'est de confirmer que getLTime_nonclass est un remplacement valide pour getLTime_class. N'hésitez pas à exprimer votre opinion. Merci

1
ihtus

Il y a beaucoup de temps quand il faut enregistrer le temps dans la base de données en GMT + 0, mais la fonction time () renverra l'heure du serveur. Sa résolution possible par la fonction suivante:

/**
     * Converts a local Unix timestamp to GMT
     *
     * @param   int Unix timestamp
     * @return  int
     */
    function local_to_gmt($time = '')
    {
        if ($time === '')
        {
            $time = time();
        }

        return mktime(
            gmdate('G', $time),
            gmdate('i', $time),
            gmdate('s', $time),
            gmdate('n', $time),
            gmdate('j', $time),
            gmdate('Y', $time)
        );
    }
0
realmag777