Déterminer le fuseau horaire d'un utilisateur

610

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-agentchaîne?

Kevin Dente
la source
6
Demandez à l'utilisateur. Si vous obtenez le fuseau horaire de l'ordinateur de l'utilisateur et qu'il est mal réglé, alors quoi?
Rob Williams
40
Ensuite, l'utilisateur ne s'en soucie probablement pas?
agnoster
2
Voulez-vous dire stackoverflow.com/q/1091372/218196 ?
Felix Kling
2
Malheureusement, les réponses à cette question permettent également le profilage des utilisateurs et le geofencing.
William Entriken
1
Pourquoi avez-vous besoin de connaître le fuseau horaire de l'utilisateur?
Braiam

Réponses:

325
-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é.

JD Isaacks
la source
5
Qu'en est-il des utilisateurs qui utilisent des téléphones portables équipés de navigateurs sans prise en charge Javascript? J'aime la question, l'utilisateur pose des questions sur les en-têtes HTTP, l'agent utilisateur ... existe-t-il un moyen de rendre ce travail côté serveur aussi précis que possible?
Nischal
19
Cela ne fonctionne pas toujours pour DST. Obtenir le décalage de fuseau horaire fait exactement ce qu'il dit. C'est le décalage. Une zone de temps est en fait une zone géographique. Cela ne fonctionnera pas pour l'heure d'été, car vous ne savez pas dans quel hémisphère l'utilisateur réside, ou si son pays a même l'heure d'été. Pourquoi ne pas l'utiliser à la place:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo
20
Je vous prie de différer avec Keyo. La définition de getTimezoneOffset () (selon la norme ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26 ) est "Renvoie la différence entre l'heure locale et l'heure UTC en minutes". - en d'autres termes, il doit tenir compte de l'heure d'été. La documentation de Mozilla indique que «l'heure d'été empêche que cette valeur soit constante même pour un lieu donné».
xgretsch
12
@xgretsch: Il obtient le décalage actuel de l'utilisateur par rapport à GMT. C'est bien si vous présentez une autre heure qui se produit le même jour (sauf si la date actuelle est une date de basculement, où elle pourrait être erronée). Cependant, il existe de nombreux fuseaux horaires qui ont le même décalage par rapport à GMT, et ils peuvent avoir des dates de basculement différentes ou ne pas utiliser l'heure d'été.
Mike Dimmick
13
Une chose à noter ici; certains endroits (comme Terre-Neuve au Canada) ont des fuseaux horaires qui sont décalés d'une demi-heure, donc après avoir divisé par 60 votre réponse peut ne pas être un entier.
Jason Walton
193

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.

Ishmaeel
la source
5
Qu'en est-il lorsqu'un utilisateur télécharge un fichier .ics qui devrait avoir une heure de début spécifique à son emplacement (par exemple 9h-11h à travers le pays)? Ils ne devraient pas avoir à dire quel est leur fuseau horaire.
Marcy Sutton
33
@Ishmaeel: mais les utilisateurs voyagent à l'étranger et ils ne devraient pas avoir besoin de dire leur fuseau horaire chaque fois qu'ils se connectent à partir d'un fuseau horaire non natif
Rajat Gupta
10
Cela ne répond pas à la question, ce qui implique clairement qu'il recherche une solution technologique.
G-Wiz
5
@gWiz OP demande une solution standard. C'est assez standard.
Simon Bergot
4
La meilleure solution serait probablement une combinaison de demander à l'utilisateur (par exemple, fournir une liste déroulante de fuseau horaire en haut d'un rapport), tout en par défaut la sélection déroulante à un fuseau horaire déterminé par GPS lorsque l'utilisateur est sur un mobile périphérique qui fournit des informations de localisation et qui, par défaut, est UTC.
Triynko
133

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.

Mads Kristiansen
la source
16
Étrangement, c'est la seule bonne réponse à la question, qui demande comment le faire côté serveur. Je soupçonne que la raison pour laquelle il existe d'autres réponses avec plus de votes est qu'une fois que vous vous rendez compte que vous devez le faire côté client, vous finissez par utiliser les autres réponses. Mais à mon humble avis, quiconque vote pour une autre réponse devrait également voter pour celle-ci.
TTT
Je crois que la meilleure méthode consiste à utiliser l'emplacement géographique pour trier les fuseaux horaires possibles et, par défaut, choisir le premier qui correspond (proche) au décalage horaire de l'agent utilisateur (JavaScript requis). Même après cela, vous devez fournir un moyen de corriger le fuseau horaire après que même cette méthode sélectionne la mauvaise.
Mikko Rantalainen
@MikkoRantalainen soyez prudent lorsque vous utilisez des proxys, car ils ne s'affichent pas toujours dans les en-têtes.
Matthieu
@Matthieu il existe une meilleure réponse de nos jours: stackoverflow.com/a/11836123/334451
Mikko Rantalainen
2
C'est littéralement la seule réponse qui répondait réellement à la question posée.
lscoughlin
54

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.

