2015-05-22 112 views
1

我有下面的代碼添加時間爲DateTime實例:如何在時區更改時向DateTime添加時間?

 DateTime d1 = new DateTime(); 
     d1 = d1.withZone(DateTimeZone.forID("Europe/London")); 
     ArrayList<String> timeList = new ArrayList<String>(); 

     for(int x = 1; x <= 10; x++) { 
     //Adds six hours to the DateTime instance. 
       d1 = d1.plusHours(6); 
       d1 = d1.plusMinutes(0); 
       d1 = d1.plusSeconds(0); 
       timeList.add(d1.toString()); 
     } 

這將創建一組的10倍,添加到一個ArrayList。但是,如果添加了6小時,則會發生夏時制變化。如何根據時區更改添加/刪除額外小時時生成正確的時間?目前它不會使用此方法刪除/添加額外的小時。如果我是開始在上午10:00運行在2015年10月24日的代碼生成

比如我希望下面的時間。請注意,時區在2015年10月25日上午02:00變更。

24/10/2015 10:00:00 BST 
24/10/2015 16:00:00 BST 
24/10/2015 22:00:00 BST 
25/10/2015 05:00:00 GMT 
25/10/2015 11:00:00 GMT 
25/10/2015 17:00:00 GMT 
25/10/2015 23:00:00 GMT 
26/10/2015 05:00:00 GMT 
26/10/2015 11:00:00 GMT 
26/10/2015 17:00:00 GMT 
+1

「容納」是什麼意思?如果您展示一個簡短但完整的程序來展示問題 - 包括實際產出和預期產出,這將非常有幫助。 –

+0

在帖子中增加了更多信息。 – MisterIbbs

+1

你還沒有添加一個簡短但完整的例子,這是我真的很想看到... –

回答

2

通常我會離開的正確答案喬恩斯基特(​​他最後的評論是多還是少在我看來,答案),但現在有哪些錯過了臨界點其他兩個不可接受的答案。

貴 「的問題」,可以縮小到這些線路和(錯誤)的期望:

24/10/2015 22:00:00 BST

25/10/2015 05 :00:00 GMT

您正確地寫道,在2015年10月25日凌晨2:00在英國發生跳回冬令時的夏令時開關。這意味着標記爲「01」的小時會發生兩次(重疊情況),因爲時鐘被設置回來並且在這個小時內重複。因此小時作爲時鐘位置標稱計數必須增加一小時得到以小時爲單位的真實的物理時間。數學:

nominal duration + one hour = real duration (= 6 real hours) 
=> nominal duration = (6 - 1) hours = 5 virtual hours 

請記住,時間戳,如 「24/10/2015 22:00:00 BST」(在ISO偏移符號: 「2015-10-24T22:00:00 + 01」)站對於全球物理時刻,這樣的時刻之間的時間差表示物理持續時間。加入六小時到原來的瞬間的持續時間包含一個小時然而所以你必須從現實小時刪除一個小時才能標稱持續時間(時鐘位置測量 - 見給出的公式的第二部分以上)。因此,在瞬間的符號:

[2015-10-24T22:00+01] + 6 physical hours = 
    [2015-10-25T04:00+01] = [2015-10-25T03:00+00] = [2015-10-25T03:00Z] 

,名義本地時間戳標記(只是看時鐘位置):

[2015-10-24T22:00] + 5 virtual hours (clock positions) = [2015-10-25T03:00] 

所以重複時鐘位置降低標稱時間,不增加它。

而這正是喬達,時間不正確:

DateTime d1 = new DateTime(2015, 10, 24, 10, 0, 0, 0, DateTimeZone.forID("Europe/London")); 

for (int x = 1; x <= 10; x++) { 
    d1 = d1.plusHours(6); 
    System.out.println("> " + d1.toString()); 
} 

> 2015-10-24T16:00:00.000+01:00 
> 2015-10-24T22:00:00.000+01:00 
> 2015-10-25T03:00:00.000Z 
> 2015-10-25T09:00:00.000Z 
> 2015-10-25T15:00:00.000Z 
> 2015-10-25T21:00:00.000Z 
> 2015-10-26T03:00:00.000Z 
> 2015-10-26T09:00:00.000Z 
> 2015-10-26T15:00:00.000Z 
> 2015-10-26T21:00:00.000Z 
+0

哦,上帝* facepalm *我只是假設OP是正確的,沒有看日期。 –

+0

更正...關於聲明:「標記爲」02「的小時發生兩次」,我相信它實際上是重複的「01小時」。根據我讀過的,在美國,加拿大和歐盟,在1:59或凌晨2點的時候,時鐘被重新設置爲「01:00」,重複1點鐘。 –

+0

@BasilBourque糾正了錯字。我被誤導了,因爲在中歐,時鐘在當地時間早上3點跳回(德國:時鐘2重複)。 –

0

別擔心,使用java.time

  • 顯然,你正在使用的喬達時庫。改用java.time代替。
  • java。時間類自動處理夏令時(DST)切換。
  • 除了讓您的JVM隨時更新tzdata time zone database更改,可能會影響您感興趣的時區之外,您無需執行任何操作。請參閱Oracle’s provided tool for tzdata更新。

java.time

讓我們來看看使用java.time類加上6個小時的結果。

定義日期和時間部分。

