Yaz Saati Uygulamasının (DST) etkin olup olmadığını ve eğer öyleyse ofseti nasıl kontrol edebilirim?


154

Bu, bunun için gerekli olan JS kodumun bir parçasıdır:

var secDiff = Math.abs(Math.round((utc_date-this.premiere_date)/1000));
this.years = this.calculateUnit(secDiff,(86400*365));
this.days = this.calculateUnit(secDiff-(this.years*(86400*365)),86400);
this.hours = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)),3600);
this.minutes = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)),60);
this.seconds = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)-(this.minutes*60)),1);

"Önce" datetime almak istiyorum, ancak DST kullanımda ise tarihler 1 saat kapalıdır. DST'nin etkili olup olmadığını nasıl kontrol edeceğimi bilmiyorum.

Yaz saatinin ne zaman başladığını ve bittiğini nasıl bilebilirim?

Yanıtlar:


313

Bu kod, Yaz Saati Uygulaması (DST) yerine Standart Saat sırasında daha büyük bir değer getTimezoneOffsetdöndüren gerçeği kullanır . Böylece Standart Süre sırasında beklenen çıktıyı belirler ve verilen tarihin çıktısının aynı (Standart) veya daha az (DST) olup olmadığını karşılaştırır.

UTC'nin batısındaki bölgeler için genellikle negatif saat olarak belirtilen (UTC'nin arkasında "bulunduğundan) pozitif dakika sayısını getTimezoneOffsetdöndürdüğünü unutmayın . Örneğin, Los Angeles UTC – 8 saat Standart, UTC-7 saat DST'dir. Aralık (kış, Standart Zaman) yerine Aralık (pozitif 480 dakika) döndürür . Doğu Yarımküre için negatif sayılar döndürür ( bunun "önde" olmasına rağmen, kışın Sydney için ( UTC + 10 saat ).getTimezoneOffset480-480-600

Date.prototype.stdTimezoneOffset = function () {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}

Date.prototype.isDstObserved = function () {
    return this.getTimezoneOffset() < this.stdTimezoneOffset();
}

var today = new Date();
if (today.isDstObserved()) { 
    alert ("Daylight saving time!");
}

28
Bunun uluslararası alanda çalıştığını doğrulayabilirim. Şu anda, hem 1 Ocak hem de 1 Temmuz'un DST döneminin ikisinde veya her ikisinde olduğu herhangi bir DST formunu kullanan herhangi bir saat dilimi yoktur. Ayrıca, TZDB'deki tüm zaman dilimlerinde ( önemsiz bir istisna dışında ) iki ofsetten daha büyük olanı DST ofsetidir. JavaScript getTimezoneOffsetters değeri döndürdüğünden Math.max, aslında standart ofseti döndürür . Kod doğrudur.
Matt Johnson-Pint

7
Ancak, herhangi bir saat dilimi tanımını 1 Ocak ve 1 Temmuz hem DST'de hem de her ikisinde birden olacak şekilde değiştirirse olmayacak (ve DST hala geçerli) olacak şekilde değiştirirse, bu kod bu bölgede çalışmaz.
Matt Johnson-Pint

9
Bu genel olarak işe yaramaz, örneğin belirli yıllarda DST'yi gözlemlemeyen ülkeler vardır ve ayrıca bazı ülkeler Ramazan ayında DST'yi geri döndürür. Bunun yanında, Date için ECMAScript tanımı bozulur ve bazı uygulamalarda TZ ortam değişkeninin işlenmesi de bozulur. Bütün bunların birleşimi bu yöntemi güvenilmez kılar. Date kullanmayan bir kütüphane kullanmaktan daha iyisiniz, örneğin timezonecomplete
rogierschouten

