2017-06-17 109 views
1

我已實現了以下方法將String轉換爲Date,因爲Date(String)構造被棄用:轉換字符串到日期 - Java的

private Date format(String inputString) { 
     DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); 
     try { 
      return dateFormat.parse(inputString); 
     } catch (ParseException e) { 
      return new Date(); 
     } 
    } 

一個inputString樣品2017-06-01T01:00:00Z。但是,當我檢查輸出時,我觀察到異常處理程序被觸發並返回new Date(),這意味着我的模式有問題:"Jun 17, 2017 1:12:02 PM"

我缺少什麼模式yyyy-MM-dd'T'HH:mm:ssZ

+4

我不能更強烈地建議不要使用傳統的'java.util.Date'類。您應該改用'java.time'包中的相應類。 –

+1

您可以打印正在捕獲的異常的堆棧跟蹤,然後在此處發佈輸出? – csmckelvey

+2

您應該考慮不推薦使用java.util.Date。整個東西。 –

回答

1

你在輸入字符串中有一個字面的Z,所以你也需要引用它(或使用X)。像,

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

更好(如在評論中指出)

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); 

另外,不要扔掉異常(至少打印堆棧跟蹤)。在Java 8+中,您應該使用新的java.time類。這可能看起來像,

private static LocalDateTime format(String inputString) { 
    String pattern = "yyyy-MM-dd'T'HH:mm:ssX"; 
    return LocalDateTime.from(DateTimeFormatter.ofPattern(pattern) 
      .parse(inputString)); 
} 
+2

我敢打賭,輸入字符串中的'Z'是時區,而不僅僅是一個文字。因此,使用'X'(ISO8601時區)而不是''Z''會更合適...... –

+2

本答案給出**差的建議**。通過將'Z'視爲文字並忽略它,您忽略了至關重要的信息:時區或與UTC的偏移量。您丟棄的信息沒有獲得任何好處。同樣,'LocalDateTime'類故意缺少關於偏移量或區域的信息 - 當缺少這樣的信息時適當,但是有意使用丟棄信息是愚蠢的。 'LocalDateTime'確實代表時間軸上的一個時刻。查看Ole V.V.的[更好的建議來使用java.time類並保留區域/偏移量信息](https://stackoverflow.com/a/44609474/642706)。 –

+1

感謝您的編輯。這是對老式代碼的改進。在現代代碼中,您仍然有效地丟棄時區信息。只有在您知道丟失的區域信息是「Z」之前,現在您不再檢查並且無法確定。這更糟糕...... –

4

Z模式表示數值時區偏移量。因此這裏要求的抵消將是+0000

X模式將允許您使用時區偏移量,如Z。 (是的,這似乎是違反直覺的,但你去那裏。)

Source

3

我同意喬C和路易斯瓦塞爾曼點評:留了早已過時的Date類,如果有什麼辦法可以。還有。現代化的替代課程非常方便和程序員友好。

此外,您的輸入字符串符合ISO 8601標準的瞬間即時點,因此適合Instant類。不需要任何明確的格式化器來解析它。我建議:

private static Instant parse(String inputString) { 
    try { 
     return Instant.parse(inputString); 
    } catch (DateTimeParseException dtpe) { 
     System.err.println("Parsing: " + dtpe); 
     return Instant.now(); 
    } 
} 

使用如下的方法,例如:

String inputString = "2017-06-01T01:00:00Z"; 
    System.out.println(parse(inputString)); 

此打印:

2017-06-01T01:00:00Z 

嗯,這是你從開始時相同的字符串,因爲Instant.toString()產生相同的ISO 8601字符串。

我也承認scottb:我們有時需要與傳統代碼進行互操作,而這些代碼確實需要一個陳舊的實例Date實例。如果這是你的情況,從Date.from(parse(inputString))產生一個。這將產生一個Date等於瞬間(在我的電腦上打印爲Thu Jun 01 03:00:00 CEST 2017,因爲那恰好是我的時區)。在任何情況下,我建議在輸入您的遺留代碼之前在最後一刻轉換爲Date以最大限度地減少您對它的使用。

只是爲了實驗,讓我們嘗試用你的格式不正確的模式字符串與新DateTimeFormatter類:

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ").parse(inputString); 

這將產生java.time.format.DateTimeParseException: Text '2017-06-01T01:00:00Z' could not be parsed at index 19。它試圖對你有所幫助:2017-06-01T01:00:00Z的索引19是Z。正如另外兩個答案所說,這正是格式模式與輸入不匹配的地方。相信我的話,這只是一個例子,你可以從現代課程中獲得更好的幫助,而不是從舊課程中獲得更多幫助。