Uzyskiwanie przesunięcia strefy czasowej klienta w JavaScript


613

Jak mogę zebrać informacje o strefie czasowej użytkownika? Potrzebuję strefy czasowej, a także godzin przesunięcia GMT.


3
Rozumiem teraz ten sam problem. Oto interesujące podejście.
Tamás Pap,

31
Tytuł pyta o strefę czasową, a tekst pyta o przesunięcie GMT. To są dwie różne rzeczy. Strefa czasowa zawiera informacje o DST, przesunięcie utc nie. Strefa czasowa ma nazwę i historię, przesunięcie nie. Zaleca się edycję tytułu na „Uzyskanie przesunięcia gmt klienta w JS”.
citykid

Potrzebuję strefy czasowej. Pomocne byłoby również przesunięcie GMT.
DaveWalley

9
Odpowiedzi tutaj koncentrują się głównie na offsecie . Dla strefy czasowej zobacz tę odpowiedź . Zobacz „Strefa czasowa! = Przesunięcie” na wiki tagu strefy czasowej .
Matt Johnson-Pint,

7
Dokładna strefa czasowa jest uzyskiwana za pomocą tego Intl.DateTimeFormat (). ResolvedOptions ().
TimeZone

Odpowiedzi:


594

var offset = new Date().getTimezoneOffset();
console.log(offset);

Przesunięcie strefy czasowej to różnica w minutach między czasem UTC i czasem lokalnym. Należy pamiętać, że oznacza to, że przesunięcie jest dodatnie, jeśli lokalna strefa czasowa znajduje się za UTC, a ujemne, jeśli jest do przodu. Na przykład, jeśli Twoja strefa czasowa to UTC + 10 (Australian Eastern Standard Time), wartość -600 zostanie zwrócona. Czas letni zapobiega temu, aby wartość ta była stała nawet dla danego regionu

Pamiętaj, że nie wszystkie strefy czasowe są przesunięte o całe godziny: na przykład Nowa Fundlandia ma UTC minus 3h 30m (pozostawiając czas letni poza równaniem).


42
@abernier Czy obowiązuje oświadczenie o getTimezoneOffsetniedokładności? Artykuł, do którego się odwołujesz, pochodzi z czerwca 2007 r. I nie zawiera szczegółowych informacji na temat niedokładności funkcji. W rzeczywistości jsTimezoneDetectwskazana biblioteka getTimezoneOffsetsama się używa .
Mike

5
@abernier To standard od ES 1, więc jestem pewien, że jakikolwiek problem z implementacją może być już naprawiony, to znaczy, to jest 7-letni artykuł.
LasagnaAndroid

49
var hrs = -(new Date().getTimezoneOffset() / 60) aby uzyskać przesunięcie w godzinach zwykle używanych
Edwin Daniels

6
Wygląda na to, że nie bierze pod uwagę czasu letniego
Shahdat

21
timezone! =utc offset
bendytree

480

Użycie przesunięcia do obliczenia strefy czasowej jest niewłaściwym podejściem i zawsze będziesz mieć problemy. Strefy czasowe i reguły dotyczące czasu letniego mogą zmieniać się kilkakrotnie w ciągu roku i trudno jest nadążyć za nimi.

Aby uzyskać strefę czasową IANA systemu w JavaScript, powinieneś użyć

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

Od września 2019 r. Działa to w 95% przeglądarek używanych na całym świecie .

Stare informacje o zgodności

ecma-402 / 1.0 mówi, że timeZonemoże być niezdefiniowany, jeśli nie zostanie przekazany konstruktorowi. Jednak przyszły projekt (3.0) rozwiązał ten problem, zmieniając domyślną strefę czasową systemu.

W tej wersji interfejsu API internacjonalizacji ECMAScript timeZonewłaściwość pozostanie niezdefiniowana, jeśli żadna timeZonewłaściwość nie zostanie podana w obiekcie opcji przekazanym do Intl.DateTimeFormat konstruktora . Jednak aplikacje nie powinny na tym polegać, ponieważ przyszłe wersje mogą zwracać wartość typu String identyfikującą bieżącą strefę czasową środowiska hosta.