5
Bu kod, örneğin Güney Afrika veya İzlanda gibi DST'yi gözlemlemeyen ülkelerde çalışmaz; yani bu ülkelerdeki diğer saat dilimleriyle karşılaştırmak için kullanırsanız, oradaki doğru zamanları göstermez. UTC'yi sonuna kadar kullanmanızı öneririz ve zamanın belirli bir DST aralığında olup olmadığını manuel olarak kontrol edin. O zaman DST elde etmek için sadece normal zaman UTC ofsetini +1 ile değiştirmek meselesidir.
Kebman

1
Bu nasıl doğru olabilir? Örneğin Almanya 2016-10-30'da DST'ye girerken, ABD bir hafta sonra 2016-11-06'da girdi. Bunun gibi kötü bilgiler, bunun gibi şeylerin gerçekleşmesine neden olan şeydir: macworld.co.uk/news/apple/…
Daniel F

22

İki tarih oluşturun: biri Haziran ayında, biri Ocak ayında. GetTimezoneOffset () değerlerini karşılaştırın.

  • Ocak ofseti> Haziran ofseti ise, müşteri kuzey yarımkürede
  • Ocak ofseti <Haziran ofseti ise, müşteri güney yarımkürede
  • fark yoksa, istemci saat dilimi DST'yi gözlemlemez

Şimdi geçerli tarihin getTimezoneOffset () yöntemini kontrol edin.

  • Haziran, kuzey yarımkürede eşitse, geçerli saat dilimi DST'dir (+1 saat)
  • Ocak, güney yarımküreye eşitse, geçerli saat dilimi DST'dir (+1 saat)

Neden yarıkürelere ihtiyacınız var? geçerli tarih için getTimezoneOffset (), iki getTimezoneOffset () öğesinden daha küçük olana eşitse DST demek yeterli olmaz mı? [ve ofset ikisi arasındaki fark nedir?]
epeleg

Kabul edilen cevabın açıkça gösterdiği gibi hemisferlere ihtiyacınız yok :)
Jon Nylander

Bu işe yaramaz. Yapılacak en iyi şey UTC saatlerini kullandığınızdan ve istediğiniz bölge için ofseti manuel olarak ayarladığınızdan emin olmaktır. Ardından, aynı bölge için DST için başlangıç ​​ve bitiş değerlerini elle bulun (varsa). Ardından, o bölgenin zamanının DST aralığı içinde olup olmadığını kontrol etmek ve sonra +1 ile ilgili olarak ofseti güncellemek istersiniz. Bu, DST'yi gözlemleyen ve görmeyen ülkeleri karşılaştırmayı mümkün kılar.
Kebman

Soru, DST'nin şu anda müşterinin makinesi Kebman'ın saat diliminde geçerli olup olmadığını nasıl belirleyeceğidir, tarihleri ​​nasıl görüntüleyeceğinizi değil, web istemcileri bunu sizin için zaten ele alır.
Jon Nylander

Ocak ve Temmuz ayları arasında (veya Şubat ve Ağustos, Mart ve Eylül vb.) 6 ay arayla kontrol edersiniz.
kpull1

17

Bu cevap, kabul edilen cevaba oldukça benzer, ancak Dateprototipi geçersiz kılmaz ve iki yerine Yaz Saati Uygulamasının geçerli olup olmadığını kontrol etmek için yalnızca bir işlev çağrısı kullanır.


Fikir şu ki, hiçbir ülke 7 ay süren DST'yi gözlemlemediği için [1] , DST'yi gözlemleyen bir alanda Ocak ayındaki UTC saatinden sapma Temmuz ayındaki farktan farklı olacaktır.

Gün Işığından Yararlanma Saati saatleri ileri hareket ettirirken , JavaScript Standart Saat sırasında her zaman daha büyük bir değer döndürür . Bu nedenle, Ocak ve Temmuz arasında minimum ofseti elde etmek, DST sırasında saat dilimini dengeleyecektir.

Daha sonra tarih saat diliminin bu minimum değere eşit olup olmadığını kontrol ederiz. Eğer öyleyse, o zaman DST'deyiz; aksi halde değiliz.