pix0r
la source
J'ai voté cette réponse parce que la latitude et la longitude obtenues à partir de bases de données comme GeoIP (qui a une version gratuite disponible à partir de maintenant) peuvent être combinées avec des bases de données qui convertissent une telle coordonnée en un fuseau horaire. Je pense que GeoNames a une dernière telle base de données.
Peter O.
Les versions actuelles (gratuites et payantes) des bases de données / API MaxMind GeoIP fournissent en effet des informations de fuseau horaire (il renvoie "Europe / Londres" pour mon fuseau horaire.) Je ne me souviens pas si l'ancienne version de leur système GeoIP fait de même, mais ça marche très bien maintenant! Les champs MaxMind sont nommés "time_zone", "time_zone_name".
Matthew Slyman
51

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 getTimezoneOffsetd'une instance de l' Dateobjet, 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 DateTimeFormatsection 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.

    • 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 faire une estimation éclairée du fuseau horaire. Ils fonctionnent en essayant d'abord l' IntlAPI si elle est disponible, et quand elle n'est pas disponible, ils interrogent la getTimezoneOffsetfonction de l' Dateobjet, 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.

Matt Johnson-Pint
la source
L'utilisation de l'emplacement géographique de l'utilisateur (c'est-à-dire sa localisation) pour déduire le fuseau horaire est également défectueuse. Les utilisateurs peuvent souhaiter utiliser un fuseau horaire spécifique sur leur appareil qui n'est pas le fuseau horaire local, même s'ils peuvent afficher la même heure (ou non). Par exemple, les voyageurs laissent souvent leurs appareils avec le fuseau horaire réglé sur leur localité habituelle et ne s'attendent pas à voir les dates et les heures utiliser un décalage différent sans en être informés. Je pourrais parler d'expérience personnelle ici… ;-)
RobG
Je ne peux pas dire si tu me traînes Rob. ;) Mais aucune de ces approches n'utilise leurs paramètres régionaux, mais plutôt le paramètre sur l'appareil, donc s'aligne avec votre point. (Seule l'approche alternative mentionnée dans le dernier paragraphe utiliserait l'emplacement actuel.)
Matt Johnson-Pint
Réaction avec une note terminologique: "locale" n'est absolument pas l'emplacement géographique de l'utilisateur. "Paramètres régionaux" est un groupe de paramètres tels que la langue, le format numérique, le calendrier, etc. Par exemple, les paramètres régionaux de_DE spécifient l'allemand comme langue par défaut, l'euro comme devise par défaut, les virgules comme séparateur décimal, les périodes comme séparateur de milliers et le grégorien. comme calendrier. Voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
azernik
49

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

Adam
la source
14
Les réponses de lien uniquement sont déconseillées, car si le lien disparaît, la réponse cesse d'être utile; et parce que sans suivre le lien, les lecteurs ne savent pas s'il donne une bonne réponse. Dans ce cas, vous pouvez préciser qu'il s'agit d'une bibliothèque tierce qui adopte une approche d'identification basée sur une base de données et peut-être expliquer certains des principes de son fonctionnement.
IMSoP
1
Cette! C'est la voie à suivre. Bibliothèque simple, gère correctement l'heure d'été. D'autres réponses sont pleines de WTF et beaucoup ne font pas DST.
Dirbaio
1
Cette bibliothèque est très intelligente. Il fonctionne en interrogeant l'offset actuel sur UTC, puis en ajustant l'heure de l'objet Date JavaScript en ajoutant ou en soustrayant les secondes jusqu'à ce que l'offset change en UTC. En utilisant cette méthode, cette bibliothèque calcule suffisamment de modifications DST pour identifier de manière unique le fuseau horaire. Je pense que la bibliothèque pourrait avoir des performances encore meilleures si elle effectuait une recherche binaire au lieu d'une recherche linéaire. La valeur de retour est une clé d'informations de zone IANA (également appelée base de données de fuseaux horaires Olson).
Mikko Rantalainen
3
Cette bibliothèque n'est plus nécessaire. Les navigateurs modernes prennent en charge l'API Intl, qui renvoie la chaîne de fuseau horaire IANA. Voir cette réponse .
Dan Dascalescu
42

Voici une manière plus complète.

  1. Obtenez le décalage du fuseau horaire pour l'utilisateur
  2. Testez certains jours sur les limites de l'heure d'été pour déterminer si elles se trouvent dans une zone qui utilise l'heure d'été.

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)

Joseph Lust
la source
Cela a fonctionné pour moi! Lisez les commentaires sous le blog pour quelques mises à jour du code.
arlomedia
Cela ne renverra toujours que le décalage standard pour le fuseau horaire, tel que +02: 00. Il ne vous donnera pas suffisamment d'informations pour déterminer le fuseau horaire de l'utilisateur, tel que Africa/Johannesburgou Europe/Istanbul. Voir le wiki des balises de fuseau horaire .
Matt Johnson-Pint
32

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.

