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.
Réponses
Trop de publicités?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 ensuitedate()
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é.
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
?>
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.
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 !
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