Déterminer la fuseau horaire d'un utilisateur

Existe-t-il un moyen standard pour qu'un serveur Web puisse déterminer le fuseau horaire d'un utilisateur dans une page Web? Peut-être d'un en-tête HTTP ou d'une partie de la chaîne user-agent?

-new Date().getTimezoneOffset()/60; 

getTimezoneOffset() soustrait votre temps de GMT et renvoie le nombre de minutes. Donc, si vous vivez en GMT-8, il retournera 480. Pour mettre cela en heures, divisez par 60. Notez également que le signe est le contraire de ce dont vous avez besoin – il calcule le décalage GMT de votre fuseau horaire, pas votre Décalage du fuseau horaire de GMT. Pour résoudre ce problème, multipliez simplement par -1.

modifier

Notez également que w3school dit:

La valeur retournée n'est pas une constante, en raison de la pratique de l'utilisation de l'heure d'été.

La manière la plus populaire (== standard?) De déterminer le fuseau horaire que j'ai vus est simplement demander aux utilisateurs eux-mêmes. Si votre site Web nécessite un abonnement, cela pourrait être enregistré dans les données de profil des utilisateurs. Pour les utilisateurs anonymes, les dates peuvent être affichées sous la forme UTC ou GMT ou certaines d'entre elles.

Je n'essaie pas d'être intelligent. C'est seulement que parfois des problèmes ont des solutions plus fines en dehors du contexte de programmation.

Il n'y a pas d'en-têtes HTTP qui rapporteront le fuseau horaire des clients jusqu'à présent, bien qu'il ait été suggéré de l'inclure dans la spécification HTTP.

Si c'était moi, j'essaierais probablement d'aller chercher le fuseau horaire avec JavaScript et de le soumettre au serveur en utilisant Ajax ou quelque chose.

Javascript est le moyen le plus simple d'obtenir l'heure locale du client. Je suggère d'utiliser un XMLHttpRequest pour renvoyer l'heure locale, et si cela échoue, revenez au fuseau horaire détecté en fonction de leur adresse IP.

En ce qui concerne la géolocalisation, j'ai utilisé MaxMind GeoIP sur plusieurs projets et ça fonctionne bien, mais je ne suis pas sûr de fournir des données de fuseau horaire. C'est un service que vous payez et ils fournissent des mises à jour mensuelles à votre base de données. Ils fournissent des enveloppes dans plusieurs langues Web.

Voici une solution JavaScript robuste pour déterminer le fuseau horaire dans lequel se trouve le navigateur.

 >>> var timezone = jstz.determine(); >>> timezone.name(); "Europe/London" 

https://bitbucket.org/pellepim/jstimezonedetect

Voici un moyen plus complet.

  1. Obtenez le décalage horaire pour l'utilisateur
  2. Testez quelques jours sur les limites de DLS pour déterminer s'ils se trouvent dans une zone qui utilise DLS.

Sauf ci-dessous:

 function TimezoneDetect(){ var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear()); var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt var intMonth; var intHoursUtc; var intHours; var intDaysMultiplyBy; //go through each month to find the lowest offset to account for DST for (intMonth=0;intMonth < 12;intMonth++){ //go to the next month dtDate.setUTCMonth(dtDate.getUTCMonth() + 1); //To ignore daylight saving time look for the lowest offset. //Since, during DST, the clock moves forward, it'll be a bigger number. if (intOffset > (dtDate.getTimezoneOffset() * (-1))){ intOffset = (dtDate.getTimezoneOffset() * (-1)); } } return intOffset; } 

Obtenir TZ et DST de JS (via Way Back Machine)

En utilisant l'approche de Unkwntech, j'ai écrit une fonction en utilisant jQuery et PHP. Ceci est testé et fonctionne!

Sur la page PHP où vous voulez avoir le fuseau horaire en tant que variable, utilisez cet extrait de code quelque part près du haut de la page:

 <?php session_start(); $timezone = $_SESSION['time']; ?> 

Cela lira la variable de session "time", que nous allons maintenant créer.

Sur la même page, dans le, vous devez d'abord inclure jQuery:

 <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script> 