w ecma-402 / 3.0, który jest wciąż w wersji roboczej, zmieniono na

W tej wersji interfejsu API internacjonalizacji ECMAScript 2015 timeZonewłaściwość będzie nazwą domyślnej strefy czasowej, jeśli żadna timeZonewłaściwość nie zostanie podana w obiekcie opcji przekazanym do Intl.DateTimeFormatkonstruktora. Poprzednia wersja pozostawiła timeZonewłaściwość niezdefiniowaną w tym przypadku.


17
To jedyna odpowiedź na pytanie o strefę czasową, której niektórzy użytkownicy mogą potrzebować, a nie tylko przesunięcie. Tak więc, jako aktualizacja w 2016-09, Intl działa w większości nowoczesnych przeglądarek, ale nie Safari. W przypadku tej przeglądarki istnieje dość dokładna kopia
user2085368

6
Zweryfikowano, że teraz działa to w przeglądarce Safari. (Korzystanie z wersji 10.0)
BadPirate,

2
Byłoby miło, gdyby działało to we wszystkich nowoczesnych przeglądarkach. Jednak IE11 i najnowszy Firefox zwracają niezdefiniowane dla właściwości timeZone.
Haprog

7
Testowałem teraz z Chrome 58, Edge 40 i Firefox 53 - działa, to wszystko. Nie działa z IE 11, nie testowałem Opery.
Suma

7
Zajęło mi trochę czasu znalezienie listy stref czasowych zwróconych przez ten interfejs API. Oto on: en.wikipedia.org/wiki/List_of_tz_database_time_zones
Xavier Poinas

123

Zdaję sobie sprawę, że ta odpowiedź jest nieco nie na temat, ale wyobrażam sobie, że wielu z nas szukających odpowiedzi również chciało sformatować strefę czasową do wyświetlania i być może również uzyskać skrót strefy. No i proszę…

Jeśli chcesz, aby strefa czasowa klienta była ładnie sformatowana, możesz polegać na metodzie Date.toString JavaScript i wykonać:

var split = new Date().toString().split(" ");
var timeZoneFormatted = split[split.length - 2] + " " + split[split.length - 1];

To da ci na przykład „GMT-0400 (EST)”, w tym minuty strefy czasowej, jeśli dotyczy.

Alternatywnie za pomocą wyrażenia regularnego możesz wyodrębnić dowolną część:

W przypadku „GMT-0400 (EDT)”:

new Date().toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1]

W przypadku „GMT-0400”:

new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1]

Tylko „EDT”:

new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1]

Tylko „-0400”:

new Date().toString().match(/([-\+][0-9]+)\s/)[1]

Odwołanie do Date.toString: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toString


4
Zepsuty w Chrome, ponieważ dołącza nazwę strefy czasowej. Zamiast tego nie używaj split.length, ale stałą split[4] + " " + split[5]?!
Christophe Roussy

4
To również nie działa w (niespodzianka, niespodzianka) IE. Właśnie zrobiłem zrzut konsoli podzielonego obiektu Date. Tak samo jest w Chrome, Firefox i Safari, ale różni się w IE. Więc nie można też liczyć na stałe indeksy. Pn 02 grudnia 2013 10:22:50 GMT-0500 (EST): Chrome, FF, Safari; Mon Dec 2 10:22:50 EST 2013: IE10
adimauro

1
Boże, dziękuję! Skakałem przez obręcze, próbując wyświetlić strefę czasową przeglądarki ..... ew Date (). ToString (). Match (/ ([AZ] + [\ + -] [0-9] +. *) /) [ 1] było dokładnie tym, czego potrzebowałem!
KiwiSunGoddess

1
To nie działa Dla mnie splitzawiera: ["Mon", "Mar", "13", "2017", "14:05:22", "GMT-0400", "(Eastern", "Daylight", "Time)"]więc wynik toDaylight Time)
DLeh