Westy92
la source
j'aime ça, mais j'ai peut-être quelque chose qui vérifie la $ _SESSION ['time'] actuelle et ne récupère le javascript que s'il est différent
Christopher Chase
1
Il est probablement plus facile d'utiliser un cookie qu'une session pour le transporter, car le verrouillage et la désérialisation de la session PHP peuvent provoquer des ralentissements dans votre application. Pour une efficacité maximale, vous pouvez copier la valeur dans la session et supprimer le cookie afin qu'il ne soit pas envoyé dans les demandes suivantes.
IMSoP
25

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/

philfreo
la source
1
Cela renvoie uniquement le décalage de fuseau horaire actuel - pas le fuseau horaire . Voir le wiki des balises de fuseau horaire .
Matt Johnson-Pint
Modifié pour inclure des informations sur la procédure à suivre pour le nom du fuseau horaire.
philfreo
24

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:

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

Keyo
la source
22

Avec la datefonction 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.

Sanjay Khatri
la source
22

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.

Jaime G
la source
21

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!

Envis
la source
$ unix_timestamp_ofshiz? Quelque chose manque ici et ne fonctionne pas tout à fait, même si cela semble être une bonne réponse.
20

Facile, utilisez simplement la getTimezoneOffsetfonction JavaScript comme ceci:

-new Date().getTimezoneOffset()/60;
JoeyFur62
la source
1
Il s'agit d'une fonction Javascript, pas d'une fonction PHP.
cincodenada
En outre, il renvoie uniquement le décalage de fuseau horaire actuel - pas le fuseau horaire . Voir le wiki des balises de fuseau horaire .
Matt Johnson-Pint
3
Ceci est juste une copie de la réponse acceptée, pourquoi vous avez même voté dessus.
Rambatino du
19

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.

Orion Edwards
la source
15

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 repose sur la getTimezoneOffsetfonction 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).

Alek Davis
la source
1
Le lien est mort. Je pense que c'est le lien alternatif: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan
1
L'article est également disponible en format PDF ici: app.box.com/shared/bfvvmidtyg
Ivaylo Slavov
La méthode de conversion de l'heure du serveur UTC en heure du client local décrite dans cet article est incorrecte. L'utilisation du décalage client actuel pour ajuster les heures UTC sur le serveur entraînera des heures "locales" incorrectes pendant la moitié de l'année pour les paramètres régionaux client qui respectent l'heure d'été. Considérez ce scénario: un client au Royaume-Uni le 14 janvier 2013 (GMT + 0000 Standard Time) définit une date et une heure du 21 août 2015 à 14h00 (GMT + 0100 Daylight Time). Cela est normalisé sur le serveur au 21 août 2015 à 13h00 UTC. Le jour où cela se produit, le décalage client est 0, donc l'heure renvoyée au client sera le 21 août 2015 à 13h00.
Stephen Blair
Point valable, mais je n'ai pas prétendu qu'il s'agissait d'une solution pare-balles. Si vous avez besoin de mettre en œuvre une solution vraiment urgente, par exemple une application de réservation de billets de train, alors vous devez trouver une solution plus complète (et complexe). Cependant, pour de nombreuses applications, ce ne serait pas un problème. Parce que dans de nombreux cas, nous voulons localiser les valeurs GMT pour la session en cours. Maintenant, si vous avez une application qui doit enregistrer un horodatage pour certains même à l'avenir et qu'elle ne peut pas tolérer le DTS, alors une bonne façon serait de présenter une option pour gagner du temps directement dans GMT. Si vous connaissez une meilleure option, veuillez la partager.
Alek Davis
14

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.

Dmitry Shechtman
la source
13

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,, usersqui 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/updatele date_created columnavec 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 tzotant 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 firsthorodatage ... 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.

homme
la source
13

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"
Tomas Tomecek
la source
5
Le nom de la fonction indique tout sur sa précision ;-)
Legends
De nos jours, moment.js n'est plus recommandé. Il existe actuellement des alternatives beaucoup plus petites ( dayjs , date-fns ). Le moment est énorme .
Dan Dascalescu
11

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

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

Angle utile
la source
1
Je pense qu'un processus plus simple consiste à l'appeler Intl.DateTimeFormat().resolvedOptions().timeZoneet à l'envoyer au serveur Web. Ref: stackoverflow.com/questions/9772955/…
Michael Tsang
8

Une option possible consiste à utiliser le Datechamp 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.

Berislav Lopac
la source
1
Malheureusement, cet en-tête semble être principalement conçu pour les réponses, et non pour les demandes: "Un agent utilisateur PEUT envoyer un champ d'en-tête Date dans une demande, bien qu'il ne le fasse généralement pas sauf s'il est censé transmettre des informations utiles au serveur." Je viens de vérifier et Firefox ne l'envoie pas.
IMSoP
8

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
?>
Dane Iracleous
la source
1
Cela ne tient pas compte des ajustements "d'heure d'été" - un utilisateur à Dublin correspondrait à votre "Europe / Dublin" en hiver, mais à "Europe / Belgrade" en été. Si vous allez utiliser le décalage actuel, tout ce que vous pouvez raisonnablement supposer est ce décalage, pas un identifiant géographique.
IMSoP
8

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'];
?>
pckabeer
la source