Existe-t-il un moyen standard pour un serveur Web de déterminer le fuseau horaire d'un utilisateur dans une page Web?
Peut-être à partir d'un en-tête HTTP ou d'une partie de la user-agent
chaîne?
Existe-t-il un moyen standard pour un serveur Web de déterminer le fuseau horaire d'un utilisateur dans une page Web?
Peut-être à partir d'un en-tête HTTP ou d'une partie de la user-agent
chaîne?
Réponses:
-new Date().getTimezoneOffset()/60;
La méthode getTimezoneOffset()
soustraira votre temps de GMT et renverra 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 l'opposé de ce dont vous avez besoin - il calcule le décalage GMT à partir de votre fuseau horaire, et non le décalage de votre fuseau horaire à partir de GMT. Pour résoudre ce problème, multipliez simplement par -1.
Notez également que w3school dit:
La valeur renvoyée n'est pas une constante, en raison de la pratique d'utilisation de l'heure d'été.
>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
La façon la plus populaire (== standard?) De déterminer le fuseau horaire que j'ai vu est de 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 anon, les dates peuvent être affichées en UTC ou GMT ou certains autres.
Je n'essaie pas d'être un aleck intelligent. C'est juste que parfois certains problèmes ont des solutions plus fines en dehors de tout contexte de programmation.
Il n'y a aucun en-tête HTTP qui rapportera 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 de récupérer le fuseau horaire en utilisant JavaScript côté client, puis 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, revenir 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 cela fonctionne bien, même si je ne sais pas s'ils fournissent 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 wrappers dans plusieurs langues Web.
Tout d'abord, comprenez que la détection de fuseau horaire en JavaScript est imparfaite. Vous pouvez obtenir la locale décalage de fuseau horaire pour une date et une heure à l' aide getTimezoneOffset
d'une instance de l' Date
objet, mais ce n'est pas tout à fait identique à une pleine zone de temps IANA comme America/Los_Angeles
.
Certaines options peuvent cependant fonctionner:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tzid);
Le résultat est une chaîne contenant le paramètre de fuseau horaire IANA de l'ordinateur sur lequel le code s'exécute.
Les environnements pris en charge sont répertoriés dans le tableau de compatibilité Intl . Développez la DateTimeFormat
section et examinez la fonction nommée resolvedOptions().timeZone defaults to the host environment
.
Certaines bibliothèques, telles que Luxon, utilisent cette API pour déterminer le fuseau horaire via des fonctions comme luxon.Settings.defaultZoneName
.
Intl
API si elle est disponible, et quand elle n'est pas disponible, ils interrogent la getTimezoneOffset
fonction de l' Date
objet, pour plusieurs points différents dans le temps, en utilisant les résultats pour choisir un fuseau horaire approprié dans un ensemble de données internes.Les deux jsTimezoneDetect et moment de -fuseau horaire ont cette fonctionnalité.
// using jsTimeZoneDetect
var tzid = jstz.determine().name();
// using moment-timezone
var tzid = moment.tz.guess();
Dans les deux cas, le résultat ne peut être considéré que comme une supposition. La supposition peut être correcte dans de nombreux cas, mais pas tous.
De plus, ces bibliothèques doivent être périodiquement mises à jour pour contrer le fait que de nombreuses implémentations JavaScript plus anciennes ne connaissent que la règle d'heure d'été actuelle pour leur fuseau horaire local. Plus de détails à ce sujet ici.
En fin de compte, une meilleure approche consiste à demander à votre utilisateur son fuseau horaire. Fournissez un paramètre qu'ils peuvent modifier. Vous pouvez utiliser l'une des options ci-dessus pour choisir un paramètre par défaut , mais ne rendez pas impossible de s'en écarter dans votre application.
Il y a aussi l'approche complètement différente de ne pas s'appuyer du tout sur le réglage du fuseau horaire de l'ordinateur de l'utilisateur. Au lieu de cela, si vous pouvez recueillir des coordonnées de latitude et de longitude, vous pouvez les résoudre en un fuseau horaire à l'aide de l' une de ces méthodes . Cela fonctionne bien sur les appareils mobiles.
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
Annexe 1: Maintenant, ce projet est situé sur GitHub: https://github.com/pellepim/jstimezonedetect
Voici une manière plus complète.
Un extrait est 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)
Africa/Johannesburg
ou Europe/Istanbul
. Voir le wiki des balises de fuseau horaire .
En utilisant l'approche d'Unkwntech, j'ai écrit une fonction utilisant jQuery et PHP. Ceci est testé et fonctionne!
Sur la page PHP où vous souhaitez avoir le fuseau horaire en tant que variable, ayez cet extrait de code quelque part vers le haut de la page:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
Cela lira la variable de session "time", que nous sommes sur le point de créer.
Sur la même page, dans <head>, vous devez tout d'abord inclure jQuery:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
Toujours dans <head>, sous 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://example.org/timezone.php",
data: 'time='+ visitortimezone,
success: function(){
location.reload();
}
});
}
});
</script>
Vous l'avez peut-être remarqué ou non, mais vous devez modifier l'URL de votre domaine réel.
Une dernière chose. Vous vous demandez probablement ce qu'est le timezone.php. Eh bien, c'est simplement ceci: (créez un nouveau fichier appelé timezone.php et pointez-le avec l'URL ci-dessus)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
Si cela fonctionne correctement, il chargera d'abord la page, exécutera le JavaScript et rechargera la page. Vous pourrez alors lire la variable $ timezone et l'utiliser à votre guise! Il renvoie le décalage de fuseau horaire UTC / GMT actuel (GMT -7) ou le fuseau horaire dans lequel vous vous trouvez.
Pour soumettre le décalage de fuseau horaire en tant qu'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 de similaire pour obtenir le nom réel du fuseau horaire à l'aide moment.tz.guess();
de http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
Je n'ai toujours pas vu de réponse détaillée ici qui indique le fuseau horaire. Vous ne devriez pas avoir besoin de géocoder par adresse IP ou d'utiliser PHP (lol) ou de deviner incorrectement à partir d'un décalage.
Premièrement, un fuseau horaire n'est pas seulement un décalage par rapport à GMT. C'est une zone de terre dans laquelle les règles de temps sont fixées par des normes locales. Certains pays ont l'heure d'été et activeront l'heure d'été à différents moments. 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 utiliser ceci:
>> 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 au format Olsen:
Avec la date
fonction PHP , vous obtiendrez la date et l'heure du serveur sur lequel se trouve le site. La seule façon d'obtenir le temps de l'utilisateur est d'utiliser JavaScript.
Mais je vous suggère de le faire, si votre site nécessite une inscription, alors le meilleur moyen est de demander à l'utilisateur tout en ayant l'inscription comme champ obligatoire. Vous pouvez lister différents fuseaux horaires sur la page d'enregistrement et les enregistrer dans la base de données. Après cela, si l'utilisateur se connecte au site, vous pouvez définir le fuseau horaire par défaut pour cette session selon le fuseau horaire sélectionné par l'utilisateur.
Vous pouvez définir n'importe quel 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 est côté client, nous devons donc utiliser JavaScript pour cela.
Ci-dessous est 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 vaut mieux demander aux utilisateurs si l'inscription est obligatoire dans votre projet.
N'utilisez pas l'adresse IP pour déterminer définitivement l'emplacement (et donc le fuseau horaire) - c'est parce qu'avec le NAT, les proxys (de plus en plus populaires) et les VPN, les adresses IP ne reflètent pas nécessairement de manière réaliste l'emplacement réel de l'utilisateur, mais l'emplacement auquel le les serveurs implémentant ces protocoles résident.
Similaire à la façon dont les indicatifs régionaux américains ne sont plus utiles pour localiser un utilisateur de téléphone, étant donné la popularité de la portabilité des numéros.
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 ajuster / corriger.
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;
}
Fournissez simplement vos heures au format d'horodatage Unix à 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 affichera toujours les heures correctement en fonction du fuseau horaire que la personne a défini sur l'horloge de son ordinateur. Il n'est pas nécessaire de demander quoi que ce soit à personne et de l'enregistrer dans des endroits, Dieu merci!
Facile, utilisez simplement la getTimezoneOffset
fonction JavaScript comme ceci:
-new Date().getTimezoneOffset()/60;
La magie semble être
visitortime.getTimezoneOffset()
C'est cool, je ne savais pas ça. Cela fonctionne-t-il dans Internet Explorer, etc.? De là, vous devriez pouvoir utiliser JavaScript pour Ajax, définir des cookies, peu importe. J'irais probablement dans la voie des cookies moi-même.
Vous devrez cependant autoriser l'utilisateur à le modifier. Nous avons essayé d'utiliser la géolocalisation (via maxmind) pour le faire il y a un certain temps, et cela était assez souvent incorrect - suffisamment pour que cela ne vaille pas la peine, alors nous laissons simplement l'utilisateur le définir dans son profil et afficher un avis aux utilisateurs qui n'ont pas encore défini le leur.
Voici un article (avec le code source) qui explique comment déterminer et utiliser l'heure localisée dans une application ASP.NET (VB.NET, C #):
En bref, l'approche décrite repose sur la getTimezoneOffset
fonction JavaScript , qui renvoie la valeur qui est 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 fais un lien vers l'article), mais le code fourni le rend vraiment facile à utiliser. Je soupçonne que vous pouvez convertir la logique en PHP et dans d'autres langages (tant que vous comprenez ASP.NET).
Si vous utilisez OpenID pour l'authentification, l' extension d'enregistrement simple résoudrait le problème pour les utilisateurs authentifiés (vous devrez convertir de tz en numérique).
Une autre option consisterait à déduire le fuseau horaire de la préférence de pays de l'agent utilisateur. C'est une méthode quelque peu grossière (ne fonctionnera pas pour en-US), mais fait une bonne approximation.
C'est simple avec JavaScript et PHP:
Même si l'utilisateur peut jouer avec son horloge interne et / ou son fuseau horaire, le meilleur moyen que j'ai trouvé jusqu'à présent pour obtenir le décalage reste new Date().getTimezoneOffset();
. Il est non invasif, ne donne pas de maux de tête et élimine le besoin de s'appuyer sur des tiers.
Disons que j'ai une table,, users
qui contient un champ date_created int(13)
, pour stocker les horodatages Unix;
En supposant un client creates a new account
, les données sont reçues par post
, et je dois insert/update
le date_created column
avec l'horodatage Unix du client, pas celui du serveur.
Étant donné que 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 serveur supplémentaire n'apparaît non plus.
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 en tzo
tant que $_POST['tzo']
;
$ts = new DateTime('now', new DateTimeZone($_POST['tzo']);
$user_time = $ts->format("F j, Y, g:i a");//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
.
Lors de la récupération de la date_created, vous pouvez convertir l'horodatage comme suit:
$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever
Maintenant, cet exemple peut répondre à vos besoins, quand il s'agit d'insérer un first
horodatage ... Lorsqu'il s'agit d'un horodatage ou d'une table supplémentaire, vous pouvez envisager d'insérer la valeur tzo dans la table des utilisateurs pour référence future, ou de la définir en session ou en cookie.
PS MAIS que faire si l'utilisateur voyage et change de fuseau horaire. Se connecte à GMT + 4, se déplace rapidement vers GMT-1 et se reconnecte. La dernière connexion serait dans le futur.
Je pense ... nous pensons trop.
Vous pouvez le faire sur le client avec le fuseau horaire et envoyer la valeur au serveur; exemple d'utilisation:
> moment.tz.guess()
"America/Asuncion"
Obtenir un nom de fuseau horaire valide pour la base de données TZ en PHP est un processus en deux étapes:
Avec JavaScript, obtenez un décalage de fuseau horaire en quelques minutes getTimezoneOffset
. Ce décalage sera positif si le fuseau horaire local est derrière UTC et négatif s'il est devant. 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 ce décalage à PHP.
En PHP, convertissez 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;</code></pre>
J'ai écrit un article de blog à ce sujet: Comment détecter le fuseau horaire de l'utilisateur en PHP . Il contient également une démo.
Intl.DateTimeFormat().resolvedOptions().timeZone
et à l'envoyer au serveur Web. Ref: stackoverflow.com/questions/9772955/…
Un moyen simple de le faire est d'utiliser:
new Date().getTimezoneOffset();
Une option possible consiste à utiliser le Date
champ d'en-tête, qui est défini dans la RFC 7231 et est censé inclure le fuseau horaire. Bien sûr, il n'est pas garanti que la valeur soit vraiment le fuseau horaire du client, mais cela peut être un point de départ pratique.
Voici comment je le fais. Cela définira le fuseau horaire par défaut de PHP sur le fuseau horaire local de l'utilisateur. Collez simplement ce qui suit en haut 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
?>