7
W rzeczywistości nie jest to dobry pomysł, rzeczywista reprezentacja czasu JS po nim new Date().toString()jest całkowicie zależna od ustawień regionalnych. Oczekiwanie, że wyniki innych klientów będą podobne do twoich, jest bardzo złym pomysłem.
Ośmiornica

71

Odpowiedzieliśmy już, jak uzyskać przesunięcie w minutach jako liczbę całkowitą, ale na wypadek, gdyby ktoś chciał lokalnego przesunięcia GMT jako ciągu, np . "+1130":

function pad(number, length){
    var str = "" + number
    while (str.length < length) {
        str = '0'+str
    }
    return str
}

var offset = new Date().getTimezoneOffset()
offset = ((offset<0? '+':'-')+ // Note the reversed sign!
          pad(parseInt(Math.abs(offset/60)), 2)+
          pad(Math.abs(offset%60), 2))

1
Musisz wymienić 1. wypełnienie, pad(parseInt(Math.abs(offset/60)), 2)aby zrobić to dobrze ... w przeciwnym razie możesz dostać +5.530, jak w moim przypadku ... nie jestem pewien, czy podłoga matematyczna itp. Będzie lepsza, czy nie ... ale to co najmniej daje mi +0530 zgodnie z oczekiwaniami
Abhinav Singh

Dokładnie to, czego szukałem. Dzięki !
Codesnooker,

to da poprawny wynik: this.pad (Math.floor ((Math.abs (offset / 60))), 2)
Vivek

Zamiast korzystać z funkcji pad, łatwiej mi to zrobić: offset = (offset <0? "+": "-") + ("0000" + parseInt ((Math.abs (offset / 60)))) .slice (-4)
flurbius

67

Możesz użyć:

strefa czasowa

<script src="moment.js"></script>
<script src="moment-timezone-with-data.js"></script>

// retrieve timezone by name (i.e. "America/Chicago")
moment.tz.guess();

Wykrywanie strefy czasowej w przeglądarce jest dość trudne, aby uzyskać właściwy wynik, ponieważ przeglądarka zapewnia niewiele informacji.

Moment Strefa czasowa wykorzystuje Date.getTimezoneOffset()i Date.toString()przez kilka chwil w ciągu bieżącego roku, aby zebrać jak najwięcej informacji o środowisku przeglądarki. Następnie porównuje te informacje ze wszystkimi załadowanymi danymi strefy czasowej i zwraca najbliższe dopasowanie. W przypadku powiązań zwracana jest strefa czasowa z miastem o największej liczbie mieszkańców.

console.log(moment.tz.guess()); // America/Chicago

12
To powinna być zaakceptowana odpowiedź. Jest to jedyny, który podaje rzeczywistą nazwę strefy czasowej zamiast przesunięcia. Pamiętaj, że przesunięcie strefy czasowej można wyprowadzić z nazwy, odwrotność nie jest prawdą. Ze względu na czas letni i inne subtelności wiele stref czasowych może mieć takie samo przesunięcie tylko w określone dni roku.
Romain G

1
Teraz jest na to natywne rozwiązanie - Intl API . Chociaż moment.js był świetną biblioteką w tamtych czasach, istnieją obecnie znacznie mniejsze alternatywy ( dayjs , date-fns ). Moment jest ogromny ; proszę nie polecać go do aplikacji klienckich.
Dan Dascalescu,

43

W swoim projekcie napisałem funkcję, która zwraca strefę czasową w hh:mmformacie. Mam nadzieję, że może to komuś pomóc:

function getTimeZone() {
    var offset = new Date().getTimezoneOffset(), o = Math.abs(offset);
    return (offset < 0 ? "+" : "-") + ("00" + Math.floor(o / 60)).slice(-2) + ":" + ("00" + (o % 60)).slice(-2);
}

// Outputs: +5:00

Working Fiddle


1
Dziękuję Ci! Właśnie tego potrzebowałem!
Jeremy Moritz

15

