İ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.
İ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.
Yanıtlar:
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
Intl.DateTimeFormat().resolvedOptions().timeZone
Wallace'ın önerdiği şekilde (IE11 yok) kullanabiliriz .
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 .
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
Firefox 52'den başlayarak beklenen değeri döndürür: kangax.github.io/compat-table/esintl/…
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()/60
UTC 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.)
Ş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)
Intl
dönmek gerekiyordu undefined
için timeZone
el 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.
Eğer kullanabilirsiniz an-dilimini zaman dilimini tahmin etmeye:
> moment.tz.guess()
"America/Asuncion"
İş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()));
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()));
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.UTCoffsetT
ekin DST ve standart (DST olmayan) için olduğu formdaki '±hhmmD'
(örneğin '-0600D'
) ofsetine ;D
S
ClientTZ.hasDST
(doğru veya yanlış).ClientTZ.UTCoffset
Bazı 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 .
7-1
Haziran 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.
Hayır. Tek bir güvenilir yol yoktur ve asla olmayacaktır. Gerçekten müşteriye güvenebileceğinizi düşündünüz mü?