JavaScript'te istemcinin saat dilimini dengeleme


614

Ziyaretçinin saat dilimi bilgilerini nasıl toplayabilirim? Timezone'a ve GMT ofset saatlerine ihtiyacım var.


3
Şimdi aynı problemi anlıyorum. İşte ilginç bir yaklaşım.
Tamás Pap

31
Başlık, saat dilimi isterken, metin GMT ofsetini ister. Bunlar 2 farklı şey. Saat Dilimi DST hakkında bilgi içerir, utc ofseti içermez. Saat Dilimi'nin bir adı ve geçmişi vardır, ofset yoktur. "İstemcinin JS'de gmt ofsetini alma" başlığını düzenlemenizi öneririz.
citykid

Saat dilimine ihtiyacım var. GMT ofseti de yardımcı olacaktır.
DaveWalley

9
Buradaki cevaplar çoğunlukla ofset üzerine odaklanmaktadır . İçin saat dilimine bakın bu cevabı . Saat dilimi wiki'sinde "Saat Dilimi! = Ofset" konusuna bakın .
Matt Johnson-Pint

Yanıtlar:


594

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

Saat dilimi farkı, UTC ve yerel saat arasındaki dakika cinsinden farktır. Bunun, yerel saat dilimi UTC'nin arkasındaysa ofsetin pozitif ve ileride negatif olduğu anlamına gelir. Örneğin, saat diliminiz UTC + 10 (Avustralya Doğu Standart Saati) ise, -600 döndürülür. Yaz saati uygulaması, bu değerin belirli bir bölge için bile sabit olmasını önler

Tüm saat dilimlerinin saatlerce dengelenmediğine dikkat edin: örneğin, Newfoundland UTC eksi 3h 30m'dir (Yaz Saati Uygulaması denklemin dışında kalır).


42
@abernier Yanlışlıkla ilgili açıklama getTimezoneOffsetyürürlükte mi? Bahsettiğiniz makale Haziran 2007 tarihlidir ve işlevin nasıl yanlış olduğuna dair hiçbir ayrıntıya sahip değildir. Ve aslında jsTimezoneDetectişaret ettiğin kütüphane getTimezoneOffsetkendini kullanıyor .
Mike

5
@abernier ES 1'den beri bir standart, bu yüzden eminim ki herhangi bir uygulama problemi şu ana kadar çözülebilir, yani 7 yıllık bir makale.
LasagnaAndroid

49
var hrs = -(new Date().getTimezoneOffset() / 60) kullanılan saatler içinde ofset almak için
Edwin Daniels

6
Yaz saatini dikkate almıyor gibi görünüyor
Shahdat

21
timezone! =utc offset
bendytree

482

Zaman dilimini hesaplamak için bir ofset kullanmak yanlış bir yaklaşımdır ve her zaman sorunlarla karşılaşırsınız. Zaman dilimleri ve gün ışığından yararlanma kuralları bir yıl boyunca birkaç kez değişebilir ve değişikliklere ayak uydurmak zordur.

Sistemin IANA saat dilimini JavaScript olarak almak için şunu kullanmalısınız:

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

Eylül 2019 itibariyle, bu, küresel olarak kullanılan tarayıcıların% 95'inde çalışıyor .

Eski uyumluluk bilgileri

ecma-402 / 1.0, kurucuya verilmezse timeZonetanımsız olabileceğini söylüyor . Ancak, gelecekteki taslak (3.0) sistem varsayılan saat dilimine geçerek bu sorunu çözdü.

ECMAScript Uluslararasılaşma API Bu versiyonda, timeZonehiçbir eğer mülkiyet tanımsız kalır timeZonemülkiyet sağlanan nesnesi seçeneklerinde sağlandı Intl.DateTimeFormat yapıcısı . Ancak, gelecek sürümler ana bilgisayar ortamının geçerli saat dilimini tanımlayan bir String değeri döndürebileceğinden, uygulamalar buna güvenmemelidir.

hala taslakta olan ecma-402 / 3.0'da

ECMAScript 2015 Uluslararasılaştırma API'sının bu sürümünde, yapıcıya sağlanan seçenekler nesnesinde timeZonehiçbir timeZoneözellik sağlanmadıysa, özellik varsayılan saat diliminin adı olacaktır Intl.DateTimeFormat. Önceki sürüm timeZone, bu durumda özelliği tanımsız bıraktı .


17
Bu, bazı kullanıcıların yalnızca ofsetin aksine ihtiyaç duyabileceği zaman dilimini almak için tek cevaptır. Bu nedenle, 2016-09'da bir güncelleme olarak, Intl Safari'de değil, çoğu modern tarayıcıda çalışır. Bu tarayıcı için, burada oldukça doğru bir javascript yedeği var - pellepim.bitbucket.org/jstz
user2085368