Aşağıdaki işlev bu algoritmayı kullanır. Bir tarih nesnesi alır dve truebu tarih için gün ışığından yararlanma saati geçerliyse ve değilse döndürür false:

function isDST(d) {
    let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
    let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
    return Math.max(jan, jul) != d.getTimezoneOffset(); 
}

1
Bu işe yarar, ancak geçerli TimeZone'da DST yoksa, doğru da sonuçlanır, bu da doğru değildir. Bunu değiştirirseniz Math.max(...) != d.get...(), belirtilen saat diliminde DST gözlemlendiğinde ve tarih şu anda DST'de olduğunda doğru dönecektir. DST gözlenmezse veya tarih Standart ofsetle eşleşirse, yanlış döndürür.
GreySage

12

Bugün aynı sorunla karşı karşıya kaldım ancak gün ışığından yararlanma sistemimiz ABD'den farklı zamanlarda başladığı ve durduğu için (en azından benim anlayışımdan), biraz farklı bir rota kullandım.

var arr = [];
for (var i = 0; i < 365; i++) {
 var d = new Date();
 d.setDate(i);
 newoffset = d.getTimezoneOffset();
 arr.push(newoffset);
}
DST = Math.min.apply(null, arr);
nonDST = Math.max.apply(null, arr);

Ardından hangisinin eşleştiğini görmek için geçerli saat dilimi sapmasını DST ve DD olmayan ile karşılaştırmanız yeterlidir.


Biz de böyle yapıyoruz. Yani, DST'nin hedef saat diliminizde değiştiği yılın zamanlarını öğrenin ve geçerli gün ve en son değişiklik tarihi için ofsetleri hesaplayın. Ya bir saate göre farklılık gösterecek ya da eşit olacaklardır (söz konusu saat diliminin bir saat farkı olduğu varsayılarak).
Heather

365 değer oluşturmaya gerek yoktur, gün ışığından yararlanma gözlemlenmediğinde bile, ofsetteki bir değişiklik belirlenir belirlenmez duran bir ikili arama yaklaşımı çok daha verimli olmalıdır. Tüm bu yaklaşımlar, yerlerin her yıl gün ışığından yararlanma gözlemlediğini varsayar ki bu her zaman doğru değildir. Yerler zaman zaman gün ışığından yararlanma özelliğini benimser ve terk eder (ECMAScript, her ne zaman uygulansalar da, geçerli kuralları varsayar).
RobG

2
Rob - Nerede arama yapacağınızı bilmiyorsanız (örneğin aradığınız yer r test noktasının üstünde veya altında mı?)
epeleg

9

Matt Johanson'un Sheldon Griffin tarafından sağlanan çözüm yorumuna dayanarak aşağıdaki kodu oluşturdum:

    Date.prototype.stdTimezoneOffset = function() {
        var fy=this.getFullYear();
        if (!Date.prototype.stdTimezoneOffset.cache.hasOwnProperty(fy)) {

            var maxOffset = new Date(fy, 0, 1).getTimezoneOffset();
            var monthsTestOrder=[6,7,5,8,4,9,3,10,2,11,1];

            for(var mi=0;mi<12;mi++) {
                var offset=new Date(fy, monthsTestOrder[mi], 1).getTimezoneOffset();
                if (offset!=maxOffset) { 
                    maxOffset=Math.max(maxOffset,offset);
                    break;
                }
            }
            Date.prototype.stdTimezoneOffset.cache[fy]=maxOffset;
        }
        return Date.prototype.stdTimezoneOffset.cache[fy];
    };

    Date.prototype.stdTimezoneOffset.cache={};

    Date.prototype.isDST = function() {
        return this.getTimezoneOffset() < this.stdTimezoneOffset(); 
    };

Tüm yorumları ve daha önce önerilen cevapları ve özellikle de dikkate alarak tüm dünyalardan en iyi şekilde yararlanmaya çalışır:

1) Yıllık stdTimezoneOffset için sonucu önbelleğe alır, böylece aynı yıl içinde birden çok tarihi test ederken yeniden hesaplamanız gerekmez.

