2012-08-09 104 views
106

這一點我的JS代碼,其中這是需要:如何檢查DST(夏令時)是否有效以及偏移量是多少?

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

我想要得到的日期時間在以前,但如果DST正在使用,則日期1小時關閉。我不知道如何檢查DST是否在使用中。

我如何知道夏令時開始和結束的時間?

回答

233

過期的鏈接給出的代碼會告訴你夏令時是否生效。它使用getTimezoneOffset在DST和標準時間期間返回不同值的事實,並比較兩者之間的差異。 (例如紐約在DST期間正常返回-5和-4)

請注意,我不知道國際時區的錯綜複雜情況,只測試過它會爲我的時區返回正確的結果。但代碼似乎很穩固。

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

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.dst = function() { 
    return this.getTimezoneOffset() < this.stdTimezoneOffset(); 
} 
+19

我可以驗證這個工程國際。目前沒有使用任何形式的DST的時區,其中1月1日和7月1日都在DST期間或兩者都有。此外,在TZDB的所有時區([有一個微不足道的例外](http://en.wikipedia.org/wiki/Antarctica/Cas​​ey)),兩個偏移量中較大的一個是DST偏移量。由於JavaScript的'getTimezoneOffset'返回反值,因此'Math.max'確實返回*標準*偏移量。代碼是正確的。 – 2013-04-08 21:39:33

+3

然而,如果任何時區改變其定義,使得1月1日和7月1日都在DST中,或者在DST中都有* not *(並且DST仍然適用),則此代碼在該區域中將不起作用。 – 2013-04-08 21:40:37

+3

這很好。能夠設置一個內部常量真的很不錯,如: 'TIMEZONE_OFFSET =((new Date())。dst())?'-04:00':'-05:00'' – nessur 2013-06-20 18:57:11

16

創建兩個日期:一個在六月,一個在一月。比較它們的getTimezoneOffset()值。

  • 如果一月偏移「6月偏移,客戶端是在北半球
  • 如果一月偏移<月偏移,客戶端是在南半球
  • 如果沒有差異,客戶端時區不遵守DST

現在檢查當前日期的getTimezoneOffset()。

  • 如果等於至6月,北半球,則當前時區爲DST(+1小時),
  • 如果等於月,南半球,則當前時區爲DST(+1小時),
+0

爲什麼你需要半球?如果說當前日期的getTimezoneOffset()等於兩個getTimezoneOffset()中的較小者,那麼它的DST是否還不足以說明問題? [和抵消是兩者之間的差異?] – epeleg 2014-11-06 08:53:05

+0

你不需要半球,因爲接受的答案清楚地表明:) – 2014-11-06 11:32:09

+0

這不會工作。最好的辦法是確保您使用UTC時間並手動設置您想要的區域的偏移量。然後手動查找相同區域的DST的開始和結束(如果有的話)。然後,您要檢查該區域的時間是否在DST範圍內,然後用+1相應更新偏移量。這使得可以比較各國觀察DST的情況,以及那些沒有的情況。 – Kebman 2015-06-27 18:34:02

11

我面對今天這個同樣的問題,但由於我們的夏令時開始,並在(從我的理解,至少)來自美國不同時間,我用了一個稍微不同的路線停止..

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

然後,您只需將當前時區偏移量與DST和nonDST進行比較,以查看哪個匹配。

+0

我們也是這樣做的。也就是說,計算DST在您的目標時區中更改的年份的時間,並計算當前日期和最近更改日期的偏移量。它們要麼相差一小時,要麼相等(假設所討論的時區是一個小時的偏移量)。 – Heather 2012-11-13 17:55:23

+0

無需創建365個值,即使在未觀察到夏令時的情況下,只要確定了偏移量的變化就會立即停止的二進制搜索方法應該效率更高。所有這些方法都假定地方每年都要遵守夏令時,這並不一定是真實的。地方時常採用和放棄夏令時(儘管ECMAScript採用現行規則,無論它們是什麼區域,總是適用)。 – RobG 2014-10-16 02:09:18

+1

Rob - 如果您不知道在哪裏搜索(即您尋找的地點是否高於或低於您的測試點?),您如何通過二分查找來實現這一點? – epeleg 2014-11-06 08:46:48

7

基於由謝爾登格里芬提供的解決方案馬特·約翰森的評論我創建了下面的代碼:

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

它試圖以獲得最佳的考慮到所有的意見都世界和先前建議的回答和具體的它:

1)緩存結果爲每年stdTimezoneOffset,以便您不需要在同一年測試多個日期時重新​​計算它。

2)它不假定DST(如果它存在的話)必然在7月, 並且即使它會在某個時間點並且某個地方是任何月份也可以工作。 然而,如果確實是7月(或接近數月)確實是夏令時,那麼性能方面會更快。

3)更糟糕的情況是它會比較每個月的第一個月的getTimezoneOffset。 [並且每年測試一次]。

它仍然做的假設是,如果有DST期間大於一個月。

如果有人想要消除這個假設,他可以將環路變成更像Aaron Cole提供的解決方案中的東西 - 但是當我發現兩個不同的偏移時,我仍然會跳過半年,並跳出循環]

1

Your're關閉,但有點關閉。你永遠不需要計算自己的時間,因爲它是你自己的時鐘的結果。它可以,如果你使用的是夏令時間在自己的位置而不是由偏移產生的遠程位置檢測:

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

