Czy istnieje niezawodny sposób na pobranie strefy czasowej z przeglądarki klienta? Widziałem następujące linki, ale chcę solidniejszego rozwiązania.
Automatyczne wykrywanie strefy czasowej za pomocą JavaScript
Czy istnieje niezawodny sposób na pobranie strefy czasowej z przeglądarki klienta? Widziałem następujące linki, ale chcę solidniejszego rozwiązania.
Automatyczne wykrywanie strefy czasowej za pomocą JavaScript
Odpowiedzi:
Spójrz na to repozytorium pageloom warto
pobierz jstz.min.js i dodaj funkcję do swojej strony html
<script language="javascript">
function getTimezoneName() {
timezone = jstz.determine()
return timezone.name();
}
</script>
i wywołaj tę funkcję ze swojego tagu display
Intl.DateTimeFormat().resolvedOptions().timeZone
(bez IE11) zgodnie z sugestią Wallace'a.
Pół dekady później mamy na to wbudowany sposób! W przypadku nowoczesnych przeglądarek użyłbym:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
Zwraca łańcuch stref czasowych IANA, ale nie zwraca przesunięcia . Dowiedz się więcej w źródłach MDN .
Tabela zgodności - od marca 2019 r. Działa dla 90% przeglądarek używanych na całym świecie. Nie działa w przeglądarce Internet Explorer .
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
zwróci oczekiwaną wartość, zaczynając od przeglądarki Firefox 52: kangax.github.io/compat-table/esintl/…
Często, gdy ludzie szukają „stref czasowych”, wystarczy tylko „przesunięcie czasu UTC”. np. ich serwer jest w UTC + 5 i chcą wiedzieć, że ich klient działa w UTC-8 .
W zwykłym starym javascript (new Date()).getTimezoneOffset()/60
zwróci bieżącą liczbę godzin przesuniętą z UTC.
Warto zwrócić uwagę na ewentualne „gotcha” w znaku getTimezoneOffset()
zwracanej wartości (z dokumentacji MDN) :
Przesunięcie strefy czasowej to różnica w minutach między czasem UTC a czasem lokalnym. Zauważ, że oznacza to, że przesunięcie jest dodatnie, jeśli lokalna strefa czasowa jest za UTC i ujemne, jeśli jest z przodu. Na przykład dla strefy czasowej UTC + 10: 00 (australijski czas wschodni standardowy, czas Władywostoku, czas standardowy Chamorro) zostanie zwrócona wartość -600.
Zalecam jednak używanie pliku day.js dla kodu JavaScript związanego z czasem / datą. W takim przypadku możesz uzyskać przesunięcie czasu UTC w formacie ISO 8601, uruchamiając:
> dayjs().format("Z")
"-08:00"
Zapewne warto wspomnieć, że klient może łatwo sfałszować te informacje.
(Uwaga: ta odpowiedź początkowo zalecała https://momentjs.com/ , ale dayjs jest bardziej nowoczesną, mniejszą alternatywą.)
Na razie najlepszym rozwiązaniem jest prawdopodobnie jstz, zgodnie z sugestią mbayloon .
Dla kompletności należy wspomnieć, że na drodze jest standard: Intl . Możesz to już zobaczyć w Chrome:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(W rzeczywistości nie jest to zgodne ze standardem, co jest kolejnym powodem, aby trzymać się biblioteki)
Intl
mają powrócić undefined
do timeZone
własności, jeśli nie ręcznie określić strefę czasową przy konstruowaniu DateTimeFormat
. Chrome odbiega od standardu, zwracając zamiast tego strefę czasową systemu; to właśnie wykorzystuje odpowiedź Johannesa, ale także powód, dla którego powiedział „tak naprawdę nie spełnia standardów”.
możesz użyć strefy czasowej momentu, aby odgadnąć strefę czasową:
> moment.tz.guess()
"America/Asuncion"
Oto plik jsfiddle
Zawiera skrót aktualnej strefy czasowej użytkownika.
Oto przykładowy kod
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
, jak użyłem console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
Użyłem podejścia podobnego do tego zastosowanego przez Josha Frasera , który określa przesunięcie czasu przeglądarki od UTC i czy rozpoznaje czas letni, czy nie (ale nieco uproszczony z jego kodu):
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();
Po załadowaniu ClientTZ.getBrowserTZ()
wykonywana jest funkcja, która ustawia:
ClientTZ.UTCoffset
do przesunięcia czasu przeglądarki w stosunku do UTC w minutach (np. CST wynosi -360 minut, co stanowi -6,0 godzin od UTC);ClientTZ.UTCoffsetT
do offsetu w postaci '±hhmmD'
(np., '-0600D'
), gdzie przyrostek oznacza D
DST i S
standard (inny niż DST);ClientTZ.hasDST
(na prawdę lub fałsz).Wartość ClientTZ.UTCoffset
jest podawana w minutach zamiast w godzinach, ponieważ niektóre strefy czasowe mają ułamkowe przesunięcia godzinowe (np. +0415).
Zamiarem ClientTZ.UTCoffsetT
jest użycie go jako klucza do tabeli stref czasowych (nie podano tutaj), na przykład <select>
listy rozwijanej .
7-1
lipca zamiast czerwca. Nie jestem pewien, czy to naprawdę robi różnicę, ponieważ wątpię, czy istnieją regionalne schematy czasu letniego, które nie obejmują czerwca.
Nie. Nie ma jednego niezawodnego sposobu i nigdy nie będzie. Czy naprawdę sądziłeś, że możesz zaufać klientowi?