2011-11-27 111 views
4

我一直在搜索這個問題,但找不到清晰明確的文檔。如何根據UTC時間+ TimeZone ID計算牆體時間?

假設我有一個UTC時間和一個TimeZone ID,那麼在Java中知道夏令時在一年中發生變化時,如何計算壁掛時間(= UTC時間+時區偏移+夏令時)?

我正在尋找一個經過測試的代碼示例。謝謝。

回答

4

當你說你在UTC有時間我假設你持有它在CalendarDate沒有時區的概念,儘管誤導toString())。如果你有時間,例如在String您可以輕鬆地解析它或日曆實例喜歡這裏:2011年6月的

Calendar summer = new GregorianCalendar(DateUtils.UTC_TIME_ZONE); 
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0); 

summer代表27日上午9:00 UTC現在,所有你需要做的是把時區從UTC更改爲Melbounre,澳大利亞:

summer.setTimeZone(TimeZone.getTimeZone("Australia/Melbourne")); 

我會用FastDateFormat打印正確的日期:

final FastDateFormat formatter = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT); 

System.out.println(formatter.format(summer)); 

在墨爾本的時間是19:00(+10小時)。但日期改到冬季:

Calendar winter = new GregorianCalendar(DateUtils.UTC_TIME_ZONE); 
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0); 
System.out.println(formatter.format(winter)); 

猛然間,在墨爾本的時間是20:00 (升小時)。

該差異證明更改Calendar的時區需要考慮DST。在UTC時區六月期間,澳大利亞有冬季,因此他們沒有觀察到夏令時。

但是在UTC的冬季,澳大利亞是夏季 - 他們通過將時鐘移動一個小時切換到夏令時。這就是爲什麼在冬季,差值爲+11小時,而夏季UTC時爲+10。


但是等等!當考慮多個時區觀察DST時,它會變得更加有趣。首先,我在歐洲/奧斯陸時區創建同一日期:

Calendar winter = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo")); 
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0); 

奧斯陸9:00冬季期間在墨爾本8:00 UTC但19:00(10小時)。

但同時夏季:

Calendar summer = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo")); 
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0); 

實際上是7:00 UTC和墨爾本17:00! +8小時

不知怎的,人們認爲兩個時區之間的差異始終保持恆定(「奧斯陸和墨爾本之間的差異總是10小時) - 這是如此,尤其是在不同的半球考慮

實際上,在冬季Oslo(無DST,UTC + 1)中觀測到DST在Melbourne(UTC + 11)另一方面,當奧斯陸有夏季時,觀測到DST(UTC + 2)時,在墨爾本(UTC + 10)沒有觀察到,現在變得很明顯,爲什麼差異在8到10小時之間變化,這取決於當天的情況年。

還請記住,DST的第一天和最後一天不是全球性的,而是針對每個時區任意選擇的。這意味着9小時的差異也是可能的(!)例如,檢查今年4月1日。

3

當你在java中使用Date時,它總是在內部使用UTC。 Timezone包含DST設置,所以它實際上非常簡單。

public static void main(String[] args) throws ParseException { 
    String stringAugust = "2011-08-01 12:00:00"; 
    String stringNovember = "2011-11-01 12:00:00"; 

    // Outputting the time in Stockholm and Santiago 
    // Stockholm has DST in August and not in November 
    // Santiago has DST in November and not in August 

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 

    // Parsing the Strings 
    sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 
    Date dateAugust = sdf.parse(stringAugust); 
    Date dateNovember = sdf.parse(stringNovember); 

    // outputting the dates for Stockholm 
    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); 
    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Stockholm")); 
    System.out.println(sdf.format(dateAugust)); 
    System.out.println(sdf.format(dateNovember)); 

    // outputting the dates for Santiago 
    sdf.setTimeZone(TimeZone.getTimeZone("America/Santiago")); 
    System.out.println(sdf.format(dateAugust)); 
    System.out.println(sdf.format(dateNovember)); 

} 

輸出

2011-08-01 14:00:00 +0200 
2011-11-01 13:00:00 +0100 
2011-08-01 08:00:00 -0400 
2011-11-01 09:00:00 -0300 
相關問題