tarayıcıdan istemci saat dilimi alın


139

İstemci tarayıcısından saat dilimi almanın güvenilir bir yolu var mı? Aşağıdaki bağlantıları gördüm ama daha sağlam bir çözüm istiyorum.

JavaScript ile bir saat dilimini otomatik algılama

JavaScript'te saat dilimi algılama



8
Yukarıdaki bağlantı jsTimezoneDetect yazdım, ve benim durum üzerine almak o çapraz çapraz javascript (coğrafi konum ve IP aramaları olmadan) ile alabilirsiniz kadar yakın olmasıdır.
Jon Nylander

Yanıtlar:


87

Bu depo bak pageloom yarar?

jstz.min.js dosyasını indirin ve html sayfanıza bir işlev ekleyin

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

ve bu işlevi ekran etiketinizden çağırın


13
TL; DR Artık Intl.DateTimeFormat().resolvedOptions().timeZoneWallace'ın önerdiği şekilde (IE11 yok) kullanabiliriz .
Code4R7

196

Yarım on yıl sonra bunun için yerleşik bir yolumuz var! Modern tarayıcılar için:

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

Bu bir IANA saat dilimi dizesi döndürür, ancak ofset değerini döndürmez . MDN referansından daha fazla bilgi edinin .

Uyumluluk tablosu - Mart 2019 itibariyle, küresel olarak kullanılan tarayıcıların% 90'ı için çalışıyor. Internet Explorer'da çalışmıyor .


4
firefox'ta çalışmıyor: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek

3
Firefox ve IE bu özelliği desteklemiyor gibi görünüyor :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Wallace

5
Intl.DateTimeFormat().resolvedOptions().timeZoneFirefox 52'den başlayarak beklenen değeri döndürür: kangax.github.io/compat-table/esintl/…
julen

Bu nasıl bir form kullanılır? Developer.mozilla.org/tr-TR/docs/Web/HTML/Element/input/… üzerinde önerildiği gibi gizli bir değerde ?
hendry

4
Firefox'ta çalışıyor
Dustin Michels

76

Genellikle insanlar "zaman dilimleri" aradığında, yeterli olan sadece "UTC farkı" dır. Örneğin, sunucuları UTC + 5'tedir ve istemcilerinin UTC-8'de çalıştığını bilmek isterler .


Düz eski javascript (new Date()).getTimezoneOffset()/60UTC geçerli saat kaç ofset dönecektir.

getTimezoneOffset()Dönüş değerinin işaretinde (MDN belgelerinden) olası bir "gotcha" yı belirtmek gerekir :

Saat dilimi farkı, UTC ve yerel saat arasındaki dakika cinsinden farktır. Bunun, yerel saat dilimi UTC'nin arkasındaysa ofsetin pozitif ve önde ise negatif olduğu anlamına gelir. Örneğin, UTC + 10: 00 saat dilimi için (Avustralya Doğu Standart Saati, Vladivostok Saati, Chamorro Standart Saati), -600 döndürülecektir.


Ancak, day.js'yi saat / tarihle ilgili Javascript kodu için kullanmanızı öneririz . Bu durumda, aşağıdakileri çalıştırarak ISO 8601 biçimli UTC ofseti elde edebilirsiniz:

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

Muhtemelen müşterinin bu bilgileri kolayca tahrif edebileceğini belirtmektedir.

