obtenir le fuseau horaire du client à partir du navigateur


139

Existe-t-il un moyen fiable d'obtenir un fuseau horaire à partir du navigateur client? J'ai vu les liens suivants mais je veux une solution plus robuste.

Détecter automatiquement un fuseau horaire avec JavaScript

Détection de fuseau horaire en JavaScript



8
J'ai écrit jsTimezoneDetect vers lequel vous créez un lien ci-dessus, et mon point de vue sur la situation est qu'il est aussi proche que possible avec du javascript purement croisé (sans géolocalisation ni recherches IP).
Jon Nylander

Réponses:


87

Regardez ce pageloom de référentiel, il est utile

téléchargez jstz.min.js et ajoutez une fonction à votre page html

<script language="javascript">
    function getTimezoneName() {
        timezone = jstz.determine()
        return timezone.name();
    }
</script>

et appelez cette fonction depuis votre tag d'affichage


13
TL; DR Nous pouvons maintenant utiliser Intl.DateTimeFormat().resolvedOptions().timeZone(pas d'IE11) comme suggéré par Wallace.
Code4R7

195

Une demi-décennie plus tard, nous avons un moyen intégré pour cela! Pour les navigateurs modernes, j'utiliserais:

const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);

Cela renvoie une chaîne de fuseau horaire IANA, mais pas le décalage . En savoir plus sur la référence MDN .

Tableau de compatibilité - en mars 2019, fonctionne pour 90% des navigateurs utilisés dans le monde. Ne fonctionne pas sur Internet Explorer .


4
ne fonctionne pas dans Firefox: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek

3
Firefox et IE ne semblent pas prendre en charge la propriété :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Wallace

5
Intl.DateTimeFormat().resolvedOptions().timeZonerenverra la valeur attendue à partir de Firefox 52: kangax.github.io/compat-table/esintl/…
julen

Comment utiliser ce formulaire? Dans une valeur cachée comme suggéré sur developer.mozilla.org/en-US/docs/Web/HTML/Element/input/… ?
hendry

4
Fonctionne dans Firefox maintenant
Dustin Michels

76

Souvent, lorsque les gens recherchent des «fuseaux horaires», ce qui suffit, c'est simplement le «décalage UTC». par exemple, leur serveur est en UTC + 5 et ils veulent savoir que leur client fonctionne en UTC-8 .


En clair, l'ancien javascript (new Date()).getTimezoneOffset()/60retournera le nombre actuel d'heures de décalage par rapport à UTC.

Il convient de noter un possible "gotcha" dans le signe de la getTimezoneOffset()valeur de retour (à partir de la documentation MDN) :

Le décalage du fuseau horaire est la différence, en minutes, entre l'heure UTC et l'heure locale. Notez que cela signifie que le décalage est positif si le fuseau horaire local est derrière UTC et négatif s'il est en avance. Par exemple, pour le fuseau horaire UTC + 10: 00 (heure normale de l'est de l'Australie, heure de Vladivostok, heure standard de Chamorro), -600 sera renvoyé.


Cependant, je vous recommande d'utiliser le day.js pour le code Javascript lié à l'heure / la date. Dans ce cas, vous pouvez obtenir un décalage UTC au format ISO 8601 en exécutant:

> dayjs().format("Z")
"-08:00"

Il convient probablement de mentionner que le client peut facilement falsifier ces informations.

(Remarque: cette réponse recommandait à l'origine https://momentjs.com/ , mais dayjs est une alternative plus moderne et plus petite.)


30
Il peut être intéressant de noter que le décalage et le fuseau horaire ne sont pas nécessairement la même chose.
Dex

9
Comment appliqueriez-vous l'heure d'été avec seulement le décalage? Dans ces domaines, le décalage est erroné la moitié de l'année. IMO le fuseau horaire est plus précis.
Savageman

4
L'heure d'été fait partie du décalage à un moment donné. L'heure d'Europe centrale en hiver est UTC + 01: 00. Cependant, lorsque l'heure d'été est appliquée, CET est UTC + 02: 00, comme c'est le cas maintenant au Danemark où je suis.
Gert Sønder du

1
c'est pourquoi getTimezoneOffset () a besoin d'une date pour travailler hors de - il ajoutera l'heure d'été en vigueur à ce moment-là.
OsamaBinLogin

2
le décalage n'est pas précis lorsque l'on considère l'heure d'été.
Greg L.

48

Pour l'instant, le meilleur pari est probablement jstz comme suggéré dans la réponse de mbayloon .

Par souci d'exhaustivité, il convient de mentionner qu'il existe une norme sur son chemin: Intl . Vous pouvez déjà voir cela dans Chrome:

> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"

(Cela ne suit pas réellement la norme, ce qui est une raison de plus de s'en tenir à la bibliothèque)


1
Intl semble stable dans tout sauf Safari. caniuse.com/#feat=internationalization
Michael Cole

2
@MichaelCole Les implémentations conformes de Intlsont censées renvoyer undefinedpour la timeZonepropriété si vous n'avez pas spécifié manuellement de fuseau horaire lors de la construction du fichier DateTimeFormat. Chrome s'écarte de la norme en renvoyant le fuseau horaire du système à la place; c'est ce que la réponse de Johannes exploite, mais aussi pourquoi il a dit "ne suit pas réellement la norme".
Chris Jester-Young

20
FYI - la norme est maintenant Intl.DateTimeFormat () .olvedOptions (). TimeZone
Nederby


4

Voici un jsfiddle

Il fournit l'abréviation du fuseau horaire de l'utilisateur actuel.

Voici l'exemple de code

var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));