6
Bunun şimdi Safari'de çalışıyor gibi göründüğü doğrulandı. (10.0 sürümünü kullanarak)
BadPirate

2
Bu tüm modern tarayıcılarda çalıştı olsaydı iyi olurdu. Ancak IE11 ve en yeni Firefox, timeZone özelliği için tanımsız olarak döner.
Haprog

7
Şimdi Chrome 58, Edge 40 ve Firefox 53 ile test ettim - hepsi işe yarayacak. IE 11 ile çalışmaz, Opera'yı test etmedim.
Suma

8
Bu API tarafından döndürülen saat dilimlerinin listesini bulmak biraz zaman aldı. İşte: en.wikipedia.org/wiki/List_of_tz_database_time_zones
Xavier Poinas

123

Bu cevabın biraz konu dışı olduğunu anlıyorum, ancak çoğumuzun görüntüleme için saat dilimini biçimlendirmek ve belki de bölge kısaltmasını almak isteyen bir cevap aradığımızı hayal ediyorum. İşte gidiyor ...

İstemci saat diliminin iyi biçimlendirilmesini istiyorsanız JavaScript Date.toString yöntemine güvenebilir ve şunları yapabilirsiniz:

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

Bu, örneğin, geçerli olduğunda saat dilimi dakikaları dahil, size "GMT-0400 (EST)" verecektir.

Alternatif olarak, regex ile istediğiniz herhangi bir parçayı çıkarabilirsiniz:

"GMT-0400 (EDT)" için:

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

"GMT-0400" için:

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

Sadece "EDT" için:

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

Sadece "-0400" için:

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

Date.toString referansı: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toString


4
Saat diliminin adını eklediğinden Chrome ile kırıldı. Split.length değil sabit kullanın. split[4] + " " + split[5]?
Christophe Roussy

4
Bu aynı zamanda (sürpriz, sürpriz) IE'de çalışmaz. Bölünmüş Date nesnesinin bir konsol dökümü yaptım. Chrome, Firefox ve Safari'de aynı, ancak IE'de farklı. Dolayısıyla, sabit dizinlere de güvenemezsiniz. Pzt 02 Ara 2013 10:22:50 GMT-0500 (EST): Krom, FF, Safari; Pzt 2 Ara 22:22:50 EST 2013: IE10
adimauro

1
Tanrım, teşekkürler! Tarayıcı saat dilimi göstermeye çalışan çemberler üzerinden atlıyorum ..... ew Date (). ToString (). Match (/ ([AZ] + [\ + -] [0-9] +. *) /) [ 1] tam olarak ihtiyacım olan şeydi!
KiwiSunGoddess

1
Bu işe yaramıyor. Benim için splitiçerir: ["Mon", "Mar", "13", "2017", "14:05:22", "GMT-0400", "(Eastern", "Daylight", "Time)"]yani sonuçDaylight Time)
DLeh

7
Bu aslında, JS süresinin gerçek temsili new Date().toString()tamamen yerel ayarlarınıza bağlıdır iyi bir fikir değildir . Diğer müşterilerin çıktılarının sizinkine benzemesini beklemek çok kötü bir fikirdir.
Ahtapot

71

Bir tamsayı olarak dakikalar içinde nasıl dengeleneceği zaten cevaplanmıştır, ancak herhangi birinin yerel GMT ofsetini bir dize olarak istemesi durumunda, örneğin "+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
Doğru yapmak için 1st dolgu ile değiştirmeniz gerekir pad(parseInt(Math.abs(offset/60)), 2)... aksi takdirde benim durumumda olduğu gibi +5.530 elde edebilirsiniz ... im matematik kat vb burada daha iyi bir şey olup olmayacağından emin değilim .... ama bu atleast bana beklendiği gibi + 0530 veriyor
Abhinav Singh

Tam aradığım şey. Teşekkürler !
codesnooker

bu doğru sonucu verecektir: this.pad (Math.floor ((Math.abs (ofset / 60))), 2)
Vivek

Pad işlevinizi kullanmak yerine bunu daha kolay buluyorum: offset = (ofset <0? "+": "-") + ("0000" + parseInt ((Math.abs (ofset / 60)))) .slice (-4)
flurbius

67

Kullanabilirsiniz:

an-saat dilimi

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

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

Tarayıcı zaman dilimi algılaması, tarayıcı tarafından sağlanan çok az bilgi olduğu için, doğru şekilde almak oldukça zordur.

Moment Timezone , tarayıcı ortamı hakkında mümkün olduğunca fazla bilgi toplamak için mevcut yıl boyunca Date.getTimezoneOffset()ve Date.toString()bir avuç anı kullanır . Daha sonra bu bilgileri yüklenen tüm saat dilimi verileriyle karşılaştırır ve en yakın eşleşmeyi döndürür. Bağlar olması durumunda, en fazla nüfusa sahip şehrin saat dilimi döndürülür.

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