Aussi dans le, sous le jQuery, collez ceci:

 <script type="text/javascript"> $(document).ready(function() { if("<?php echo $timezone; ?>".length==0){ var visitortime = new Date(); var visitortimezone = "GMT " + -visitortime.getTimezoneOffset()/60; $.ajax({ type: "GET", url: "http://domain.com/timezone.php", data: 'time='+ visitortimezone, success: function(){ location.reload(); } }); } }); </script> 

Vous pouvez ou non avoir remarqué, mais vous devez modifier l'url dans votre domaine actuel.

Une dernière chose. Vous vous demandez peut-être ce que c'est que heck timezone.php. Eh bien, c'est simplement ceci: (créez un nouveau fichier appelé timezone.php et indiquez -le avec l'URL ci-dessus)

 <?php session_start(); $_SESSION['time'] = $_GET['time']; ?> 

Si cela fonctionne correctement, il va d'abord charger la page, exécuter JavaScript et recharger la page. Vous pourrez ensuite lire la variable timezone et l'utiliser à votre convenance! Il renvoie le décalage horaire GMT / GMT actuel (GMT -7) ou n'importe quel fuseau horaire dans lequel vous vous trouvez.

Je n'ai toujours pas vu une réponse détaillée ici qui obtient le fuseau horaire. Vous ne devriez pas nécessairement géocoder par adresse IP ou utiliser PHP (lol) ou deviner incorrectement à partir d'un décalage.

Tout d'abord, un fuseau horaire n'est pas seulement un décalage de GMT. C'est un domaine où les règles de temps sont fixées par les normes locales. Certains pays ont des économies de lumière du jour et allumeront l'heure d'été à des moments différents. Il est généralement important d'obtenir la zone réelle, pas seulement le décalage actuel.

Si vous avez l'intention de stocker ce fuseau horaire, par exemple dans les préférences de l'utilisateur, vous voulez la zone et pas seulement le décalage. Pour les conversions en temps réel, cela n'aura pas beaucoup d'importance.

Maintenant, pour obtenir le fuseau horaire avec javascript, vous pouvez l'utiliser:

 >> new Date().toTimeString(); "15:46:04 GMT+1200 (New Zealand Standard Time)" //Use some regular expression to extract the time. 

Cependant, j'ai trouvé plus facile d'utiliser simplement ce plugin robuste qui renvoie le fuseau horaire formaté Olsen:

https://github.com/scottwater/jquery.detect_timezone

Pour envoyer le décalage du fuseau horaire sous la forme d'un en-tête HTTP sur les requêtes AJAX avec jQuery

 $.ajaxSetup({ beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60); } }); 

Vous pouvez également faire quelque chose d'similaire pour obtenir le nom du fuseau horaire actuel en utilisant moment.tz.guess(); À partir de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

Facile, utilisez simplement la fonction JavaScript getTimezoneOffset comme getTimezoneOffset :

 -new Date().getTimezoneOffset()/60; 

Avec la fonction de date PHP, vous obtiendrez l'heure de la date du serveur sur lequel se trouve le site. La seule façon d'obtenir l'heure de l'utilisateur est d'utiliser JavaScript.

Mais je vous le suggère, si votre site nécessite l'inscription, la meilleure façon est de demander à l'utilisateur de l'inscrire comme champ obligatoire. Vous pouvez répertorier différents fuseaux horaires dans la page de registre et l'enregistrer dans la base de données. Après cela, si vous vous connectez au site, vous pouvez définir un fuseau horaire par défaut pour cette session selon le fuseau horaire sélectionné par les utilisateurs. Vous pouvez définir un fuseau horaire spécifique à l'aide de la fonction PHP date_default_timezone_set . Cela définit le fuseau horaire spécifié pour les utilisateurs.

Fondamentalement, le fuseau horaire des utilisateurs va au côté du client, nous devons donc utiliser JavaScript pour cela.