(Not: Bu yanıt başlangıçta https://momentjs.com/ önerilir , ancak dayjs daha modern, daha küçük bir alternatiftir.)


30
Ofset ve zaman diliminin mutlaka aynı şey olmadığını belirtmek gerekir.
Dex

9
DST'yi sadece ofset ile nasıl uygularsınız? Bu alanda ofset yılın yarısında yanlıştır. IMO saat dilimi daha doğrudur.
Savageman

4
DST herhangi bir zamanda ofsetin bir parçasıdır. Kışın Orta Avrupa Saati UTC + 01: 00'dir. Ancak, DST uygulandığında CET UTC + 02: 00, şimdi olduğum Danimarka'da olduğu gibi.
Gert Sønderby

1
Bu nedenle getTimezoneOffset () 'in çalışmak için bir tarihe ihtiyacı vardır - o anda DST'ye eklenir.
OsamaBinLogin

2
Yaz Saati dikkate alındığında ofset doğru değildir.
Greg L.

48

Şimdilik, en iyi bahis muhtemelen mbaylon'un cevabında önerildiği gibi jstz .

Tamlık için, yolda bir standart olduğu belirtilmelidir: Intl . Bunu Chrome'da zaten görebilirsiniz:

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

(Bu aslında standarda uymuyor, bu da kütüphaneye bağlı kalmak için bir neden daha var)


1
Uluslararası Safari dışında her şeyde istikrarlı görünüyor. caniuse.com/#feat=internationalization
Michael Cole

2
@MichaelCole uyumluluğunu uygulamaları arasında Intldönmek gerekiyordu undefinediçin timeZoneel oluşturulmasında bir zaman dilimini belirtmek olmasaydı mülkiyet DateTimeFormat. Chrome, bunun yerine sistemin saat dilimini döndürerek standarttan sapar; Johannes'in cevabı bu yüzden de "standartlara uymuyor" dedi.
Chris Jester-Young

20
FYI - standart şimdi Intl.DateTimeFormat (). ResolvedOptions (). TimeZone
Nederby


4

İşte bir jsfiddle

Geçerli kullanıcı saat diliminin kısaltmasını sağlar.

İşte kod örneği

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

1
Tarihi May 22 2015 03:45 PM CDT kullandığım şekilde görüntülemek için console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
αƞjiβ

5
Kemanınız artık çalışmıyor ve konsolda hata veriyor.
Saumil

2

UTC'den tarayıcı zaman uzaklığını ve DST'yi tanıyıp tanımadığını (ancak kodundan biraz basitleştirildiğini) belirleyen Josh Fraser tarafından alınan yaklaşıma benzer bir yaklaşım kullandım :

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();

Yüklendikten sonra, ClientTZ.getBrowserTZ()fonksiyon yürütülür:

  • ClientTZ.UTCoffset dakika cinsinden tarayıcı zaman uzaklığına (ör. CST, UTC'den −6,0 saat olan 60360 dakikadır);
  • ClientTZ.UTCoffsetTekin DST ve standart (DST olmayan) için olduğu formdaki '±hhmmD'(örneğin '-0600D') ofsetine ;DS
  • ClientTZ.hasDST (doğru veya yanlış).

ClientTZ.UTCoffsetBazı saat dilimleri fraksiyonel saatlik uzaklıklar (örneğin 0415) var çünkü saat yerine, birkaç dakika içinde sağlanır.

Arkadaki amaç ClientTZ.UTCoffsetT, bir açılır liste gibi bir zaman dilimi tablosunda (burada sağlanmayan) bir anahtar olarak kullanmaktır.<select> liste .


Gün ışığından yararlanma gözlemlenirse her zaman 'D' dönecektir. Ve neden sadece beş ay fark var? Elbette, Ocak ve Temmuz daha güvenilir bir şekilde çalışacak mı?
Matt

@Matt - Evet, 7-1Haziran yerine Temmuz ayı için kullanabilirsiniz . Gerçekten bir fark yaratıp yaratmadığından emin değilim, çünkü Haziran'ı içermeyen bölgesel DST şemaları olduğundan şüpheliyim.
David R Tribble

-13

Hayır. Tek bir güvenilir yol yoktur ve asla olmayacaktır. Gerçekten müşteriye güvenebileceğinizi düşündünüz mü?


23
Açıklığa kavuşturmak için: Müşterinin saati doğru şekilde ayarlanmamış olabilir veya sizi gerçek saatten farklı bir saat diliminde olduklarını düşünmeye kandırmaya çalışıyor olabilir. Müşterinin saat dilimini kullanacaksanız, önemli bir şey için yapmayın.
Ryan Kinal

7
-1 potansiyel olarak yanıltıcı bir cevap vermek ve açıklığa kavuşturmamak için.
Doug S

6
Evet, başvurum için müşteriye güvenebilirim. İstemci yanlış yapılandırılmışsa veya bir hata içeriyorsa, bu benim kullanıcılarımda.
Michael Cole

3
Aslında Florian'a katılıyorum. Güvenilir yöntem? Türü. Güvenilir veri? Kesinlikle hayır.
Soymak

4
Soru verinin nasıl kullanılacağını söylemiyor. Örneğin, algılanan saat diliminin bir sunucuya gönderileceğini söylemez. Dolayısıyla, veriler tamamen yerel olarak kullanılıyorsa, güven hakkındaki sözler önemsizdir.
dolmen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.