12
Bu kabul edilen cevap olmalı. Bu, ofset yerine gerçek saat dilimi adını veren tek addır . Saat dilimi ofsetinin addan türetilebileceğini unutmayın, tersi doğru değildir. DST ve diğer incelikler nedeniyle, birden fazla zaman dilimi yalnızca yılın belirli günlerinde aynı dengelemeye sahip olabilir.
Romain G

1
Bunun için yerel bir çözüm var - Intl API'sı . Moment.js o gün için harika bir kütüphane olsa da, şu anda çok daha küçük alternatifler var ( dayjs , date-fns ). An çok büyük ; lütfen istemci uygulamaları için önermeyin.
Dan Dascalescu

43

Projemde saat dilimini hh:mmbiçiminde döndüren bir işlev yazdım . Umarım bu birine yardımcı olabilir:

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

Çalışma keman


1
Teşekkür ederim! İhtiyacım olan bu!
Jeremy Moritz

15

Hem uzaklığı hem de saat dilimini veren tek satır , yeni bir Date nesnesinde yalnızca toTimeString () öğesini çağırmaktır . MDN'den:

toTimeString()Yöntem Amerikan İngilizcesi Okunabilir biçimde Date nesnesinin saat bölümünü döndürür.

Yakalama, saat diliminin standart IANA biçiminde olmamasıdır; "kıta / şehir" IANA biçiminden biraz daha kullanıcı dostudur . Denemek:

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

California'da şu anda toTimeString()döner Pacific Daylight TimeIntl API döndürür iken America/Los_Angeles. Kolombiya'da olsun istiyorum Colombia Standard Time, vsAmerica/Bogota .

Bu soruya verilecek diğer pek çok yanıtın Date.toString () yöntemini çağırarak aynı bilgileri almaya çalıştığını unutmayın. MDN'nin açıkladığı gibi bu yaklaşım o kadar güvenilir değildir :

Tarih örnekleri, zaman içindeki belirli bir noktayı ifade eder. ToString () öğesini çağırmak, Amerikan İngilizcesinde okunabilir bir biçimde biçimlendirilen tarihi döndürür. [...] Bazen zaman bölümünün bir dizesinin elde edilmesi arzu edilir; böyle bir şey,toTimeString() .

toTimeString()ECMA-262 uygulanması uyumlu bir motor elde dizede farklı olabilir, çünkü yöntem özellikle faydalıdır toString()için Datebiçimi uygulama bağımlı olarak, nesnelerin; basit dizi dilimleme yaklaşımları birden fazla motorda tutarlı sonuçlar vermeyebilir.


13

deneyin getTimezoneOffset()bir Datenesne:

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

Bu yöntem, saat dilimi ofsetini dakika olarak döndürür; bu, GMT ile yerel saat arasındaki dakika cinsinden farktır.


9

JavaScript:

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


3
Bu cevap önceki cevapların vermediğini ne sağlıyor?
Dan Dascalescu

7

İle moment.js :

moment().format('zz');

6
zve zz1.6.0 bkz itibariyle kullanım dışı edilmiş momentjs.com/docs/#/displaying/format
MrUpsidown

3
@MrUpsidown şimdi ZveZZ
brauliobo

4
@brauliobo Bu parametreler aynı şeyi döndürmez. z ve zz, saat dilimini döndürdü, örneğin CST, ancak Z ve ZZ ofseti döndürdü, örneğin -0600.
Luca Spiller

Son dokümanlar şovu .zoneAbbr()değiştirildi zve zz. Buradaki
tabish89

1
Moment.js o gün için harika bir kütüphane olsa da, şu anda çok daha küçük alternatifler var ( dayjs , date-fns ). An çok büyük ; lütfen istemci uygulamaları için önermeyin.
Dan Dascalescu

6

İle , geçerli saat dilimini şu şekilde bulabilirsiniz:

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>


İle , geçerli saat dilimini şu şekilde bulabilirsiniz:

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>

Her iki API da dakikalar içinde utc ofseti döndürür.


Moment.js o gün için harika bir kütüphane olsa da, şu anda çok daha küçük alternatifler var ( dayjs , date-fns ). An çok büyük ; lütfen istemci uygulamaları için önermeyin.
Dan Dascalescu

1
"Dayjs ile, geçerli saat dilimi olarak bulabilirsiniz" tam olarak doğru değildir - saat dilimini değil, yalnızca ofseti bulacaksınız . Ayrıca, Dayjs'in saat dilimi desteği yok . Onun .utcOffset () yöntemi yerel üzerinde basit bir sarmalayıcıdır getTimezoneOffset().
Dan Dascalescu

4

Saat diliminde saat dilimi

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

