What's your time zone?
JAVA日期和時間類徹底解決(2)
Page 2 of 3
首先嘗試的解決方案
基于Java文檔信息和DateTest類的輸出結果,
我打了一個最好的賭:JAVA虛擬機在第一次被運行時就自動設置了一個默認的時間區域(time zone)。為了驗證,我創建了一個ItsInitializer
類,使得我的應用程序在被加載(launched)時便能夠運行它。以下是我的第一次嘗試:
import java.util.TimeZone;
import java.util.SimpleTimeZone;
public class ItsInitializer {
private static boolean s_initialized = false;
private ItsInitializer() {
}
public static synchronized void initialize() {
if (!s_initialized) {
// Modifies the default time zone, disables the Daylight Saving Time.
SimpleTimeZone dtz = (SimpleTimeZone) TimeZone.getDefault();
dtz.setStartRule(0,0,0,0);
dtz.setEndRule(0,0,0,0);
TimeZone.setDefault(dtz);
s_initialized = true;
}
}
}
換句話說,我改變了JVM的默認TimeZone,
因此它沒有夏令時(DST)規則,所以你也不用擔心去調整它。
后來J2SE 1.4發布了,于是我也升級了。但是意外的是:它的ItsInitializer類不能運行了。
于是我立即再去調查。 發現了一個DateTest類的輸出(
for J2SE 1.4.1_01 on Windows 98):
Date = Tue May 06 05:31:03 IDT 2003
Calendar = java.util.GregorianCalendar[time=1052188263870,areFieldsSet=true,areAllFieldsSet
=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Jerusalem",offset=7200000,
dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone
[id=Asia/Jerusalem,offset=7200000,dstSavings=3600000,useDaylight=true,startYear=0,
startMode=1,startMonth=3,startDay=1,startDayOfWeek=0,startTime=3600000,startTimeMode=0,
endMode=1,endMonth=9,endDay=1,endDayOfWeek=0,endTime=3600000,endTimeMode=0]],
firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2003,MONTH=4,WEEK_OF_YEAR=19,
WEEK_OF_MONTH=2,DAY_OF_MONTH=6,DAY_OF_YEAR=126,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,
HOUR=5,HOUR_OF_DAY=5,MINUTE=31,SECOND=3,MILLISECOND=870,ZONE_OFFSET=7200000,
DST_OFFSET=3600000]
你也看到了吧,J2SE 1.4中的TimeZone類的zone成員已經不在是
SimpleTimeZone
的一個實例了。取而代之的是sun.util.calendar.ZoneInfo
類。因此,我需要改變它的Initializer來兼容J2SE 1.4平臺:
import java.util.TimeZone;
import java.util.SimpleTimeZone;
public class ItsInitializer {
private static boolean s_initialized = false;
private ItsInitializer() {
}
public static synchronized void initialize() {
if (!s_initialized) {
// Modifies default time zone, disables Daylight Saving Time.
TimeZone l_defaultTimeZone = TimeZone.getDefault();
int l_rawOffset = l_defaultTimeZone.getRawOffset();
String l_id = l_defaultTimeZone.getID();
SimpleTimeZone l_simpleTimeZone = new SimpleTimeZone(l_rawOffset,
l_id,
0,
0,
0,
0,
0,
0,
0,
0);
TimeZone.setDefault(l_simpleTimeZone);
s_initialized = true;
}
}
}
我創建了一個沒有DST規則的SimpleTimeZone
實例,并將它指派為JVM的默認TimeZone
. 第二個執行形式比第一個更好,因為它沒有為Calendar類的zone成員考慮一個實際的類。注意,這第二個版本是向下兼容的------它能在J2SE 1.3上很好的工作。沒有什么能比通過親身經歷來學習更有收獲,我想獲得更多的經驗,然后能完全解決這個問題。
我認為,在夏令時(DTS)期間,我們總是會物理地去調整一下計算機的時間,因此我們從不必去調整DST了,這樣就可以使得JVM總是設置一個默認的沒有夏令時規則的time zone 。結果問題得以解決。
于是我們高興地通過以上策略來開發我們的應用程序,所有事情都很順利了。沒有更多的日期和時間上的矛盾和差異。 當冬天來臨,我們將計算機時間重新調整回來。在程序中我們也沒有遇到任何日期和時間上的問題,這還要感謝ItsInitializer
這個類。
但是,后來發現,我犯了另一個錯,使我不得不又回到當初那種煩躁。
一個無法預料的故障
冬天過了,夏天又一次來臨,自然的又進入了夏令時階段。我原本以為沒問題的,于是使用了上面的策略來解決。
On the very day we moved to DST, I got timestamp discrepancies. What happened?
今年,我沒有物理上去調整計算機的時間。我已經配置了我們的SUN服務器來使我們不需要物理地調整系統時鐘。date命令是一個
Unix/Linux命令,用來顯示當前系統的日期和時間。date
的Solaris版本使用timezone配置文件幫助自動調整DST的顯示。和
Java的Calendar類的工作機制類似。
因此,如果timezone配置文件被安裝了,你就不用物理地去調整系統時鐘了。我相信LINUX也可以這樣做。
我們的Windows上運行的是Windows XP,我們也沒有物理地去調整系統時間。我們能在Windows XP配置時間區域。問題來了,對于DST,有時候會自動進行調整而有時候又不會調整,下面兩張圖顯示了這個:
Figure 1. Time zone with automatic DST adjustment
|
Figure 2. Time zone without automatic DST adjustment
|
Translated by Willpower,2003.11.18
posted on 2006-02-18 09:32
水煮三國 閱讀(421)
評論(0) 編輯 收藏