2014-02-21 54 views
5

我的時區是GMT + 1。Java SimpleDateFormat將解析字符串解釋爲UTC

因此,「日期」對象與「22.09.1985 00:00UTC」在tostring函數上顯示「Sun Sep 22 01:00:00 CEST 1985」。

現在,我試圖通過解析「22/09/1985」與SimpleDateFormat的創建此日期

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 
sdf.setTimeZone(TimeZone.getDefault()); 
Date d = sdf.parse("22/09/1985"); 
    => Sun Sep 22 00:00:00 CEST 1985 

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 
Date d = sdf.parse("22/09/1985"); 
    => Sun Sep 22 02:00:00 CEST 1985 

如何配置的SimpleDateFormat,它創建它打印「太陽報09月22日01:00的日期:00 CEST 1985「,輸入字符串」22/09/1985「?

+0

使用'的SimpleDateFormat( 「EEE MMM d HH:MM:SSžDD/MM/YYYY」);' –

+0

所以它是不可能讓sdf將字符串解釋爲UTC而不定義字符串中的時區? – wutzebaer

+0

嚴格地說,所有Date對象都基於UTC,因爲它在內部存儲爲自1970年1月1日00:00 UTC以來的毫秒數。使用第二個「DateFormat」在正確的時區顯示日期的實際文本。 – Powerlord

回答

7

我的假設是錯誤的,

22.09.1985 00:00UTC is actually 22.09.1985 02:00CET 

所以

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 
Date d = sdf.parse("22/09/1985"); 

正是我想要的,我相比它的日期是錯誤的。

2

使用特定時區解析日期字符串的事實不會使打印的Date對象使用該時區。您仍在使用Date#toString()的相同實現,該實現使用默認時區格式化Date對象。

你將需要的是format你的Date對象與那個對象SimpleDateFormat。如果你有一個特定的字符串,那麼你就需要另一個SimpleDateFormat對象解析該字符串:

String dateString = "22/09/1985"; 

SimpleDateFormat parser = new SimpleDateFormat("dd/MM/yyyy"); 
Date parsedDate = parser.parse(dateString); 

SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); 
formatter.setTimeZone(TimeZone.getTimeZone("UTC")); 
System.out.println(formatter.format(parsedDate)); 

的Java Date沒有與之相關聯的時區的概念。您只能使用指定的時區格式化Date對象,並獲取字符串。否則,切換到JodaTime library

+0

日期對象仍然具有值「Sun Sep 22 00:00:00 CEST 1985」,這不是我想要的 – wutzebaer

+0

@wutzebaer Date對象不具有TimeZone的概念。您只能將其格式化爲與特定時區相關的日期字符串。我建議你看看JodaTime庫,這在處理日期時要好得多。 –

+0

@RohitJain由於'Calendar'是爲了在時區有用的時候使用而設計的,因此股票JDK庫沒有任何'Calendar'格式化類。 – Powerlord

1

Date是一個相對「愚蠢」的類,因爲它只代表自1970-01-01 00:00:00以來的毫秒數。

如果你想打印出日期,就好像它是一個不同的時區,你需要構建的是一個TimeZoneDateFormat/SimpleDateFormatformat它把一個字符串的方式。

4

避免java.util.Date &日曆

你找到的衆多原因之一,以避免使用java.util.Date & .Calendar。他們是非常麻煩的。要麼使用Joda-Time,要麼在Java 8中使用受Joda-Time啓發並由JSR 310定義的新java.time package

搜索StackOverflow for「joda date」以查找很多示例。

時區

你說:

我的時區爲GMT + 1。

不正確的,你的本地從UTC/GMT偏移是+01。那不是你的時區。時區是關於夏令時(DST)和其他異常的規則的偏移量規則。

這偏移應該有兩個數字:+01(或+01:00),而不是+1,根據ISO 8601標準。

避免3或4個字母代碼,如CET。它們既不標準也不唯一。使用proper time zone names

一般來說,您應該在所有日期時間工作中指定時區,而不是依賴當前JVM的默認值。

在Joda-Time和java.time中,日期 - 時間對象都真正知道其分配的時區。 java.util.Date沒有時區,但似乎是因爲它的toString在創建字符串表示時應用了默認時區,因爲您可悲地學到了難題。

示例代碼

某些代碼使用Joda-Time 2.3。

String input = "22/09/1985"; 

DateTimeZone timeZone = DateTimeZone.forID("Europe/Amsterdam"); 
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy"); 
DateTime dateTime = formatter.withZone(timeZone).parseDateTime(input); 
DateTime dateTimeUtcGmt = dateTime.withZone(DateTimeZone.UTC); 
DateTime dateTimeIndia = dateTime.withZone(DateTimeZone.forID("Asia/Kolkata")); 
String outputMontreal = DateTimeFormat.forStyle("FF").withZone(DateTimeZone.forID("America/Montreal")).withLocale(Locale.CANADA_FRENCH).print(dateTime); 
// All of the above date-time represent the very same moment in the timeline of the Universe. 

轉儲到控制檯...

System.out.println("dateTime: " + dateTime); 
System.out.println("dateTimeUtcGmt: " + dateTimeUtcGmt); 
System.out.println("dateTimeIndia: " + dateTimeIndia); 
System.out.println("outputMontreal: " + outputMontreal); 

運行當...

dateTime: 1985-09-22T00:00:00.000+02:00 
dateTimeUtcGmt: 1985-09-21T22:00:00.000Z 
dateTimeIndia: 1985-09-22T03:30:00.000+05:30 
outputMontreal: samedi 21 septembre 1985 18 h 00 EDT