2017-06-08 158 views
0

有一個問題,當由於夏令時(每年兩次)移動時鐘時,日期在Java中不正確(我在中歐:GMT+2在夏天,​​冬季)Jboss Java日期夏令時

如果時間提前1小時移動,new Date()仍舊返回舊時間(比當前時間晚1小時)。

在Java 7中,無需重新啓動Jboss應用程序服務器就可以解決這個問題嗎?

如果我在Windows中手動更改時間,重現問題:Date未更新到系統日期,除非重新啓動jboss。

Calendar c = Calendar.getInstance(); 
c.setTime(new Date()); 
+1

此行爲意味着你很可能不使用正確的時區,所以你可能希望徹底檢查您的應用程序如何使用時間戳。據我所知,您可能希望完全從「Date」遷移出去,因爲該班級不支持時區或任何類型的DST轉換。使用'java.time'包中的類,或者如果您還沒有Java8,至少應該使用java.util.Calendar'。 –

+4

Date對象沒有時區信息,它只是自紀元以來的毫秒數。它恰好顯示打印時的默認時區,但不影響其狀態。 – assylias

+0

使用日曆和setTime(新日期())。只想獲得當前系統日期而無需重新啓動。如果手動更新系統日期,則不重新更新當前日曆日期。 – kandan

回答

2

的Java < = 7,則可以使用ThreeTen Backport,對Java 8的新的日期/時間類有很大反向移植。

使用此功能,您可以輕鬆處理DST更改。

首先,您可以使用org.threeten.bp.DateTimeUtils從和轉換爲Calendar

下面的代碼轉換Calendarorg.threeten.bp.Instant,這是代表「UTC瞬間」(時間戳獨立的時區的一類:現在,在這一刻,每個人都在世界上處於同一時刻,雖然他們的本地日期和時間可能會有所不同,具體取決於它們的位置)。

然後,Instant轉換爲org.threeten.bp.ZonedDateTime(這意味着:在這個時刻,這個時區的日期和時間是什麼?)。我還使用了org.threeten.bp.ZoneId獲得時區:

Calendar c = Calendar.getInstance(); 
c.setTime(new Date()); 

// get the current instant in UTC timestamp 
Instant now = DateTimeUtils.toInstant(c); 

// convert to some timezone 
ZonedDateTime z = now.atZone(ZoneId.of("Europe/Berlin")); 

// today is 08/06/2017, so Berlin is in DST (GMT+2) 
System.out.println(z); // 2017-06-08T14:11:58.608+02:00[Europe/Berlin] 

// testing with a date in January (not in DST, GMT+1) 
System.out.println(z.withMonth(1)); // 2017-01-08T14:11:58.608+01:00[Europe/Berlin] 

我剛剛撿到使用歐洲中部時區(Europe/Berlin)一些時區:您不能使用這3個字母的縮寫,因爲他們是ambiguous and not standard。您可以將代碼更改爲最適合您系統的時區(您可以使用ZoneId.getAvailableZoneIds()獲得所有可用時區的列表)。

我喜歡這個解決方案,因爲它是明確的,我們正在使用的時區顯示給用戶(DateCalendartoString()方法使用默認時區在幕後,你永遠不知道他們在做什麼)。

並在內部,我們可以繼續使用Instant,這是UTC,所以它不受時區的影響(你可以隨時轉換,並從時區時,你需要) - 如果你想在ZonedDateTime轉換回Instant,只需使用toInstant()方法即可。


其實,如果你想獲得當前的日期/時間,只是忘了老班(DateCalendar)和只使用Instant

// get the current instant in UTC timestamp 
Instant now = Instant.now(); 

但是,如果你仍然需要使用舊的課程,只需使用DateTimeUtils即可完成轉換。


以上示例的輸出結果是ZonedDateTime.toString()方法的結果。如果要更改格式,使用org.threeten.bp.format.DateTimeFormatter類(看看在javadoc有關所有可能的格式更多細節):

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z X"); 
// DST (GMT+02) 
System.out.println(formatter.format(z)); // 08/06/2017 14:11:58 CEST +02 
// not DST (GMT+01) 
System.out.println(formatter.format(z.withMonth(1))); // 08/01/2017 14:11:58 CET +01