2) DST'nin (eğer varsa) mutlaka Temmuz ayında olduğunu varsaymaz ve bir noktada ve bir yerde herhangi bir ay olsa bile çalışacaktır. Ancak Performans açısından, Temmuz (veya aylara yakın) gerçekten DST ise daha hızlı çalışacaktır.

3) Daha da kötüsü, her ayın ilkinin getTimezoneOffset'ini karşılaştıracaktır. [ve bunu test edilen yılda bir kez yapın].

Hala yaptığı varsayım, DST süresi varsa bir aydan daha uzun olmasıdır.

Birisi bu varsayımı kaldırmak istiyorsa, döngüyü Aaron Cole tarafından sağlanan çözümde whats benzeri bir şeye dönüştürebilir - ancak yine de yarım yıl ileri atlayıp iki farklı ofset bulunduğunda döngüden çıkarım]


4

Moment.js kitaplığı, bir sağlar .isDst()zamanı nesneleri yöntem.

moment # isDST geçerli anın yaz saati uygulamasında olup olmadığını kontrol eder.

moment([2011, 2, 12]).isDST(); // false, March 12 2011 is not DST
moment([2011, 2, 14]).isDST(); // true, March 14 2011 is DST

Var moment = çalıştı ('moment'); this.logger.info (moment ([2011, 2, 12]). isDST ()); this.logger.info (moment ([2011, 2, 14]). isDST ()); her ikisi de yanlış
Logan_B

DST değişiklik tarihleri ülkeler arasında , hatta aynı ülkedeki eyaletler (Arizona eyaleti) arasında bile değişiklik gösterir . ABD'de 2011-03-13'te, Almanya'da 2011-03-31'de idi. Bu nedenle sonuç, çalışmak için yapılandırılan saat dilimine bağlı olarak değişir.
Daniel F

1
Arizona eyaleti içinde bile değişir timeanddate.com/time/us/arizona-no-dst.html
Daniel F

3

getTimezoneOffset()JavaScript yöntem olup, tarayıcıda 00:00 saat dilimi ofset dakika sayısını verir. Örneğin, Yaz Saati Uygulamasındaki (DST) America / New_York saat dilimi 300 sayısını döndürür. 300 dakika sıfırdan 5 saat farktır. 300 dakika 60 dakikaya bölünür 5 saattir. Her zaman dilimi sıfır zaman dilimi ile karşılaştırılır, +00: 00 / Etc / GMT / Greenwich zamanı.

MDN Web Belgeleri

Bilmeniz gereken bir sonraki şey, ofsetin gerçek zaman diliminin ters işaretine sahip olmasıdır.

Saat dilimleri hakkında bilgi İnternet Tahsisli Sayılar Kurumu (iana) tarafından sağlanır.

iana zaman dilimleri

İyi biçimlendirilmiş bir Zaman Dilimi tablosu joda.org tarafından sağlanır

joda-time Saat Dilimleri

+00: 00 veya Etc / GMT Greenwich zamanı

Tüm zaman dilimleri +00: 00 / "Etc / GMT" / Greenwich saatinden kaydırılmıştır

Yaz Saati Yaz aylarında her zaman "normal" saatten daha erken bir saattir. Saatlerinizi sonbahar mevsiminde yeniden ayarladınız. (Ne yapacağını hatırlamak için "Geri Çekil" sloganı)

Yani, Amerika / New_York Yaz Saati uygulamasında (kış) normal saatten bir saat önce. Örneğin, yaz aylarında New York'ta öğleden sonra normalde 17:00, şimdi Yaz Saati'nde Amerika / New_York saatidir. "America / New_York" adı, "Uzun Format" zaman dilimi adıdır. ABD'nin doğu kıyısı tipik olarak saat dilimlerini Doğu Standart Saati (EST) olarak adlandırır.