1
Pour afficher la date telle que May 22 2015 03:45 PM CDT je l'ai utilisée console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
αƞjiβ

5
Votre violon ne fonctionne plus et donne des erreurs dans la console.
Saumil

2

J'ai utilisé une approche similaire à celle adoptée par Josh Fraser , qui détermine le décalage horaire du navigateur par rapport à UTC et s'il reconnaît ou non l'heure d'été (mais quelque peu simplifiée à partir de son code):

var ClientTZ = {
    UTCoffset:  0,          // Browser time offset from UTC in minutes
    UTCoffsetT: '+0000S',   // Browser time offset from UTC in '±hhmmD' form
    hasDST:     false,      // Browser time observes DST

    // Determine browser's timezone and DST
    getBrowserTZ: function () {
        var self = ClientTZ;

        // Determine UTC time offset
        var now = new Date();
        var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0);    // Jan
        var diff1 = -date1.getTimezoneOffset();
        self.UTCoffset = diff1;

        // Determine DST use
        var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0);    // Jun
        var diff2 = -date2.getTimezoneOffset();
        if (diff1 != diff2) {
            self.hasDST = true;
            if (diff1 - diff2 >= 0)
                self.UTCoffset = diff2;     // East of GMT
        }

        // Convert UTC offset to ±hhmmD form
        diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
        var hr = Math.floor(diff2);
        var min = diff2 - hr;
        diff2 = hr * 100 + min * 60;
        self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');

        return self.UTCoffset;
    }
};

// Onload
ClientTZ.getBrowserTZ();

Lors du chargement, la ClientTZ.getBrowserTZ()fonction est exécutée, ce qui définit:

  • ClientTZ.UTCoffset au décalage horaire du navigateur par rapport à UTC en minutes (par exemple, CST est de -360 minutes, qui est de -6,0 heures de UTC);
  • ClientTZ.UTCoffsetTau décalage sous la forme '±hhmmD'(par exemple, '-0600D'), où le suffixe est Dpour DST et Spour standard (non-DST);
  • ClientTZ.hasDST (à vrai ou faux).

Le ClientTZ.UTCoffsetest fourni en minutes au lieu d'heures, car certains fuseaux horaires ont des décalages horaires fractionnaires (par exemple, +0415).

L'intention derrière ClientTZ.UTCoffsetTest de l'utiliser comme clé dans un tableau de fuseaux horaires (non fourni ici), comme pour une <select>liste déroulante .


Il semblerait qu'il renverra toujours «D» si l'heure d'été est observée. Et pourquoi seulement cinq mois de différence? Sûrement, janvier et juillet fonctionneront de manière plus fiable?
Matt

@Matt - Oui, vous pouvez utiliser 7-1pour juillet au lieu de juin. Je ne sais pas si cela fait vraiment une différence, car je doute qu'il existe des régimes régionaux d'heure d'été qui n'incluent pas le mois de juin.
David R Tribble

-13

Non. Il n'y a pas de moyen fiable unique et il n'y en aura jamais. Pensiez-vous vraiment pouvoir faire confiance au client?


23
Pour clarifier: l'horloge du client peut ne pas être réglée correctement, ou il peut essayer de vous tromper en pensant qu'il se trouve dans un fuseau horaire différent du réel. Si vous comptez utiliser le fuseau horaire du client, ne le faites pas pour quelque chose d'important.
Ryan Kinal

7
-1 pour avoir donné une réponse potentiellement trompeuse et ne pas clarifier.
Doug S

6
Oui, pour mon application, je peux faire confiance au client. Si le client a été mal configuré ou a un bogue, c'est sur mes utilisateurs.
Michael Cole

3
Je suis en fait d'accord avec Florian. Méthode fiable? En quelque sorte. Données fiables? Certainement pas.
Rob

4
La question ne dit pas comment les données seront utilisées. Par exemple, il ne dit pas que le fuseau horaire détecté sera jamais soumis à un serveur. Ainsi, la remarque sur la confiance n'est pas pertinente si les données sont utilisées uniquement localement.
dolmen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.