Jednowierszowy, który podaje zarówno przesunięcie, jak i strefę czasową, to po prostu wywołanie metody toTimeString () na nowym obiekcie Date. Z MDN:

toTimeString()Metoda zwraca część czasu obiekt Date w postaci czytelnej dla człowieka w amerykańskim angielskim.

Problem polega na tym, że strefa czasowa nie ma standardowego formatu IANA; jest nieco bardziej przyjazny dla użytkownika niż format IANA „kontynent / miasto” . Wypróbuj to:

console.log(new Date().toTimeString().slice(9));
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
console.log(new Date().getTimezoneOffset() / -60);

Obecnie w Kalifornii toTimeString()zwraca, Pacific Daylight Timegdy wraca interfejs API Intl America/Los_Angeles. W Kolumbii dostaniesz Colombia Standard Timekontra America/Bogota.

Zauważ, że wiele innych odpowiedzi na to pytanie próbuje uzyskać te same informacje, wywołując Date.toString (). To podejście nie jest tak niezawodne, jak wyjaśnia MDN :

Instancje daty odnoszą się do określonego momentu w czasie. Wywołanie metody toString () zwróci datę sformatowaną w czytelnej dla człowieka formie w amerykańskim angielskim. [...] Czasami pożądane jest uzyskanie ciągu czasu; coś takiego można osiągnąć za pomocą toTimeString()metody.

toTimeString()Metoda jest szczególnie użyteczna, ponieważ silniki zgodne wykonawcze ECMA 262 może różnić się w ciągu otrzymanego z toString()o Dateobiektach, w odniesieniu do formatu jest zależne od implementacji; proste metody cięcia łańcuchów mogą nie dawać spójnych wyników dla wielu silników.


13

spróbuj getTimezoneOffset()tego Dateobiektu:

var curdate = new Date()
var offset = curdate.getTimezoneOffset()

Ta metoda zwraca przesunięcie strefy czasowej w minutach, co stanowi różnicę między czasem GMT a czasem lokalnym w minutach.


9

JavaScript:

var d = new Date();
var n = d.getTimezoneOffset();
var timezone = n / -60;
console.log(timezone);


3
Co zawiera ta odpowiedź, której nie udzieliły poprzednie odpowiedzi?
Dan Dascalescu,

7

Z moment.js :

moment().format('zz');

6
zi zzzostały wycofane z wersji 1.6.0 patrz momentjs.com/docs/#/displaying/format
MrUpsidown

3
@MrUpsidown jest teraz ZiZZ
brauliobo

4
@ hydraulraulob Te parametry nie zwracają tego samego. Z i ZZ zwróciły strefę czasową, np. CST, ale Z i ZZ zwracają przesunięcie, np. -0600.
Luca Spiller,

Najnowsze pokazy dokumentów .zoneAbbr()zostały zastąpione zi zz. Zobacz dokumentację tutaj
tabish89,

1
Chociaż moment.js był świetną biblioteką w tamtych czasach, istnieją obecnie znacznie mniejsze alternatywy ( dayjs , date-fns ). Moment jest ogromny ; proszę nie polecać go do aplikacji klienckich.
Dan Dascalescu

6

Z , możesz znaleźć aktualną strefę czasową jako

