2012-10-26 68 views
17

SimpleDateFormat是一種非常友好的解析器,它可以生成結果日期而不是拋出錯誤。我怎樣才能嚴格解析一個日期沒有regexps等?Java:如何嚴格解析日期?

fmt = new SimpleDateFormat("dd.MM.yyyy") 
fmt.parse("10.11.2012") // it works 
fmt.parse("10.1150.2012") // it works but it's unwanted 
+3

它可能會也可能不會解決您的問題,但是,如果您正在處理Java中的日期,我會強烈建議喬達時間庫 – Eduardo

回答

31

fmt.setLenient(false);是你在找什麼。

+6

可悲的是,設置寬鬆的錯誤仍然是寬鬆的。 「2010/01/5」可以用於「yyyy/MM/dd」模式。 20100901andGarbage「被允許爲模式」yyyyMMdd「。我發佈了一個答案,使用擴展SimpleDateFormat的類來保證嚴格匹配。 –

+0

java.text.DateFormat.parse的doc說:」該方法可能不會使用整個文本給定的字符串。 「,所以行爲是正確的 – Germinate

9

java.time

您還可以使用Java中8 java.time package及更高版本(Tutorial)。它的解析嚴格檢查日期值。

例如:

String strDate = "20091504"; 
TemporalAccessor ta = DateTimeFormatter.ofPattern("yyyyMMdd").parse(strDate); 

直接給出:

Exception in thread "main" java.time.format.DateTimeParseException: 
Text '20091504' could not be parsed: 
Invalid value for MonthOfYear (valid values 1 - 12): 15 
+0

'DateTimeFormatter'有三個解析器樣式(與DateFormat的兩個樣式相比):strict,smart和lenient。幸運的是,smart是默認的,它會捕獲大多數不需要的輸入,顯然是不正確的。對於更嚴格的驗證,你當然可以嘗試嚴格的解析器風格。[文檔](http://docs.oracle.com/javase/8/docs/api/java/time/format/ResolverStyle.html )是相當豐富的。 –

2

不幸fmt.setLenient(假);不會達到嚴格的日期格式。它有助於某些人,例如使用格式「yyyyMMdd」解析「2010-09-01」將會成功,如果lenient == true,但結果非常奇怪:2009/12/09。

即使lenient == false解析()仍然行爲寬鬆。 「2010/01/5」可以用於「yyyy/MM/dd」模式。並且像「1999/2011」這樣的模式「yyyy/yyyy」的數據分歧是可以容忍的(產生2011)。模式匹配後也允許垃圾。例如:「20100901」和「20100901andGarbage」都將匹配「yyyyMMdd」。

我寫了一個SimpleDateFormat的擴展,它執行嚴格的模式匹配。你可以在這裏找到它:

SimpleDateFormat.parse() ignores the number of characters in pattern

在我的版本格式()和解析()是功能性的逆。這是我認爲大多數人都會期待的。