强制SimpleDateFormat解析整个字符串

我有一个日期字符串,格式如下: "dd/MM/yyyy HH:mm:ss" 。 我想从它创建一个Date对象,我正在使用SimpleDateFormat类。 我们的应用程序接受存储在String数组中的许多不同日期格式。 我们所做的是遍历该数组,将applyPattern用于我们的SimpleDateFormat对象并尝试parse给定的日期字符串。 如果它抛出exception,我们在数组中尝试下一个日期格式等。

但是我发现SimpleDateFormat类的parse方法不一定会尝试解析整个字符串。 如果它从字符串的某些部分成功创建了Date对象,那么它将返回它。 这里的问题是我们给定的日期字符串包含日期和时间数据,但是在我们的第一次parse尝试中, SimpleDateFormat使用更简单的模式: "dd/MM/yyyy" 。 并且因为在解析过程中它在给定的日期字符串中找到匹配日期,所以它在那里停止并创建一个没有时间信息的Date对象。

有没有办法强制SimpleDateFormat解析它给出的整个字符串?

 String dateString = "01/01/2015 05:30:00"; Date date = null; for (String format : Constants.DATE_FORMATS) {//String Array that contains many date format strings. try { simpleDateFormat.applyPattern(format);//First format applied is "dd/MM/yyyy". date = simpleDateFormat.parse(dateString); //No exception thrown it accepts the "dd/MM/yyyy" part of the dateString even though the string itself contains even more data. } catch (Exception e) {} } //Returns a date object with the time set to 00:00:00 

我不认为有办法强制SimpleDateFormat解析整个String,但你可以比较格式的长度和输入的长度

 String[] formats = new String[] {"dd/MM/yyyy", "dd/MM/yyyy HH:mm:ss"}; String input = "25/09/2015 10:25:31"; Date result = null; for (String format: formats) { if (input != null && format.length() == input.length()) { try { SimpleDateFormat sdFormat = new SimpleDateFormat(format); result = sdFormat.parse(input); break; } catch (ParseException e) { } } } 

编辑另一种方法是使用JodaTime来解析String。

 String[] formats = new String[] { "dd/MM/yyyy", "dd/MM/yyyy HH:mm:ss" }; String input = "25/09/2015 10:25:31"; LocalDateTime result = null; for (String format : formats) { try { DateTimeFormatter sdFormat = DateTimeFormat.forPattern(format); result = sdFormat.parseLocalDateTime(input); break; } catch (IllegalArgumentException e) { } } System.out.println(result); Date resultDate = result.toDate(); System.out.println(resultDate); 

这给了你

 2015-09-25T10:25:31.000 Fri Sep 25 10:25:31 CEST 2015 

您可以通过提供ParsePosition来检查解析了多少输入。 parse方法更新位置以告诉您解析了多少。

 ParsePosition pos = new ParsePosition(0); date = simpleDateFormat.parse(dateString, pos); if (pos.getIndex() < dateString.length()) { // did not parse all of dateString } 

您可以使用类似的东西而不是SimpleDateFormat

 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; class StrictDateFormat extends SimpleDateFormat { private String pattern; public void applyPattern(String pattern) { super.applyPattern(pattern); this.pattern = pattern; } @Override public Date parse(String source) throws ParseException { if (source.length() != pattern.length()) { throw new ParseException("Wrong size", pattern.length()); } return super.parse(source); } } 

如果您解析的字符串与模式的长度不同,则会抛出exception。 这应该可以防止"01/01/2015 05:30:00""dd/MM/yyyy"解析。 这个将永远是严格的,而不仅仅是"dd/MM/yyyy"

对于那些想要获取java.util.Date对象并避免使用第三方库的人,我使用了答案的压缩版本:

 for (String format : Constants.DATE_FORMATS) { try { return Date.from(LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(format)).atZone(ZoneId.systemDefault()).toInstant()); } catch (DateTimeParseException e) {} } 

使用此代码块,它将使用正确的格式,使用java 8自己的java.time库,它正确匹配格式。 不要忘记添加try-catch块! IDE不会要求它,因为DateTimeParseException是一个运行时exception但我们想要处理它以便进入下一个循环迭代。