Bugünün saat dilimi ofsetini başka bir tarihin saat dilimi ofseti ile karşılaştırmak istiyorsanız, saat dilimi ofsetinin matematiksel işaretinin (+/- "Pozitif / Negatif") saat diliminin tersi olduğunu bilmeniz gerekir.

Joda.org adresindeki saat dilimi tablosuna bakın ve "America / New_York" için saat dilimini bulun. Standart Ofset'in önünde negatif bir işaret olacaktır.

Dünya kendi ekseni üzerinde saat yönünün tersine döner. Greenwich'teki güneşin doğuşunu izleyen bir kişi, New York'taki birisinin güneşin doğuşunu görmesinden 5 saat önce güneşin doğuşunu görür. ABD'nin Batı Kıyısı'ndaki biri, ABD'nin Doğu Kıyısı'ndaki bir kişi güneşin doğuşunu gördükten sonra güneşin doğuşunu görecek.

Tüm bunları bilmeniz için bir neden var. Böylece, yılın herhangi bir saat diliminde her zaman dilimini test etmenize gerek kalmadan, bazı JavaScript kodlarının DST durumunu doğru alıp almadığını mantıksal olarak belirleyebileceksiniz.

New York'ta Kasım ayının olduğunu ve saatlerin bir saat önce ayarlandığını düşünün. New York'ta yaz aylarında ofset 240 dakika veya 4 saattir.

Temmuz ayında bir tarih oluşturmak ve sonra ofset elde ederek bunu test edebilirsiniz.

var July_Date = new Date(2017, 6, 1);
var july_Timezone_OffSet = July_Date.getTimezoneOffset();

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

Tarayıcının geliştirici araçları konsol günlüğüne ne yazdıracak?

Yanıt: 240

Böylece, Ocak ayında bir tarih oluşturabilir ve tarayıcınızın kış sezonu için bir saat dilimi farkı için ne döndüğünü görebilirsiniz.

var Jan_Date = new Date(2017, 0, 1);//Month is zero indexed - Jan is zero
var jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

Yanıt: 300

Açıkçası 300, 240'dan daha büyüktür. Peki, bu ne anlama geliyor? Kış ofsetini yaz ofsetinden daha büyük olan test kodunu yazmalı mısınız? Yoksa yaz mevsimi kış mevsiminden daha az mı? Yaz ve kış saat dilimi ofsetleri arasında bir fark varsa, bu saat dilimi için DST'nin kullanıldığını varsayabilirsiniz. Ancak bu, bugün tarayıcıların saat dilimi için DST kullanıp kullanmadığını söylemez . Bu nedenle, bugün için saat dilimini dengelemeniz gerekir.

var today = new Date();
var todaysTimeZone = today.getTimezoneOffset();

console.log('todaysTimeZone : ' + todaysTimeZone)

Cevap:? - Yılın zamanına bağlı

Bugünün saat dilimi uzaklığı ve yaz saati bölge uzaklığı aynıysa, VE yaz ve kış saat dilimi uzaklıkları farklıysa, o zaman mantıksal kesinti ile, bugün DST'de OLMAMALIDIR.

