我一直在搜索這個問題,但找不到清晰明確的文檔。如何根據UTC時間+ TimeZone ID計算牆體時間?
假設我有一個UTC時間和一個TimeZone ID,那麼在Java中知道夏令時在一年中發生變化時,如何計算壁掛時間(= UTC時間+時區偏移+夏令時)?
我正在尋找一個經過測試的代碼示例。謝謝。
我一直在搜索這個問題,但找不到清晰明確的文檔。如何根據UTC時間+ TimeZone ID計算牆體時間?
假設我有一個UTC時間和一個TimeZone ID,那麼在Java中知道夏令時在一年中發生變化時,如何計算壁掛時間(= UTC時間+時區偏移+夏令時)?
我正在尋找一個經過測試的代碼示例。謝謝。
當你說你在UTC有時間我假設你持有它在Calendar
(Date
沒有時區的概念,儘管誤導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日。
當你在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