2013-08-29 145 views
4

請看看你是否可以告訴我如何處理我的情況下的DST問題。夏令時在java

第一,我的應用程序是一個物流系統,這是全球用戶,所以它涉及時區的問題,我將處理它集預訂的用戶本地日期時,以下幾點:

1.當用戶登錄應用,我們可以根據登錄IP獲取用戶的時區,但這只是一個偏移量(我不記得這個東西的時間),例如「GMT + 08」(北京)或「GMT-06」(芝加哥)。

2.before用戶保存預訂時,我們需要設置預訂本地日期,因爲我不能得到用戶本地日期直接.so我會得到服務器日期第一(在我的情況下,這是北京時間),然後根據服務器日期和用戶時區計算本地日期,例如,如果用戶時區爲「GMT-08」,則服務器日期爲2013-08-29 17:45:00。服務器時區爲「GMT + 08」,那麼我將使用服務器日期-8-8,結果將爲2013-08-29 01:45:00。但由於我不考慮DST,計算出的本地日期將會與實際的日期有所不同,現在在舊金山,實際的本地日期將比我以這種方式計算的結果早一個小時,

我發現java TimeZone已經考慮了DST問題,但是我在構建TimeZone時需要提供「位置」名稱(例如US/Alaska,Pacific/Apia)。而在我的情況下,我能得到的只是offset.so你能告訴我如何解決我的案例中的DST問題嗎?

回答

3

這是頭痛

  1. 以我的經驗的常見來源,通過IP地址的位置並不總是可靠的,例如當人們使用企業VPN時。
  2. 你是正確的,基於地區的時區(「歐洲/巴黎」,「CET」)更適合正確處理DST。

我用下面的方法解決了一個類似的問題: 您將精確的時區與服務器端數據庫中的每個用戶相關聯。當用戶填寫預訂表單時,您將顯示一個TZ選擇器,預先填入其默認TZ。因此,他可以仔細檢查它(恕我直言,比IP猜測更安全),並且在服務器端,日期可以安全地從本地服務器轉換爲服務器時間並返回。

5

是的,您應該使用Joda-Time或Java 8中新的java.time包(受Joda-Time的啓發)。

偏移量是由某個日期時間值表示的從UTC(GMT)開始的小時和分鐘數。西海岸是-08:00(忽略夏令時的廢話),意思是8小時UTC以後。

請注意,它的初始版本中的java.time有一個小錯誤,它無法處理只有幾小時的偏移量(例如+08)而沒有分鐘(如+08:00)。

A time zone是偏移量有關夏令時(DST),DST更改歷史和其他異常信息的規則。

正確使用time zone names(主要是大陸斜線城市)。避免使用3或4個字母代碼,如EST,它既不標準也不唯一。

java.util.Date沒有時區,而Joda-Time DateTime

要獲得網絡瀏覽器的時區,請參閱this question。但通常情況下,這並不好。正如您可能已經看到的,許多網站要求用戶選擇一個時區。

您的確切用例令人困惑。通常最好的方法是使用UTC的日期時間值,然後根據需要調整到用戶的當地時間。通常最適合您的軟件工作並將日期時間存儲爲UTC。然後呈現調整爲適合用戶的本地日期時間。換句話說,全球考慮(UTC),本地出現(本地時區調整)。

通常系統管理員將他們的服務器計算機設置爲UTC(無時區偏移量)。如果您的操作系統(如Mac OS X)不提供UTC,則使用Reykjavik,因爲冰島全年使用UTC而無夏令時。同樣,數據庫引擎幾乎總是將日期時間值轉換爲UTC以存儲。

Joda-Time的確提供了LocalDate類,當你真的不關心時區或時間時。但通常最好使用日期時間(DateTime實例),並根據需要格式化爲僅限日期的字符串。

Joda-Time中的示例代碼2.3。

DateTimeZone timeZoneChina = DateTimeZone.forID("Asia/Shanghai"); 
DateTime dateTimeChina = new DateTime(2013, 8, 29, 17, 45, 00, timeZoneChina); 
DateTime dateTimeUtc = dateTimeChina.withZone(DateTimeZone.UTC); 
DateTime dateTimeParis = dateTimeChina.withZone(DateTimeZone.forID("Europe/Paris")); 

DateTimeZone timeZoneUsWestCoast = DateTimeZone.forID("America/Los_Angeles"); 
DateTime dateTimeUnitedStatesWestCoast = dateTimeChina.withZone(timeZoneUsWestCoast); 

DateTimeFormatter formatter = ISODateTimeFormat.date(); 
String outputDateOnlyForUnitedStatesWestCoast = formatter.withZone(timeZoneUsWestCoast).print(dateTimeUtc); 

轉儲到控制檯...

System.out.println("dateTimeChina: " + dateTimeChina); 
System.out.println("dateTimeUtc: " + dateTimeUtc); 
System.out.println("dateTimeParis: " + dateTimeParis); 
System.out.println("dateTimeUnitedStatesWestCoast: " + dateTimeUnitedStatesWestCoast); 
System.out.println("outputDateOnlyForUnitedStatesWestCoast: " + outputDateOnlyForUnitedStatesWestCoast); 

運行時...

dateTimeChina: 2013-08-29T17:45:00.000+08:00 
dateTimeUtc: 2013-08-29T09:45:00.000Z 
dateTimeParis: 2013-08-29T11:45:00.000+02:00 
dateTimeUnitedStatesWestCoast: 2013-08-29T02:45:00.000-07:00 
outputDateOnlyForUnitedStatesWestCoast: 2013-08-29