console.log(moment().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>


Z , możesz znaleźć aktualną strefę czasową jako

console.log(dayjs().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://unpkg.com/dayjs@1.8.10/dayjs.min.js"></script>

Oba API zwracają przesunięcie utc w ciągu kilku minut.


Chociaż moment.js był świetną biblioteką w tamtych czasach, istnieją obecnie znacznie mniejsze alternatywy ( dayjs , date-fns ). Moment jest ogromny ; proszę nie polecać go do aplikacji klienckich.
Dan Dascalescu,

1
„W dayjs możesz znaleźć aktualną strefę czasową, ponieważ” nie jest dokładnie dokładne - znajdziesz tylko przesunięcie, a nie strefę czasową . Ponadto Dayjs nie obsługuje strefy czasowej . Jego metoda .utcOffset () jest prostym opakowaniem nad rodzimym getTimezoneOffset().
Dan Dascalescu

4

Strefa czasowa w godzinach

var offset = new Date().getTimezoneOffset();
if(offset<0)
    console.log( "Your timezone is- GMT+" + (offset/-60));
else
    console.log( "Your timezone is- GMT-" + offset/60);

Jeśli chcesz być precyzyjny, jak wspomniałeś w komentarzu, powinieneś spróbować w ten sposób:

var offset = new Date().getTimezoneOffset();

if(offset<0)
{
    var extraZero = "";
    if(-offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT+" + Math.ceil(offset/-60)+":"+extraZero+(-offset%60));
}
else
{
    var extraZero = "";
    if(offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT-" + Math.floor(offset/60)+":"+extraZero+(offset%60));
}


Nie działa w strefach czasowych, gdy nie jest pełna godzina, jak Wenezuela, gdzie zwraca GMT-4.5
Mirko

Tak to prawda. 0,5 oznacza 0,5 * 30 minut. Myślę, że masz to, dlaczego daje 0,5?
Abrar Jahin

tak, więc GMT-4.5 nie jest prawidłową strefą czasową, potrzebuje trochę dodatkowej analizy, aby zostać GMT-4: 30
Mirko

@Mirko teraz druga część odpowiedzi jest dla Ciebie
Abrar Jahin

Jeśli chcesz być bardziej precyzyjny, użyj UTC zamiast GMT, [Hilton i McCarthy 2013, str. 231–2. ], patrz także na wikipedia GMT - ( en.wikipedia.org/wiki/Greenwich_Mean_Time )
Tom Kuschel

3

Jeśli wszystko, czego potrzebujesz, to skrót strefy czasowej „MST” lub „EST”:

function getTimeZone(){
    var now = new Date().toString();
    var timeZone = now.replace(/.*[(](.*)[)].*/,'$1');//extracts the content between parenthesis
    return timeZone;
}

Korzystanie Date.toString()nie jest niezawodne, a MDN wyjaśnia, dlaczego. Mam wklejony odpowiednią sekcję z ich docs w mojej odpowiedzi .
Dan Dascalescu,

3

Zobacz, jak ten wynikowy operator był odwrotny do strefy czasowej. Więc zastosuj jakąś funkcję matematyczną, a następnie sprawdź liczbę mniejszą lub większą.

wprowadź opis zdjęcia tutaj

Zobacz dokument MDN

var a = new Date().getTimezoneOffset();

var res = -Math.round(a/60)+':'+-(a%60);
res = res < 0 ?res : '+'+res;

console.log(res)


1
wzrost wartości ujemnej, jakiś problem
Arun Prasad ES

1
Dlaczego round? Powinno być floor, prawda?
Qwertiy

3
function getLocalTimeZone() {
    var dd = new Date();
    var ddStr = dd.toString();
    var ddArr = ddStr.split(' ');
    var tmznSTr = ddArr[5];
    tmznSTr = tmznSTr.substring(3, tmznSTr.length);
    return tmznSTr;
}

Przykład: czw. 21 czerwca 2018 18:12:50 GMT + 0530 (czas standardowy w Indiach)

O / P: +0530


Korzystanie Date.toString()nie jest niezawodne, a MDN wyjaśnia, dlaczego. Mam wklejony odpowiednią sekcję z ich docs w mojej odpowiedzi .
Dan Dascalescu,


2

Ta wartość pochodzi z komputera użytkownika i można ją zmienić w dowolnym momencie, więc myślę, że to nie ma znaczenia, chcę tylko uzyskać przybliżoną wartość, a następnie przekonwertować ją na GMT na moim serwerze.

Na przykład jestem z Tajwanu i zwraca mi „+8”.

Przykład roboczy

JS

function timezone() {
    var offset = new Date().getTimezoneOffset();
    var minutes = Math.abs(offset);
    var hours = Math.floor(minutes / 60);
    var prefix = offset < 0 ? "+" : "-";
    return prefix+hours;
}


$('#result').html(timezone());

HTML

<div id="result"></div>

Wynik

+8

2

Na new Date() możesz uzyskać przesunięcie, aby uzyskać nazwę strefy czasowej, którą możesz zrobić:

new Date().toString().replace(/(.*\((.*)\).*)/, '$2');

otrzymasz wartość pomiędzy ()końcem daty, czyli nazwą strefy czasowej.


Korzystanie Date.toString()nie jest niezawodne, a MDN wyjaśnia, dlaczego. Mam wklejony odpowiednią sekcję z ich docs w mojej odpowiedzi . Odpowiedź ta została już udzielona co najmniej 3 razy.
Dan Dascalescu,

2

To byłoby moje rozwiązanie:


    // For time zone:
    const timeZone = /\((.*)\)/.exec(new Date().toString())[1];
    
    // Offset hours:
    const offsetHours = new Date().getTimezoneOffset() / 60;
    
    console.log(`${timeZone}, ${offsetHours}hrs`);

1

Jako alternatywę dla new Date().getTimezoneOffset()i moment().format('zz')możesz także użyć:

var offset = moment.parseZone(Date.now()).utcOffset() / 60
console.log(offset);
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>

jstimezone jest również dość błędny i nieobsługiwany ( https://bitbucket.org/pellepim/jstimezonedetect/issues?status=new&status=open )


Chociaż moment.js był świetną biblioteką w tamtych czasach, istnieją obecnie znacznie mniejsze alternatywy ( dayjs , date-fns ). Moment jest ogromny ; proszę nie polecać go do aplikacji klienckich.
Dan Dascalescu,

1

Użyj tego, aby przekonwertować OffSet na postive:

var offset = new Date().getTimezoneOffset();
console.log(offset);
this.timeOffSet = offset + (-2*offset);
console.log(this.timeOffSet);

-2

Szukałem tylko trzyliterowego ciągu znaków (jak „PDT”) i wypróbowałem odpowiedź Marqueza, ale musiałem ją nieco ulepszyć, aby obsługiwała wiele przeglądarek. Na szczęście ciąg znaków jest ostatnim potencjalnym dopasowaniem :)

Oto co zrobiłem w CoffeeScript:

browserTimezone = ->
  userDate = new Date()
  zoneMatches = userDate.toString().match(/([A-Z][A-Z][A-Z])/g)
  userZone = zoneMatches[zoneMatches.length - 1]

Działa w IE8, IE9, Safari 9, Firefox 44 i Chrome 48


2
Istnieją jednak strefy czasowe z 4 literami - bądź ostrożny: na przykład CEST (czas środkowoeuropejski letni)
jbrosi

Korzystanie Date.toString()nie jest niezawodne, a MDN wyjaśnia, dlaczego. Mam wklejony odpowiednią sekcję z ich docs w mojej odpowiedzi .
Dan Dascalescu,

-3

Musisz tylko dołączyć moment.js i jstz.js

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>

i potem

<script>
$(function(){
 var currentTimezone = jstz.determine();
 var timezone = currentTimezone.name();
 alert(timezone);
});

</script>

-3

To dla mnie bardzo dobra praca:

// Translation to offset in Unix Timestamp
let timeZoneOffset = ((new Date().getTimezoneOffset())/60)*3600;

1
Jakieś wyjaśnienie?

-4

możesz po prostu tego spróbować. zwróci ci aktualny czas maszyny

var _d = new Date(), t = 0, d = new Date(t*1000 + _d.getTime())


Myślę, że tak należy to zrobić: new Date(new Date().getTime()); wyświetli się: „Pt 28 grudnia 2018 10:15:23 GMT + 0100 (środkowoeuropejski standardowy czas) {}”
darmis

-4

To wystarczy.


var time = new Date(),
timestamp = Date(1000 + time.getTime());
console.log(timestamp);

Thu May 25 2017 21:35:14 GMT+0300 (IDT)

nieokreślony

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.