Voici le script pour obtenir le fuseau horaire des utilisateurs en utilisant PHP et JavaScript.

 <?php #http://www.php.net/manual/en/timezones.php List of Time Zones function showclienttime() { if(!isset($_COOKIE['GMT_bias'])) { ?> <script type="text/javascript"> var Cookies = {}; Cookies.create = function (name, value, days) { if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); var expires = "; expires=" + date.toGMTString(); } else { var expires = ""; } document.cookie = name + "=" + value + expires + "; path=/"; this[name] = value; } var now = new Date(); Cookies.create("GMT_bias",now.getTimezoneOffset(),1); window.location = "<?php echo $_SERVER['PHP_SELF'];?>"; </script> <?php } else { $fct_clientbias = $_COOKIE['GMT_bias']; } $fct_servertimedata = gettimeofday(); $fct_servertime = $fct_servertimedata['sec']; $fct_serverbias = $fct_servertimedata['minuteswest']; $fct_totalbias = $fct_serverbias – $fct_clientbias; $fct_totalbias = $fct_totalbias * 60; $fct_clienttimestamp = $fct_servertime + $fct_totalbias; $fct_time = time(); $fct_year = strftime("%Y", $fct_clienttimestamp); $fct_month = strftime("%B", $fct_clienttimestamp); $fct_day = strftime("%d", $fct_clienttimestamp); $fct_hour = strftime("%I", $fct_clienttimestamp); $fct_minute = strftime("%M", $fct_clienttimestamp); $fct_second = strftime("%S", $fct_clienttimestamp); $fct_am_pm = strftime("%p", $fct_clienttimestamp); echo $fct_day.", ".$fct_month." ".$fct_year." ( ".$fct_hour.":".$fct_minute.":".$fct_second." ".$fct_am_pm." )"; } showclienttime(); ?> 

Mais selon mon point de vue, il est préférable de demander aux utilisateurs si l'inscription est obligatoire dans votre projet.

Quiconque connaît des services qui correspondent à la propriété intellectuelle à l'emplacement géographique

Eh bien, chanceux pour vous, cette réponse peut être trouvée sur notre propre site Web stackoverflow: comment obtenir le pays selon une certaine IP?

Spoiler: http://www.hostip.info/use.html

Javascript:

 function maketimus(timestampz) { var linktime = new Date(timestampz * 1000); var linkday = linktime.getDate(); var freakingmonths=new Array(); freakingmonths[0]="jan"; freakingmonths[1]="feb"; freakingmonths[2]="mar"; freakingmonths[3]="apr"; freakingmonths[4]="may"; freakingmonths[5]="jun"; freakingmonths[6]="jul"; freakingmonths[7]="aug"; freakingmonths[8]="sep"; freakingmonths[9]="oct"; freakingmonths[10]="nov"; freakingmonths[11]="dec"; var linkmonthnum = linktime.getMonth(); var linkmonth = freakingmonths[linkmonthnum]; var linkyear = linktime.getFullYear(); var linkhour = linktime.getHours(); var linkminute = linktime.getMinutes(); if (linkminute < 10) { linkminute = "0" + linkminute; } var fomratedtime = linkday + linkmonth + linkyear + " " + linkhour + ":" + linkminute + "h"; return fomratedtime; } 

Il suffit de fournir votre temps au format UNIX Timestamp à cette fonction, javascript connaît déjà le fuseau horaire de l'utilisateur.

comme ça:

Php:

 echo '<script type="text/javascript"> var eltimio = maketimus('.$unix_timestamp_ofshiz.'); document.write(eltimio); </script><noscript>pls enable javascript</noscript>'; 

Cela montrera toujours les temps correctement en fonction du fuseau horaire que la personne a mis sur l'horloge de son ordinateur, pas besoin de demander quoi que ce soit à personne et de l'enregistrer dans des endroits, merci à Dieu!

N'utilisez pas l'adresse IP pour déterminer définitivement l'emplacement (et le fuseau horaire hense) – c'est parce qu'avec NAT, Proxies (de plus en plus populaire) et les VPN, les adresses IP ne reflètent pas nécessairement réellement l'emplacement réel de l'utilisateur, mais l'emplacement où les serveurs La mise en œuvre de ces protocoles résident.

Semblable à la façon dont les codes de zone ne sont plus utiles pour localiser un utilisateur de téléphone, compte tenu de la popularité de Number Portability.

L'adresse IP et les autres techniques indiquées ci-dessus sont utiles pour suggérer une valeur par défaut que l'utilisateur peut régler / corriger.

