Question

Existe-t-il un moyen standard permettant à 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 du user-agent chaîne?

Pas de solution correcte

Autres conseils

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

La méthode getTimezoneOffset() soustraira votre temps de GMT et renverra le nombre de minutes.Donc, si vous habitez en GMT-8, il renverra 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 de GMT par rapport à votre fuseau horaire, et non le décalage de votre fuseau horaire par rapport à GMT.Pour résoudre ce problème, multipliez simplement par -1.

Notez également que w3école 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 vu est simplement demander aux utilisateurs eux-mêmes. Si votre site Web nécessite un abonnement, cela peut être enregistré dans les données de profil des utilisateurs.Pour les utilisateurs anonymes, les dates peuvent être affichées au format UTC ou GMT ou autre.

Je n'essaie pas d'être un malin.C'est juste que parfois certains problèmes ont des solutions plus fines en dehors de tout contexte de programmation.

Jusqu'à présent, aucun en-tête HTTP ne signalera le fuseau horaire du client, 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 du genre.

JavaScript est le moyen le plus simple d'obtenir l'heure locale du client.Je suggérerais d'utiliser un XMLHttpRequête 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 GéoIP 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 pour lequel vous payez et ils fournissent des mises à jour mensuelles de votre base de données.Ils fournissent des wrappers dans plusieurs langages 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 une manière plus complète.

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

Un extrait 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 à partir de JS (via Way Back Machine)

Tout d’abord, comprenez que la détection du fuseau horaire en JavaScript est imparfaite.Vous pouvez obtenir le local décalage horaire pour une date et une heure particulières en utilisant getTimezoneOffset sur une instance du Date objet, mais ce n'est pas tout à fait la même chose qu'un objet complet Fuseau horaire de l'IANA comme America/Los_Angeles.

Certaines options peuvent cependant fonctionner :

  • La plupart des navigateurs modernes prennent en charge les fuseaux horaires IANA dans leur implémentation du API d'internationalisation ECMAScript, vous pouvez donc faire ceci :

    const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
    

    Le résultat est une chaîne contenant le paramètre de fuseau horaire IANA de l’ordinateur sur lequel le code est exécuté.

    Les environnements pris en charge sont répertoriés dans le tableau de compatibilité International.Élargir la DateTimeFormat section et regardez la fonctionnalité nommée resolvedOptions().timeZone defaults to the host environment.

    • Certaines bibliothèques, comme Luxon utilisez cette API pour déterminer le fuseau horaire grâce à des fonctions telles que luxon.Settings.defaultZoneName.
  • Si vous devez prendre en charge un ensemble plus large d'environnements, tels que des navigateurs Web plus anciens, vous pouvez utiliser une bibliothèque pour créer un supposition éclairée au fuseau horaire.Ils fonctionnent en essayant d'abord le Intl API si elle est disponible, et lorsqu'elle n'est pas disponible, ils interrogent le getTimezoneOffset fonction du Date objet, pour plusieurs moments différents, en utilisant les résultats pour choisir un fuseau horaire approprié à partir d'un ensemble de données interne.

    Les deux jsTimezoneDetect et moment-fuseau horaire avoir 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.Cette supposition peut être correcte dans de nombreux cas, mais pas dans tous.

    De plus, ces bibliothèques doivent être périodiquement mises à jour pour contrecarrer le fait que de nombreuses implémentations JavaScript plus anciennes ne connaissent que les actuel règle de l’heure d’été 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 défaut paramètre, mais ne faites pas en sorte qu'il soit impossible de s'en écarter dans votre application.

Il y a aussi l'approche totalement différente de pas en s'appuyant sur le paramètre de fuseau horaire de l'ordinateur de l'utilisateur.Au lieu de cela, si vous pouvez rassembler les coordonnées de latitude et de longitude, vous pouvez les résoudre en un fuseau horaire en utilisant une de ces méthodes.Cela fonctionne bien sur les appareils mobiles.

En utilisant l'approche d'Unkwntech, j'ai écrit une fonction en utilisant jQuery et PHP.C'est testé et ça marche !

Sur la page PHP où vous souhaitez avoir le fuseau horaire comme variable, placez cet extrait de code quelque part en 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 le <head>, vous devez tout d'abord inclure jQuery :

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

Également dans le <head>, 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://example.org/timezone.php",
                data: 'time='+ visitortimezone,
                success: function(){
                    location.reload();
                }
            });
        }
    });
</script>

Vous l'avez peut-être remarqué ou non, mais vous devez remplacer l'URL par votre domaine actuel.

