2012-08-27 69 views
5

我試圖設置HOUR_OF_DAY字段並更改GregorianCalendar日期對象的時區。Java GregorianCalendar更改時區

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
//date.get(Calendar.HOUR_OF_DAY); 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

輸出:

HOUR: 16 
HOUR: 23 

對於HOUR_OF_DAY的一些原因值設定不同的時區後不會改變。但是,如果我去掉date.get的HOUR_OF_DAY,一切正常,正是因爲它應該

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
date.get(Calendar.HOUR_OF_DAY); // uncommenting this line will is changing the output 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

輸出:

HOUR: 16 
HOUR: 13 

這怎麼可能?爲什麼.get方法正在改變對象的行爲?

回答

8

GregorianCalendar的類繼承其從Calendarget方法,該方法具有以下副作用:

在寬大模式下,所有日曆字段被歸一化。

這意味着,當get被稱爲Calendar對象上time值和所有字段都重新計算。這可能會導致一些不可預知的行爲,特別是當與setTimeZone結合時,其自身具有一些documented buggy behavior

0

TL;博士

OffsetDateTime.now(ZoneOffset.ofHours(10) ).withHour(23) 

避免遺留日期時類

遺留的日期 - 時間類別,包括GregorianCalendar是一個令人困惑的。尷尬,糟糕的設計混亂。避免它們。現在代替java.time類。具體而言,GregorianCalendar被替換爲ZonedDateTime

偏移 - 從-UTC

你顯然希望提前與UTCoffset-from-UTC十個小時的時刻。定義你想要的偏移量。

ZoneOffset offset = ZoneOffset.ofHours(10) ; 

offset.toString():+10:00

獲得當前時刻爲OffsetDateTime與偏移。

OffsetDateTime odt = OffsetDateTime.now(offset) ; 

odt.toString():2018-02-15T16:44:44.216642 + 10:00

你想覆蓋小時是23

OffsetDateTime odt23 = odt.withHour(23) ; 

odt23.toString():2018-02-15T23:44:44。216642 + 10:00

時區

我正在嘗試設置HOUR_OF_DAY領域,改變GregorianCalendar的日期對象的時區。

不,你正在改變offset-from-UTC而不是time zone

總是更好地使用時區而不僅僅是偏移量,如果您知道某個的預期區域。時區是過去,現在和未來某個地區的人們所使用的偏移量的歷史變化。有了時區,您始終可以確定偏移量,但反之亦然。

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

ZoneId z = ZoneId.of("Australia/Brisbane") ; 

捕獲該區域人員所看到的掛鐘時間中的當前時刻。

ZonedDateTime zdt = ZonedDateTime.now(z) ; 

覆蓋時間。

ZonedDateTime zdt23 = zdt.withHour(23) ; 

關於java.time

java.time框架是建立在Java 8和更高版本。這些類代替了日期時間類legacy,如java.util.Date,Calendar,& SimpleDateFormat

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

使用JDBC driverJDBC 4.2或更高版本兼容的,你可以交換java.time直接對象與數據庫。不需要字符串和java.sql。*類。

從何處獲取java.time類?

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