Yaz ve kış saat dilimi ofsetlerini karşılaştırmayı atlayabilir, (DST'nin bu saat dilimi için kullanılıp kullanılmadığını bilmek) ve sadece bugünün saat dilimi ofsetini yaz TZ ofsetiyle karşılaştırabilir ve her zaman doğru cevabı alabilir misiniz?

today's TZ Offset !== Summer TZ Offset

Peki, bugün kışın mı yaz mı? Bunu biliyorsan, aşağıdaki mantığı uygulayabilirsin:

if ( it_is_winter && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Ama sorun şu ki, bugünün tarihinin kış mı yoksa yaz mı olduğunu bilmiyorsunuz. Her saat dilimi, DST'nin ne zaman başlayıp durduğuna ilişkin kendi kurallarına sahip olabilir. Dünyadaki her saat dilimi için her saat diliminin kurallarını izlemeniz gerekir. Yani, daha iyi ve daha kolay bir yol varsa, daha iyi ve daha kolay bir yol da yapabilirsiniz.

Geriye kalan şey, bu saat diliminin DST kullanıp kullanmadığını bilmeniz ve ardından günün saat dilimi ofsetini yaz saati dilimi ofseti ile karşılaştırmanızdır. Bu size her zaman güvenilir bir cevap verecektir.

Son mantık:

if ( DST_Is_Used_In_This_Time_Zone && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Tarayıcıdaki saat diliminin DST kullanıp kullanmadığını belirleme işlevi:

function is_DST_Used_In_This_TimeZone() {
  var Jan_Date, jan_Timezone_OffSet, July_Date, july_Timezone_OffSet 
      offsetsNotEqual, thisYear, today;

  today = new Date();//Create a date object that is now
  thisYear = today.getFullYear();//Get the year as a number

  Jan_Date = new Date(thisYear, 0, 1);//Month is zero indexed - Jan is zero
  jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

  console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

  July_Date = new Date(thisYear, 6, 1);
  july_Timezone_OffSet = July_Date.getTimezoneOffset();

  console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

  offsetsNotEqual = july_Timezone_OffSet !== jan_Timezone_OffSet;//True if not equal

  console.log('offsetsNotEqual: ' + offsetsNotEqual);

  return offsetsNotEqual;//If the offsets are not equal for summer and
       //winter then the only possible reason is that DST is used for
       //this time zone
}

1
Dateandtime.com'a göre DST, 10 Mart 2019'da başladı ve bu nedenle yaz aylarında, kış değil ve New York'un DST ofseti -5 değil -4'tür.
jk7

Cevaba bir iyileştirme veya düzeltme yapılması gerekiyorsa, lütfen bir düzenleme yapın ve incelenecektir.
Alan Wells

2

Moment.js kullanın ( https://momentjs.com/ )

moment().isDST(); Gün ışığı tasarrufu gözlemlenirse size verecektir.

Ayrıca sizin için göreceli zamanı hesaplamak için yardımcı işlevi vardır. Manuel hesaplamalar yapmanız gerekmez, örn.moment("20200105", "YYYYMMDD").fromNow();


1

Yakınız ama biraz uzaktasınız. Kendi saatinizin bir sonucu olduğu için asla kendi zamanınızı hesaplamanıza gerek yoktur. Bulunduğunuz yerde gün ışığından yararlanma saatini kullanıp kullanmadığınızı algılayabilir, ancak ofset tarafından üretilen uzak bir konum için kullanamazsınız:

newDateWithOffset = new Date(utc + (3600000*(offset)));

Bu hala yanlış ve DST içinde ise bir saat kapalı olacak. Halihazırda DST'lerinin içindeyken veya istemiyorlarsa bir uzak zaman hesabına ihtiyacınız vardır ve buna göre ayarlayın. bunu hesaplamayı deneyin ve saatinizi - 2/1/2015 diyelim olarak değiştirin ve saati DST dışındaymış gibi bir saat geri sıfırlayalım. Ardından, hala 2 saat geride olması gereken bir yer için bir ofset hesaplayın. İki saatlik pencereden bir saat önce gösterilir. Yine de saati hesaba katmanız ve ayarlamanız gerekir. NY ve Denver için yaptım ve her zaman Denver (saat önde) yanlış gidin.


1

Moment.js kullanarak bunu buldum kütüphanesini burada açıklanan bazı kavramlarla (Ocak - Haziran karşılaştırması) kullanmanın çok iyi çalıştığını .

Bu basit işlev, kullanıcının bulunduğu saat diliminin Yaz Saati Uygulamasını gözlemleyip gözlemlemediğini döndürür:

function HasDST() {
    return moment([2017, 1, 1]).isDST() != moment([2017, 6, 1]).isDST();
}

Bunun (Windows'ta) çalışıp çalışmadığını kontrol etmenin basit bir yolu, saat diliminizi DST olmayan bir bölgeye değiştirmek, örneğin Arizona yanlış, EST veya PST doğru döndürecektir.

resim açıklamasını buraya girin


1

Tüm Zaman Dilimlerinde Çalışan Geleceğe Hazır Çözüm

  1. Izin vermek xgün ışığında çarpanlarına ayırmadan ilgi yıl beklenen milisaniye olsun.
  2. Izin vermek Epochy beri milisaniye sayısı faiz tarihinin başından .
  3. Izin vermek tam tarih ve zaman Dönemiz beri milisaniye sayısı
  4. Let tikisinin çıkarma olacak xve ygelen z: z - y - x. Bu, DST nedeniyle ofseti verir.
  5. Eğer tsıfır, o zaman DST yürürlükte değildir. tSıfır değilse , DST geçerlidir.

(function(){"use strict";
function dstOffsetAtDate(dateInput) {
    var fullYear = dateInput.getFullYear()|0;
	// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
 	//   except if it can be exactly divided by 100, then it isn't (2100,2200,etc)
 	//	  except if it can be exactly divided by 400, then it is (2000, 2400)"
	// (https://www.mathsisfun.com/leap-years.html).
    var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
	// (fullYear & 3) = (fullYear % 4), but faster
    //Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
    var fullMonth = dateInput.getMonth()|0;
    return (
        // 1. We know what the time since the Epoch really is
        (+dateInput) // same as the dateInput.getTime() method
        // 2. We know what the time since the Epoch at the start of the year is
        - (+new Date(fullYear, 0, 0)) // day defaults to 1 if not explicitly zeroed
        // 3. Now, subtract what we would expect the time to be if daylight savings
        //      did not exist. This yields the time-offset due to daylight savings.
        - ((
            ((
                // Calculate the day of the year in the Gregorian calendar
                // The code below works based upon the facts of signed right shifts
                //    • (x) >> n: shifts n and fills in the n highest bits with 0s 
                //    • (-x) >> n: shifts n and fills in the n highest bits with 1s
                // (This assumes that x is a positive integer)
                (31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
                ((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
                (31 & ((2-fullMonth) >> 4)) + // March
                (30 & ((3-fullMonth) >> 4)) + // April
                (31 & ((4-fullMonth) >> 4)) + // May
                (30 & ((5-fullMonth) >> 4)) + // June
                (31 & ((6-fullMonth) >> 4)) + // July
                (31 & ((7-fullMonth) >> 4)) + // August
                (30 & ((8-fullMonth) >> 4)) + // September
                (31 & ((9-fullMonth) >> 4)) + // October
                (30 & ((10-fullMonth) >> 4)) + // November
                // There are no months past December: the year rolls into the next.
                // Thus, fullMonth is 0-based, so it will never be 12 in Javascript
                
                (dateInput.getDate()|0) // get day of the month
				
            )&0xffff) * 24 * 60 // 24 hours in a day, 60 minutes in an hour
            + (dateInput.getHours()&0xff) * 60 // 60 minutes in an hour
            + (dateInput.getMinutes()&0xff)
        )|0) * 60 * 1000 // 60 seconds in a minute * 1000 milliseconds in a second
        - (dateInput.getSeconds()&0xff) * 1000 // 1000 milliseconds in a second
        - dateInput.getMilliseconds()
    );
}

// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);

// Performance Benchmark:
console.time("Speed of processing 16384 dates");
for (var i=0,month=date.getMonth()|0; i<16384; i=i+1|0)
    date.setMonth(month=month+1+(dstOffsetAtDate(date)|0)|0);
console.timeEnd("Speed of processing 16384 dates");
})();

Yukarıdaki kod snippet'inin birçok nedenden dolayı burada yayınlanan diğer tüm cevaplardan daha üstün olduğuna inanıyorum.

  • Bu cevap tüm zaman dilimlerinde, hatta Antarktika / Casey'de çalışır .
  • Gün ışığından yararlanma çok değişebilir. Bundan 20 yıl sonra, bazı ülkelerde normal 2 yerine 3 DST periyodu olabilir. Bu kod, DST ofsetini yalnızca DST'nin etkin olup olmadığını değil, milisaniye cinsinden döndürerek bu durumu ele alır.
  • Yılın aylarının büyüklüğü ve Artık Yılların çalışma şekli, zamanımızı güneşin yolunda tutmaya mükemmel uyum sağlar. Heck, o kadar mükemmel çalışıyor ki, tek yaptığımız sadece burada ve orada sadece birkaç saniye ayarlamak . Şimdiki artık sistemimiz 24 Şubat 1582'den beri yürürlükte ve öngörülebilir gelecek için yürürlükte kalacaktır.
  • Bu kod, DST kullanmayan saat dilimlerinde çalışır.
  • Bu kod, DST'nin uygulanmasından önceki tarihi zamanlarda (1900'ler gibi) çalışır.
  • Bu kod maksimum tamsayı için optimize edilmiştir ve dar bir döngüde çağrıldığında size sorun vermeyecektir. Yukarıdaki kod snippet'ini çalıştırdıktan sonra, performans karşılaştırmasını görmek için çıktının en altına gidin. Bilgisayarım Chrome'da ~ 97 ms'de 16384 tarihi işleyebilir.

Ancak, 2'den fazla DST süresi için hazırlık yapmıyorsanız, DST'nin bir boole olarak etkili olup olmadığını belirlemek için aşağıdaki kod kullanılabilir.

function isDaylightSavingsInEffect(dateInput) {
    // To satisfy the original question
    return dstOffsetAtDate(dateInput) !== 0;
}

0

Geçenlerde UTC ve DST ile bir tarih dizesi oluşturmanız gerekiyordu ve Sheldon'ın cevabına dayanarak bunu bir araya getirdim:

Date.prototype.getTimezone = function(showDST) {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);

    var utcOffset = new Date().getTimezoneOffset() / 60 * -1;
    var dstOffset = (jan.getTimezoneOffset() - jul.getTimezoneOffset()) / 60;

    var utc = "UTC" + utcOffset.getSign() + (utcOffset * 100).preFixed(1000);
    var dst = "DST" + dstOffset.getSign() + (dstOffset * 100).preFixed(1000);

    if (showDST) {
        return utc + " (" + dst + ")";
    }

    return utc;
}
Number.prototype.preFixed = function (preCeiling) {
    var num = parseInt(this, 10);
    if (preCeiling && num < preCeiling) {
        num = Math.abs(num);
        var numLength		 = num.toString().length;
        var preCeilingLength = preCeiling.toString().length;
        var preOffset		 = preCeilingLength - numLength;
        for (var i = 0; i < preOffset; i++) {
            num = "0" + num;
        }
    }
    return num;
}
Number.prototype.getSign = function () {
    var num	 = parseInt(this, 10);
    var sign = "+";
    if (num < 0) {
        sign = "-";
    }
    return sign;
}

document.body.innerHTML += new Date().getTimezone() + "<br>";
document.body.innerHTML += new Date().getTimezone(true);
<p>Output for Turkey (UTC+0200) and currently in DST: &nbsp; UTC+0300 (DST+0100)</p>
<hr>


0

Kullanırken bir sorun mu var? Date.toString().indexOf('Daylight Time') > -1

"" + new Date()

Cmt 01 01 100050 00:00:00 GMT-0500 (Doğu Standart Zamanı)

"" + new Date(...)

Paz 01 Mayıs 100033 00:00:00 GMT-0400 (Doğu Yaz Saati)

Bu, tüm tarayıcılarla uyumlu görünüyor.


Evet, dünyanın her yerinde çalışmıyor. Avrupa'da yaz aylarında, olsun"Thu Jul 02 2020 14:07:01 GMT+0200 (Central European Summer Time)"
Tadej Krevh

0

ES6 Tarzı

Math.min(...[0, 6].map(v => new Date(95, v, 1).getTimezoneOffset() * -1));
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.