LocalDate ld = LocalDate.of (2015, Month.OCTOBER, 24); // 24th Oct 2015 at 10:00am per the Question. 
LocalTime lt = LocalTime.of (10, 0); 

定義的時區,一個ZoneId對象,Europe/London

ZoneId z = ZoneId.of ("Europe/London"); 

合併以創建ZonedDateTime對象。

ZonedDateTime zdtStart = ZonedDateTime.of (ld, lt, z); 

ZonedDateTime中提取InstantInstant類表示UTC中時間軸上的一個時刻,分辨率爲nanoseconds(小數點後最多九(9)位數字)。

Instant instantStart = zdtStart.toInstant (); 

將我們的時間跨度6小時定義爲Duration。 java.time類可以通過添加一個Duration對象來執行日期 - 時間數學。

A Duration未連接到時間線,實際上存儲了幾秒和幾納秒。所以在這個課堂上,「六小時」以及時鐘和DST等沒有智能。當我們要求六小時的Duration時,該班級立即計算出(6小時* 60分鐘每小時* 60秒每分鐘)= 21,600秒。

Duration sixHours = Duration.ofHours (6); // 21,600 seconds = (6 hours * 60 minutes per hour * 60 seconds per minute). 

循環十次。第一循環通過將Duration添加到ZonedDateTime,並將結果轉換爲Instant

// Increment the `ZonedDateTime`. 
ZonedDateTime zdt = zdtStart; 
for (int i = 1 ; i <= 10 ; i++) { 
    System.out.println (">zdt.toString() " + zdt + " | zdt.toInstant().toString(): " + zdt.toInstant () + "\n"); 
    // Set up next loop. 
    zdt = zdt.plus (sixHours); 
} 

運行時。請注意倫敦時間的時間跳躍。這是Daylight Saving Time (DST)轉換,秋季時的「後退」時間,當英格蘭從標準時間從+01:00的偏移量轉移到Zulu偏移量+00:00,其中凌晨2點時鐘跳回到重複凌晨1點。所以,如果我們預計22:00加上6個小時導致4點,我們會看到3點。您可以在Instant的價格中看到確實已經過去了六個小時。訣竅是,倫敦人在那個時候一小時左右就把鐘擺回來了。

查看history of DST cutoversEurope/London

zdt.toString()2015-10-24T10:00 + 01:00 [Europe/London] | zdt.toInstant()。toString():2015-10-24T09:00:00Z

zdt.toString()2015-10-24T16:00 + 01:00 [Europe/London] | zdt.toInstant()。toString():2015-10-24T15:00:00Z

zdt.toString()2015-10-24T22:00 + 01:00 [Europe/London] | zdt.toInstant()。toString():2015-10-24T21:00:00Z

zdt.toString()2015-10-25T03:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-25T03:00:00Z

zdt.toString()2015-10-25T09:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-25T09:00:00Z

zdt.toString()2015-10-25T15:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-25T15:00:00Z

zdt.toString()2015-10-25T21:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-25T21:00:00Z

zdt.toString()2015-10-26T03:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-26T03:00:00Z

zdt.toString()2015-10-26T09:00Z [Europe/London] | zdt.toInstant()。toString():2015-10-26T09:00:00Z

zdt.toString()2015-10-26T15:00Z [Europe/London] | 。zdt.toInstant()的toString():2015-10-26T15:00:00Z

對於我們交換的樂趣,增加了6個小時先後到Instant和結果轉換爲倫敦時間。

// Increment the `Instant`. 
Instant instant = instantStart; 
for (int i = 1 ; i <= 10 ; i++) { 
    System.out.println (">instant.toString() " + instant + " | instant.atZone(z).toString(): " + instant.atZone (z) + "\n"); 
    // Set up next loop. 
    instant = instant.plus (sixHours); 
} 

運行時,我們看到相同的值輸出。

instant.toString()2015-10-24T09:00:00Z | instant.atZone(z).toString():2015-10-24T10:00 + 01:00 [歐洲/倫敦]

instant.toString()2015-10-24T15:00:00Z | instant.atZone(z).toString():2015-10-24T16:00 + 01:00 [歐洲/倫敦]

instant.toString()2015-10-24T21:00:00Z | instant.atZone(z).toString():2015-10-24T22:00 + 01:00 [歐洲/倫敦]

instant.toString()2015-10-25T03:00:00Z | instant.atZone(z).toString():2015-10-25T03:00Z [歐洲/倫敦]

instant.toString()2015-10-25T09:00:00Z | instant.atZone(z).toString():2015-10-25T09:00Z [歐洲/倫敦]

instant.toString()2015-10-25T15:00:00Z | instant.atZone(z).toString():2015-10-25T15:00Z [歐洲/倫敦]

instant.toString()2015-10-25T21:00:00Z | instant.atZone(z).toString():2015-10-25T21:00Z [歐洲/倫敦]

instant.toString()2015-10-26T03:00:00Z | instant.atZone(z).toString():2015-10-26T03:00Z [歐洲/倫敦]

instant.toString()2015-10-26T09:00:00Z | instant.atZone(z).toString():2015-10-26T09:00Z [歐洲/倫敦]

instant.toString()2015-10-26T15:00:00Z | instant.atZone(z).toString():2015-10-26T15:00Z [歐洲/倫敦]

看到這個code run live at IdeOne.com


關於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的一個試驗場。您可以在這裏找到一些有用的類,如IntervalYearWeekYearQuartermore