Une dernière chose.Vous vous demandez probablement ce qu'est ce fichier timezone.php.Eh bien, c'est simplement ceci :(créez un nouveau fichier appelé fuseau horaire.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 horaire UTC/GMT actuel (GMT -7) ou le fuseau horaire dans lequel vous vous trouvez.

Je n'ai toujours pas vu ici de réponse détaillée concernant le fuseau horaire.Vous ne devriez pas avoir besoin de géocoder par adresse IP, d'utiliser PHP (lol) ou de deviner de manière incorrecte à partir d'un décalage.

Premièrement, un fuseau horaire n’est pas simplement un décalage par rapport à GMT.Il s'agit d'un territoire dans lequel les règles temporelles sont fixées par des normes locales.Certains pays passent à l'heure d'été et activent l'heure d'été à des heures différentes.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 utilisateur, vous souhaitez le fuseau 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 :

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

Pour soumettre le décalage 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 en utilisant moment.tz.guess(); depuis http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

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

Mais je vous suggère de le faire, si votre site nécessite une inscription, le meilleur moyen est de demander à l'utilisateur d'avoir l'inscription comme champ obligatoire.Vous pouvez répertorier différents fuseaux horaires sur la page d'inscription 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 en fonction du fuseau horaire sélectionné par les utilisateurs.

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 va du côté client, nous devons donc utiliser JavaScript pour cela.

Vous trouverez ci-dessous le script permettant d'obtenir le fuseau horaire des utilisateurs à l'aide de 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.

Facile, utilisez simplement le JavaScript getTimezoneOffset fonctionne comme ceci :

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

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 à qui que ce soit et de le sauvegarder dans des endroits, Dieu merci !

La magie semble être là

visitortime.getTimezoneOffset()

C'est cool, je n'étais pas au courant.Est-ce que cela fonctionne dans Internet Explorer, etc. ?À partir de là, vous devriez pouvoir utiliser JavaScript vers Ajax, définir des cookies, etc.J'emprunterais probablement 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 ce faire il y a quelque temps, et cela se trompait assez souvent - suffisamment pour que cela n'en vaille pas la peine, nous avons donc simplement laissé l'utilisateur le définir dans son profil et afficher un avis aux utilisateurs qui Je n'ai pas encore réglé le leur.

N'utilisez pas l'adresse IP pour déterminer définitivement l'emplacement (et donc le fuseau horaire) : en effet, 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 où l'utilisateur se trouve. les serveurs implémentant ces protocoles résident.

De la même manière, les indicatifs régionaux aux États-Unis ne sont plus utiles pour localiser un utilisateur de téléphone, compte tenu de la popularité de la portabilité des numéros.

L'adresse IP et les autres techniques présentées ci-dessus sont utiles pour suggérer un défaut que l'utilisateur peut ajuster/corriger.

S'il vous arrive d'utiliser ID ouvert pour l'authentification, Extension d'inscription simple résoudrait le problème pour les utilisateurs authentifiés (vous devrez convertir de tz en numérique).

Une autre option serait de déduire le fuseau horaire à partir des préférences nationales de l'agent utilisateur.Il s'agit d'une méthode quelque peu grossière (ne fonctionnera pas pour en-US), mais constitue une bonne approximation.

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#) :

Il est temps

En bref, l'approche décrite s'appuie sur le JavaScript getTimezoneOffset fonction, qui renvoie la valeur enregistrée dans le cookie de session et utilisée par le code-behind pour ajuster les valeurs d'heure entre GMT et l'heure locale.Ce qui est bien, c'est que l'utilisateur n'a pas besoin de spécifier le fuseau horaire (le code le fait automatiquement).Il y a plus de choses à faire (c'est pourquoi je crée 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 (à condition de comprendre ASP.NET).

C'est simple avec JavaScript et PHP :

Même si l'utilisateur peut jouer avec son horloge interne et/ou son fuseau horaire, la meilleure façon que j'ai trouvée jusqu'à présent, pour obtenir le décalage, reste new Date().getTimezoneOffset();.C’est non invasif, ne pose pas de problèmes et élimine le besoin de recourir à des tiers.

Dis que j'ai une table, users, qui contient un champ date_created int(13), pour stocker les horodatages Unix ;

En supposant qu'un client creates a new account, les données sont reçues par post, et j'ai besoin de 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 le besoin de le stocker dans des sessions et/ou des cookies, et aucun serveur supplémentaire n'arrive 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;

Disons 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: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 du date_created, vous pouvez convertir l'horodatage comme ceci :

$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 lorsqu'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 comme session ou comme cookie.

P.S.MAIS que se passe-t-il si l'utilisateur voyage et change de fuseau horaire.Se connecte à GMT+4, se déplace rapidement jusqu'à GMT-1 et se reconnecte.La dernière connexion aurait lieu dans le futur.

Je pense...nous réfléchissons trop.

Vous pourriez le faire sur le client avec moment-fuseau horaire et envoyer la valeur au serveur ;exemple d'utilisation :

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

Un moyen simple de le faire est d'utiliser :

new Date().getTimezoneOffset();

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

  1. Avec JavaScript, obtenez un décalage de fuseau horaire en minutes via getTimezoneOffset.Ce décalage sera positif si le fuseau horaire local est en retard sur 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;
    

    Transmettez ce décalage à PHP.

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

    // 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.

Une option possible consiste à utiliser le Date champ d'en-tête, qui est défini dans RFC7231 et est censé inclure le fuseau horaire.Bien entendu, il n'est pas garanti que la valeur corresponde réellement au fuseau horaire du client, mais cela peut constituer un point de départ pratique.

Voici comment je procède.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
?>

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'];
?>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top