這仍然將是錯誤的,並關閉一個小時,如果他們在DST。您需要遠程時間賬戶,如果他們目前在他們的DST內並且相應地進行調整。嘗試計算這一點,並將您的時鐘更改爲 - 可以說2015年2月1日,並將時鐘重置爲一小時,就好像夏令時之外。然後計算一個應該仍然落後2小時的地方的偏移量。它將在兩小時之前顯示一小時。您仍然需要考慮小時並進行調整。我爲紐約和丹佛做過,並且總是在丹佛進行不正確的(小時前)。

5

已經解決了,但只是認爲我應該添加我做的方式(以防人們感興趣)。

function isDST(t) { //t is the date object to check, returns true if daylight saving time is in effect. 
    var jan = new Date(t.getFullYear(),0,1); 
    var jul = new Date(t.getFullYear(),6,1); 
    return Math.min(jan.getTimezoneOffset(),jul.getTimezoneOffset()) == t.getTimezoneOffset(); 
} 

與例外答案(janurary和july時區偏移)的工作方式相同,然後返回條件。

0

我最近需要創建一個日期字符串UTC和DST,以及基於Sheldon的答案,我把這個在一起:

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 \t \t = num.toString().length; 
 
     var preCeilingLength = preCeiling.toString().length; 
 
     var preOffset \t \t = preCeilingLength - numLength; 
 
     for (var i = 0; i < preOffset; i++) { 
 
      num = "0" + num; 
 
     } 
 
    } 
 
    return num; 
 
} 
 
Number.prototype.getSign = function() { 
 
    var num \t = 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>

1

moment.js庫提供的.isDst()方法,其時間對象。

moment#isDST檢查當前時刻是否在夏令時。

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

我發現,使用Moment.js庫的一些這裏描述的概念(比較1至6月)的作品非常好。

這個簡單的函數將返回是否該用戶是在時區遵守夏令時:

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

一個簡單的方法來檢查這個工程(在Windows上)是你的時區更改爲非DST區域,例如亞利桑那州將返回錯誤,而EST或PST將返回true。

enter image description here

0

getTimezoneOffset()該方法在JavaScript中,在瀏覽器中,返回分鐘從00:00時區偏移的數目。例如,夏令時(DST)中的America/New_York時區返回數字300. 300分鐘與零差距爲5小時。 300分鐘除以60分鐘是5小時。每個時區都與零時區相比,+00:00/Etc/GMT /格林威治時間。

MDN Web Docs

,你必須知道的下一件事,就是偏移具有實際的時區的符號相反。

有關時區的信息由互聯網編號分配機構保持(IANA)

iana time zones

一個很好的格式化時區的表由joda.org

joda-time Time Zones

供給+00:00或其他格林威治時間

所有時區ar e從+00:00 /「Etc/GMT」/格林尼治時間偏移

夏令時總是比夏季的「正常」時間早。你在秋季設置你的時鐘。 (「回退」的口號,以記住該做什麼)

因此,美國/紐約時間在夏令時(冬季)是一小時前的正常時間。所以,例如,通常是下午5點。在夏天的紐約市下午,現在是下午4點。美國/紐約時間夏令時。名稱「America/New_York」時間是「長格式」時區名稱。美國東海岸通常會呼叫他們的時區東部標準時間(EST)

如果您想比較今天的時區偏移量與其他日期的時區偏移量,則需要知道數學符號(+/- - 「正/負」)時區偏移與時區相反。

查看joda.org的時區表,找到「America/New_York」的時區。它在標準偏移量前面會有一個負號。

地球在其軸上逆時針旋轉。在紐約市有人看到日出前5個小時,一個人在格林威治觀看日出即可看到日出。在美國東海岸的人看到日出之後,美國西海岸的人會看到日出。

有一個原因,你需要知道所有這些。這樣您就可以從邏輯上確定某些JavaScript代碼是否正確獲取DST狀態,而無需在一年的不同時間測試每個時區。

想象一下,它是11月在紐約市,時鐘已經被設置了一個小時。在紐約市的夏天,抵消是240分鐘或4小時。

您可以通過創建一個7月份的日期然後獲取偏移量來測試。

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

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet) 

什麼打印到瀏覽器的開發者工具控制檯日誌?

答案是:240

所以,現在你可以創建一月份日期,看看你的瀏覽器返回時區的冬季偏移。

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) 

答案是:300

顯然,300比240大那麼,這是什麼意思?您是否應該編寫測試冬季偏移大於夏季偏移的代碼?或夏季偏移量低於冬季偏移量?如果夏季和冬季時區偏移之間存在差異,則可以假定DST正在用於此時區。但是,這並不告訴你,如果今天正在瀏覽器時區使用DST。所以,你需要獲得今天的時區偏移量。

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

console.log('todaysTimeZone : ' + todaysTimeZone) 

答案是:? - 取決於一年中的時間

如果今天的時區偏移量和夏令時區偏移量是相同的,夏季和冬季時區偏移量是不同的,那麼通過邏輯推理,今天一定是不在DST。

您可以省略比較夏令時和冬令時偏移(要知道夏令時是否用於此時區),並將今日時區偏移與夏季TZ偏移進行比較,並始終得出正確答案?

today's TZ Offset !== Summer TZ Offset 

那麼,今天是在冬天還是夏天呢?如果你知道,那麼你可以採用以下邏輯:

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

但問題是,你不知道,如果今天的日期是在冬季或夏季。每個時區在DST啓動和停止時都有自己的規則。您需要跟蹤世界上每個時區的每個時區的規則。所以,如果有更好更簡單的方法,那麼你可以做更好更簡單的方法。

我們剩下的就是你需要知道這個時區是否使用DST,然後比較今天的時區偏移和夏令時偏移。這總會給你一個可靠的答案。

最終的邏輯是:

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

功能,以確定是否在瀏覽器中的時區使用夏令時:

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 
}