La magie semble être dans

 visitortime.getTimezoneOffset() 

C'est cool, je ne le savais pas. Est-ce que cela fonctionne dans IE, etc.? De là, vous devriez pouvoir utiliser JS dans ajax, configurer des cookies, peu importe. Je ferais probablement la route des cookies moi-même.

Vous devrez toutefois permettre à l'utilisateur de le modifier. Nous avons essayé d'utiliser la géolocalisation (via maxmind) pour le faire il y a quelque temps, et il était faux assez souvent – assez pour que cela ne vaut pas la peine, alors on laisse l'utilisateur le définir dans son profil et montre un avis aux utilisateurs qui N'ont pas encore réglé leur cas.

Une façon simple de le faire est d'utiliser:

 new Date().getTimezoneOffset(); 

Si vous utilisez OpenID pour l'authentification, Simple Registration Extension résoudrait le problème pour les utilisateurs authentifiés (vous devrez convertir de tz en numériques).

Une autre option serait d'inférer le fuseau horaire à partir de la préférence de pays de l'agent de l'utilisateur. C'est une méthode un peu grossière (ne fonctionnera pas pour les États-Unis), mais constitue une bonne approximation.

Voici un article (avec code source) qui explique comment déterminer et utiliser le temps localisé dans une application ASP.NET (VB.NET, C #):

C'est à propos du temps

En bref, l'approche décrite repose sur la fonction JavaScript getTimezoneOffset , qui renvoie la valeur enregistrée dans le cookie de session et utilisée par code-behind pour ajuster les valeurs de temps entre GMT et l'heure locale. La bonne chose est que l'utilisateur n'a pas besoin de spécifier le fuseau horaire (le code le fait automatiquement). Il y a plus d'implication (c'est pourquoi je lierai l'article), mais le code est très facile à utiliser. Je soupçonne que vous pouvez convertir la logique en PHP et dans d'autres langues (aussi longtemps que vous comprenez ASP.NET).

Simple avec JS et PHP :

Même si l'utilisateur peut se contenter de son horloge interne et / ou de la fuseau horaire, la meilleure façon de trouver jusqu'à présent, pour obtenir le décalage, reste la new Date().getTimezoneOffset(); . Il n'est pas invasif, ne donne pas de mal à la tête et élimine la nécessité de compter sur des tiers.

Disons que j'ai des users table qui contiennent un champ date_created int(13) , pour stocker des horodatages Unix;

En supposant qu'un client creates a new account , les données sont reçues par post et j'ai besoin d' insert/update la date_created column avec l'horodatage Unix du client, et non le serveur.

Étant donné que le timezoneOffset est nécessaire au moment de l'insertion / mise à jour, il est transmis en tant qu'élément $ _POST supplémentaire lorsque le client soumet le formulaire, éliminant ainsi la nécessité de le stocker dans des sessions et / ou des cookies, et aucun autre serveur ne peut être utilisé.

 var off = (-new Date().getTimezoneOffset()/60).toString();//note the '-' in front which makes it return positive for negative offsets and negative for positive offsets var tzo = off == '0' ? 'GMT' : off.indexOf('-') > -1 ? 'GMT'+off : 'GMT+'+off; 

Dites que le serveur reçoit tzo comme $_POST['tzo'] ;

 $ts = new DateTime('now', new DateTimeZone($_POST['tzo']); $user_time = $ts->format("F j, Y, g:ia");//will return the users current time in readable format, regardless of whether date_default_timezone() is set or not. $user_timestamp = strtotime($user_time); 

Insérer / mettre à jour date_created=$user_timestamp .

Lorsque vous récupérez la date_created, vous pouvez convertir l'horodatage comme suit:

 $date_created = //get from db $created = date("F j, Y, g:ia",$date_created);//return it to the user or whatever 

Maintenant, cet exemple peut correspondre à ses besoins, quand il s'agit d'insérer un first timestamp … Lorsqu'il s'agit d'un timestamp supplémentaire ou d'une table, vous pouvez envisager d'insérer la valeur tzo dans la table des utilisateurs pour une référence ultérieure ou un paramètre Comme session ou comme cookie.

PS, mais que faire si l'utilisateur voyage et change les fuseaux horaires. Connectez-vous à GMT + 4, voyage rapidement vers GMT-1 et se connecte à nouveau. La dernière connexion serait à l'avenir.

Je pense … nous pensons trop.

Essayez ce code php

 <?php $ip = $_SERVER['REMOTE_ADDR']; $json = file_get_contents("http://api.easyjquery.com/ips/?ip=".$ip."&full=true"); $json = json_decode($json,true); $timezone = $json['LocalTimeZone']; ?> 

Une option possible est d'utiliser le champ d'en-tête Date , qui est défini dans RFC 7231 et devrait inclure le fuseau horaire. Bien sûr, il n'est pas garanti que la valeur est vraiment le fuseau horaire du client, mais ce peut être un point de départ pratique.

Voici comment je le fais. Cela définira le fuseau horaire par défaut de PHP à la fuseau horaire local de l'utilisateur. Il suffit de coller ce qui suit au sommet de toutes vos pages:

 <?php session_start(); if(!isset($_SESSION['timezone'])) { if(!isset($_REQUEST['offset'])) { ?> <script> var d = new Date() var offset= -d.getTimezoneOffset()/60; location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?offset="+offset; </script> <?php } else { $zonelist = array('Kwajalein' => -12.00, 'Pacific/Midway' => -11.00, 'Pacific/Honolulu' => -10.00, 'America/Anchorage' => -9.00, 'America/Los_Angeles' => -8.00, 'America/Denver' => -7.00, 'America/Tegucigalpa' => -6.00, 'America/New_York' => -5.00, 'America/Caracas' => -4.30, 'America/Halifax' => -4.00, 'America/St_Johns' => -3.30, 'America/Argentina/Buenos_Aires' => -3.00, 'America/Sao_Paulo' => -3.00, 'Atlantic/South_Georgia' => -2.00, 'Atlantic/Azores' => -1.00, 'Europe/Dublin' => 0, 'Europe/Belgrade' => 1.00, 'Europe/Minsk' => 2.00, 'Asia/Kuwait' => 3.00, 'Asia/Tehran' => 3.30, 'Asia/Muscat' => 4.00, 'Asia/Yekaterinburg' => 5.00, 'Asia/Kolkata' => 5.30, 'Asia/Katmandu' => 5.45, 'Asia/Dhaka' => 6.00, 'Asia/Rangoon' => 6.30, 'Asia/Krasnoyarsk' => 7.00, 'Asia/Brunei' => 8.00, 'Asia/Seoul' => 9.00, 'Australia/Darwin' => 9.30, 'Australia/Canberra' => 10.00, 'Asia/Magadan' => 11.00, 'Pacific/Fiji' => 12.00, 'Pacific/Tongatapu' => 13.00); $index = array_keys($zonelist, $_REQUEST['offset']); $_SESSION['timezone'] = $index[0]; } } date_default_timezone_set($_SESSION['timezone']); //rest of your code goes here ?> 

Vous pourriez le faire sur un client avec moment-timezone et envoyer la valeur au serveur; Utilisation de l'échantillon:

 > moment.tz.guess() "America/Asuncion" 

Obtenir un nom de base de données TZ valide en PHP est un processus en deux étapes:

1) Avec Javascript, obtenez un décalage horaire en minutes via getTimezoneOffset . Ce décalage sera positif si le fuseau horaire local est derrière UTC et négatif s'il est en avance. Vous devez donc ajouter un signe opposé au décalage.

 var timezone_offset_minutes = new Date().getTimezoneOffset(); timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes; 

Passez cet offset à PHP.

2) En PHP, convertir ce décalage en un nom de fuseau horaire valide avec la fonction timezone_name_from_abbr .

 // Just an example. $timezone_offset_minutes = -360; // $_GET['timezone_offset_minutes'] // Convert minutes to seconds $timezone_name = timezone_name_from_abbr("", $timezone_offset_minutes*60, false); // America/Chicago echo $timezone_name; 

J'ai écrit un article sur le blog: http://usefulangle.com/post/31/detect-user-browser-timezone-name-in-php Il contient aussi une démo.