J'ai besoin de savoir dans quel fuseau horaire se trouvent actuellement mes utilisateurs en fonction de leur en-tête IP ou http.
J'ai eu beaucoup de réponses à ce sujet, mais je n'ai pas compris ces réponses. Certains ont dit utiliser -new Date().getTimezoneOffset()/60
( à partir d’ici ). Mais qu'est-ce que ça veut dire?
J'ai un date_default_timezone_set("Asia/Calcutta");
à la racine de ma page (index.php). Donc, pour cela, je dois obtenir le fuseau horaire de manière dynamique et le configurer à la place de Asia/Calcutta
.
Pour résumer la réponse de Matt Johnson en termes de code:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.4/jstz.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var tz = jstz.determine(); // Determines the time zone of the browser client
var timezone = tz.name(); //'Asia/Kolhata' for Indian Time.
$.post("url-to-function-that-handles-time-zone", {tz: timezone}, function(data) {
//Preocess the timezone in the controller function and get
//the confirmation value here. On success, refresh the page.
});
});
</script>
Les informations de fuseau horaire du navigateur ne font pas partie de la spécification HTTP. Vous ne pouvez donc pas les obtenir simplement à partir d'un en-tête.
Si vous avez des coordonnées de localisation (à partir d'un GPS de périphérique mobile, par exemple), vous pouvez rechercher le fuseau horaire en utilisant l'une de ces méthodes . Cependant, la géolocalisation par adresse IP n’est pas une bonne solution car, souvent, l’adresse IP est celle d’un FAI ou d’un serveur proxy qui peut se trouver dans un autre fuseau horaire.
Il existe certaines stratégies que vous pouvez utiliser pour détecter le fuseau horaire, telles que l’utilisation de la bibliothèque jsTimeZoneDetect , ce qui est un excellent point de départ, mais suffisamment imparfait pour que vous ne puissiez pas compter uniquement sur cela. Si vous utilisez moment.js, il existe une fonction intégrée dans moment-fuseau appelée moment.tz.guess()
qui fait la même chose.
L'idée d'utiliser la fonction getTimezoneOffset()
de JavaScript est erronée en ce sens que vous n'obtenez pas de fuseau horaire, mais uniquement un décalage pour une date donnée. Voir la section du wiki de la balise TimeZone intitulée "TimeZone! = Offset".
Quel que soit le résultat, vous devez choisir l'une des deux approches suivantes:
OR
Je discute de cela plus en détail (d'un point de vue c #) dans this answer .
Les dépendances:
http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
//Get remote IP
$ip = $_SERVER['REMOTE_ADDR'];
//Open GeoIP database and query our IP
$gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);
$record = geoip_record_by_addr($gi, $ip);
//If we for some reason didnt find data about the IP, default to a preset location.
if(!isset($record)) {
$record = new geoiprecord();
$record->latitude = 59.2;
$record->longitude = 17.8167;
$record->country_code = 'SE';
$record->region = 26;
}
//Calculate the timezone and local time
try {
//Create timezone
$user_timezone = new DateTimeZone(get_time_zone($record->country_code, ($record->region!='') ? $record->region : 0));
//Create local time
$user_localtime = new DateTime("now", $user_timezone);
$user_timezone_offset = $user_localtime->getOffset();
}
//Timezone and/or local time detection failed
catch(Exception $e) {
$user_timezone_offset = 7200;
$user_localtime = new DateTime("now");
}
echo 'User local time: ' . $user_localtime->format('H:i:s') . '<br/>';
echo 'Timezone GMT offset: ' . $user_timezone_offset . '<br/>';
Une solution est de leur demander! Surtout sur les systèmes membres où vous pouvez capturer/enregistrer un utilisateur - donnez-leur un choix à ce moment-là. Simple mais précis.
Cela fonctionne bien ...
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled)
document.cookie = "tzo="+ (- new Date().getTimezoneOffset());
</script>
EOE;
if (!isset($_COOKIE['tzo'])) {
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled) document.reload();
else alert("Cookies must be enabled!");
</script>
EOE;
die();
}
$ts = new DateTime('now', new DateTimeZone('GMT'));
$ts->add(DateInterval::createFromDateString($_COOKIE['tzo'].' minutes'));
Le fuseau horaire n'est pas disponible dans l'en-tête HTTP, mais le pays (abréviation) est dans l'en-tête ACCEPT_LANGUAGE. Ce sera quelque chose comme "en-US" (US est le code du pays). Ceci peut être combiné avec les informations JavaScript pour avoir une bonne idée du fuseau horaire de l'utilisateur.
C'est ce que j'utilise dans JS:
function timezone() {
var now = new Date();
var jano = new Date(now.getFullYear(), 0, 1).getTimezoneOffset()/-60;
var julo = new Date(now.getFullYear(), 6, 1).getTimezoneOffset()/-60;
var tz = Math.min(jano, julo);
if (jano != julo) tz += ((jano < julo) ? 'S' : 'W') + Math.abs(jano - julo);
return tz;
}
Cela renvoie une chaîne du type "-6S1" pour la zone centrale (décalage horaire standard de -6 heures, heure d'été activée en été et ajout d'une heure). J'utilise un cookie pour le rendre disponible à PHP. PHP recherche dans la base de données TZ les zones correspondantes, ainsi que le pays. Pour ici (US, -6S1), il y a 7 zones correspondantes, la première est "America/Chicago".
En passant, il y a 2 zones dans la base de données où DST ajoute autre chose qu'une heure: l'île Lord Howe (10.5W0.5) et Troll Station, Antarctica (0W2).