2017-04-20 28 views
1

我在CST(24小時)中有一個日期字符串,我想將它轉換爲GMT(12小時)。 我有一個像下面的java方法,當我的系統時間是加爾各答時間時工作正常。 (我運行java方法的系統) 但是,當我的系統在上海時,GMT時間不正確。從CST到GMT的日期格式轉換不起作用

String inputDate = "01-19-2017 06:01 CST"; 
SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z"); 
parsedInput = inputFormatter.parse(inputDate); 

// parsedInput -> Tue Jan 19 06:01:00 CST 2017 -> When system time is Shanghai time 
// parsedInput -> Thu Jan 19 17:31:00 IST 2017 -> When system time is Kolkata time 


SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy hh:mm a Z"); 
TimeZone gmt = TimeZone.getTimeZone("GMT"); 
formatter.setTimeZone(gmt); 
String formattedDate = formatter.format(parsedInput); 

// formattedDate -> 01-18-2017 10:01 PM +0000 -> When system time is Shanghai time (Incorrect) 
// formattedDate -> 01-19-2017 12:01 PM +0000 -> When system time is Kolkata time 
+0

*「週二1月19日6時01分00秒CST 2016 - >當系統時間爲上海時間」 * < - 那是隻是一個錯字或它真的改變年份到2016年? –

+1

這裏「24小時」是什麼意思?請注意,您在輸入和輸出中都使用'hh'(12小時制)... –

+4

另請注意,許多時區縮寫都非常模糊。 *您希望CST在這種情況下表示什麼? –

回答

4

避免僞時區

的3-4個字母時區縮寫如CST實際時間重現它在你當前的系統區域。他們不是標準化的。他們甚至不是獨一無二的!

您的CST可能是「中國標準時間」,或者可能是美洲的「中央標準時間」,或可能是其他內容。有無法知道哪一個。

另一個例子:IST可能意味着「印度標準時間」或「愛爾蘭標準時間」或其他。

可靠地解密這些僞區域是不可能的。喬達時間圖書館有一個拒絕甚至嘗試的明智政策。不幸的是,java.time類在解析時會做出猜測,但結果可能不是您期望的區域。

所以千萬不要使用這些無用的僞區域。使用格式爲continent/regionproper time zone name,如America/Chicago,Asia/Kolkata,Pacific/Auckland

避免遺留日期時類

您正在使用的是現在遺留的麻煩舊日期時間類,由java.time類取代。

解決方法

如果你知道你所有的投入都用於同一個時區,然後砍掉僞區和過程作爲一個LocalDateTime,應用擬區作爲ZoneId產生ZonedDateDate。從那你可以提取UTC時間的Instant

String input = "01-19-2017 06:01".replace(" " , "T") ; // Insert a 「T」 to comply with standard ISO 8601 format used by default in java.time. 
LocalDateTime ldt = LocalDateTime.parse(input); // Lacks any concept of time zone or offset-from-UTC. So *not* an actual moment on the timeline. 
ZoneId z = ZoneId.of("America/Chicago"); // Assuming 「CST」 meant this zone in North America. 
ZonedDateTime zdt = ldt.atZone(z); // Assign a time zone to determine an actual moment on the timeline. 
Instant instant = zdt.toInstant(); // Extract a value in UTC. 

您可以選擇通過印度的掛鐘時間鏡頭看到同一時刻。

ZonedDateTime zdtKolkata = zdt.withZoneSameInstant(ZoneId.of("Asia/Kolkata")) ; 

從不依靠默認區域

你的JVM的當前默認時區可以在任何時刻任何代碼在JVM中執行任何應用程序的任何線程改變。由於這可以隨時改變,你不能依賴於某個特定的價值。

當您省略時區的可選參數時,日期 - 時間類將隱式應用當前默認時區。所以解決方案很簡單:總是指定預期/所需的時區

請注意上面的代碼示例如何在每個機會中指定區域。

(同上,用於Locale,順便說一句。通過顯式指定,而不是依賴於當前的默認。)

0

嘗試設置TimeZoneinputFormatter爲好,如:

SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z"); 
inputFormatter.setTimeZone(TimeZone.getTimeZone("GMT")); 

如果不指定時區,它採用默認值考慮進去,這是你的情況Asia/Shanghai,因此,結果不正確。

您可以在上面snippett與Asia/Shanghai更換GMT

+0

解析前設置inputFormatter的時區不會影響任何內容..它仍然是相同的。 –

2

你的問題是CST的模糊性。在大多數情況下,SimpleDateFormat將CST理解爲您預期的中央標準時間。但是,當您的電腦運行上海時間時,這將成爲格式化程序日曆的時區,然後突然將CST理解爲中國標準時間,與上海時間相同。

因此Darshan Mehta’s solution,將inputFormatter的時區設置爲中國標準時間以外的其他時間,在我的電腦上運行。我不知道爲什麼它不適合你(我把它設置爲TimeZone.getTimeZone("America/Chicago")以符合CST的預期解釋)。

但是,正確和優秀的解決方案是完全避免三個和四個字母的時區縮寫。你們只是造成問題的一個例子。如果可以,給你的輸入字符串以明確區UTC的偏移量,這樣是絕不含糊:

String inputDate = "01-19-2017 06:01 -0600"; 

現在你的代碼工作無論預期的計算機的時區設置。模式字符串中的Z已經與-0600匹配得很好。

所有這一切都說,如果你可以使用Java 8的日期和時間類,你可以幫你切換到它們。我毫不猶豫地將它們稱爲「Java 8日期和時間類」,因爲它們也被反向移植到Java 6和7,所以如果你能在Java 8之前依賴庫依賴,那麼你應該有一切機會。較新的類更加程序員友好,並且方便使用。一個簡單的例子,讓你開始:

String inputDate = "01-19-2017 06:01 -0600"; 
    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm Z"); 
    ZonedDateTime parsedInput = ZonedDateTime.parse(inputDate, inputFormatter); 

    OffsetDateTime gmtTime = parsedInput.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC); 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy hh:mm a Z"); 
    String formattedDate = gmtTime.format(formatter); 
    System.out.println(formattedDate); // prints 01-19-2017 12:01 PM +0000