Yorumda belirttiğiniz gibi kesin olmak istiyorsanız, bu şekilde denemelisiniz.

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


Tam bir saat olmadığında, GMT-4.5'e döndüğü Venezuela gibi saat dilimleri için çalışmaz
Mirko

Evet bu doğru. 0.5, 0.5 x 30 dakika anlamına gelir. Sanırım bunu neden 0,5 veriyor?
Abrar Jahin

evet, bu yüzden GMT-4.5 geçerli bir saat dilimi değil, GMT-4: 30
Mirko

@Mirko şimdi cevabın ikinci kısmı sizin için
Abrar Jahin

Daha kesin olmak istiyorsanız, GMT yerine UTC kullanın, [Hilton ve McCarthy 2013, s. 231-2. ], ayrıca bkz. wikipedia GMT - ( en.wikipedia.org/wiki/Greenwich_Mean_Time )
Tom Kuschel

3

İhtiyacınız olan tek şey "MST" veya "EST" saat dilimi kısaltmasıysa:

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

Kullanımı Date.toString()güvenilir değildir ve MDN bunun nedenini açıklar. Ben onların dokümanlardan ilgili bölümü yapıştırdıktan Cevabıma .
Dan Dascalescu

3

Bu sonuç operatörünün saat dilimine zıt olduğunu görün.Biraz matematik işlevi uygulayın, sonra num'u daha az veya daha fazla doğrulayın.

resim açıklamasını buraya girin

MDN belgesine bakın

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

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

console.log(res)


1
negatif değer, bazı sorun
Arun Prasad ES

1
Neden round? Olmalı floor, değil mi?
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;
}

Örnek: 21 Haziran 2018, Per 18:12:50 GMT + 0530 (Hindistan Standart Saati)

O / P: +0530


Kullanımı Date.toString()güvenilir değildir ve MDN bunun nedenini açıklar. Ben onların dokümanlardan ilgili bölümü yapıştırdıktan Cevabıma .
Dan Dascalescu


2

Bu değer kullanıcının makinesinden ve her zaman değiştirilebilir, bu yüzden önemli olmadığını düşünüyorum, sadece yaklaşık bir değer almak ve daha sonra sunucumda GMT'ye dönüştürmek istiyorum.

Örneğin, Tayvanlıyım ve benim için "+8" döndürüyor.

Çalışma örneği

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>

Sonuç

+8

2

Üzerinde new Date() yapabileceğiniz saat dilimi adını almak için ofseti alabilirsiniz:

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

()tarihin sonundaki, yani saat diliminin adı arasındaki değeri alırsınız .


Kullanımı Date.toString()güvenilir değildir ve MDN bunun nedenini açıklar. Ben onların dokümanlardan ilgili bölümü yapıştırdıktan Cevabıma . Ayrıca, bu cevap en az 3 kez verilmiştir.
Dan Dascalescu

2

Bu benim çözümüm olurdu:


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

1

Alternatif olarak new Date().getTimezoneOffset()vemoment().format('zz') , ayrıca kullanabilirsiniz:

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 da oldukça buggy ve bakımsız ( https://bitbucket.org/pellepim/jstimezonedetect/issues?status=new&status=open )


Moment.js o gün için harika bir kütüphane olsa da, şu anda çok daha küçük alternatifler var ( dayjs , date-fns ). An çok büyük ; lütfen istemci uygulamaları için önermeyin.
Dan Dascalescu

1

OffSet'i postive dönüştürmek için bunu kullanın:

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

-2

Sadece 3 harfli dize ("PDT" gibi) arıyordu ve Marquez'in cevabını denedim ama çapraz tarayıcı desteği için biraz ince ayar yapmak zorunda kaldım. Neyse ki, dize son potansiyel eşleşme :)

İşte yaptığım şey, CoffeeScript'te:

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

IE8, IE9, Safari 9, Firefox 44 ve Chrome 48'de çalışır


2
Gerçi 4 harfli zaman dilimleri vardır - dikkatli olun: Örneğin CEST (Orta Avrupa Yaz Saati)
jbrosi

Kullanımı Date.toString()güvenilir değildir ve MDN bunun nedenini açıklar. Ben onların dokümanlardan ilgili bölümü yapıştırdıktan Cevabıma .
Dan Dascalescu

-3

Sadece moment.js ve jstz.js'yi dahil etmelisiniz

<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>

ve ondan sonra

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

</script>

-3

Bu benim için çok iyi bir iş:

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

1
Herhangi bir açıklama var mı?

-4

bunu deneyebilirsiniz. mevcut makine zamanını döndürür

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


Bence şu şekilde yapılmalı new Date(new Date().getTime()); : "Cum 28 Aralık 2018 10:15:23 GMT + 0100 (Orta Avrupa Standart Saati) {}"
darmis

-4

Bu işi yapacak.


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

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

Tanımsız

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.