2016-12-06 179 views
2

我可以在不更改日期的情況下更改我的java代碼中Date對象的時區嗎? 當我寫 Date date = new Date(longValue); 我在我的當地時區得到這個日期。我想得到這個日期,但我的時區應該是我的用戶ID(例如「America/Chicago」)在DB(不是本地)中出現的時區。更改日期對象的時區而不更改日期

在此先感謝您的幫助。

+0

始終使用UTC時間在數據庫中保存日期,並且您可以在需要時獲取任何時區日期。 –

回答

9

TL;博士

ZonedDateTime zdtMontreal = 
    ZonedDateTime.now(ZoneId.of("America/Montreal")); 

ZonedDateTime zdtAuckland = 
    zdtMontreal.withZoneSameLocal(ZoneId.of("Pacific/Auckland")); 

同一時刻。zdtAuckland時刻

要確定這是你的意圖。我對你做錯事感到心有餘悸,對日期時間處理的工作方式感到困惑。日期時間工作混淆。一定要搜索和研究堆棧溢出。

java.time

Joda-Time項目,現在在maintenance mode,建議遷移java.time。

Local…類故意沒有時區或offset-from-UTC信息。

LocalDate ld = LocalDate.of(2016 , Month.January , 23); // 2016-01-23 
LocalTime lt = LocalTime.of(12 , 34 , 56); // 12:34:56 

這些值尚未代表時間軸上的一個點。那是奧克蘭新西蘭,巴黎FR還是蒙特利爾CA的中午時間?我們必須應用時區來確定實際時刻。我們應用ZoneId獲得ZonedDateTime

continent/region的格式指定一個proper time zone name,如America/MontrealAfrica/Casablanca,或Pacific/Auckland。切勿使用3-4字母縮寫,如ESTISTCST,因爲它們是而不是真正的時區,不是標準化的,甚至不是唯一的(!)。

ZoneId zMontreal = ZoneId.of("America/Montreal"); 
ZonedDateTime zdtMontreal = ZonedDateTime.of(ld , lt , zMontreal); 

要看到代表在標準ISO 8601格式該值的字符串,調用toString。實際上,ZonedDateTime類通過在方括號中明智地附加時區名稱來擴展標準格式。

String outputMontreal = zdtMontreal.toString(); 

2016-01-23T12:34:56-05:00 [美國/蒙特利爾]

要獲得相同的日期和時間相同的日另一個時區,重複這個過程。

ZoneId zParis = ZoneId.of("Europe/Paris"); 
ZonedDateTime zdtParis = ZonedDateTime.of(ld , lt , zParis); 

ZoneId zAuckland = ZoneId.of("Pacific/Auckland"); 
ZonedDateTime zdtAuckland = ZonedDateTime.of(ld , lt , zAuckland); 

但是知道你在時間上得到一個不同時刻。奧克蘭中午發生在巴黎中午前幾個小時,而在蒙特利爾中午甚至更晚,因爲三個不同時間點碰巧分享巧合wall-clock time

2016-01-23T12:34:56-05:00 [美國/蒙特利爾]

2016-01-23T12:34:56 + 01:00 [歐洲/巴黎]

2016-01-23T12:34:56 + 13:00 [太平洋/奧克蘭]

enter image description here

當前時刻

要獲得當前時刻,請致電Instant.nowInstant類表示UTC中時間軸上的一個時刻,分辨率爲nanoseconds(小數點後最多九位數字)。

Instant instance = Instance.now(); 

ZoneId應用於調整到一個時區。

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = instance.atZone(z); 

對其他所需時區重複此過程,與我們在上面做的類似。

作爲快捷方式,您可以直接獲得ZonedDateTime

ZonedDateTime zdtMontreal = ZonedDateTime.now(ZoneId.of("America/Montreal")); 

而作爲另一種快捷方式,可以採用不同的時區,同時保持相同的日期和時間相同的日(相同掛鐘時間)。致電ZonedDateTime::withZoneSameLocal

ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameLocal(ZoneId.of("Pacific/Auckland")); 

我再說一遍:這導致是在時間線上不同點。 zdtAuckland正在zdtMontreal發生前幾個小時發生。

要保持同一時刻,請撥打ZonedDateTime::withZoneSameInstant

數據庫

平時最好存儲在數據庫中UTC您的日期時間值。已經在Stack Overflow上進行了廣泛的討論。搜索更多信息。


關於java。時間

java.time框架內置於Java 8及更高版本中。這些類別取代了日期時間類別legacy,如java.util.Date,Calendar,& SimpleDateFormat

Joda-Time項目現在在maintenance mode中,建議遷移到java.time。請致電Oracle Tutorial。並搜索堆棧溢出了很多例子和解釋。規格是JSR 310

從何處獲取java.time類?

ThreeTen-Extra項目與其他類擴展java.time。這個項目是未來可能增加java.time的一個試驗場。您可以在這裏找到一些有用的類,例如Interval,YearWeek,YearQuartermore

0

你會發現ZonedDateTime非常有幫助:

Java 8 Convert given time and time zone to UTC time

另外,您可以創建另一個Date對象,並應用一些手動偏移到它。

+0

我已經嘗試過,但它並沒有解決我的問題。我只想改變我的時區而不是約會。例如,我希望將這個日期11/23/2016,4:16 PM EST更改爲2016/11/23,4:16 PM CST。這可能嗎? – user3334226

0

如何使用Java8 ZonedDateTime類做一個例子:

Date date = new Date(longValue); 
ZoneId = ZoneId.of("America/Chicago"); 
ZonedDateTime dt = ZonedDateTime.ofInstant(date.toInstant(), zoneId); 

您已經標記了與喬達的問題,但真正與Java8你不需要它了。

+0

我已經嘗試過,但它沒有解決我的問題。我只想改變我的時區而不是約會。例如,我希望將這個日期11/23/2016,4:16 PM EST更改爲2016/11/23,4:16 PM CST。你的例子也改變了日期。 – user3334226