Java 8 LocalDateTime正在解析无效日期

我想在客户端validation日期,所以我写了下面的代码。 但是我没有得到exception,而是获得了2月31日日期字符串的正确日期对象,这显然是无效日期。

public class Test { public static void main(String[] args) { String dateFormat = "HH:mm:ss MM/dd/yyyy"; String dateString = "11:30:59 02/31/2015"; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US); try { LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter); System.out.println(date); } catch (Exception e) { // Throw invalid date message } } } 

输出 :2015-02-28T11:30:59

有谁知道为什么LocalDateTime正在解析这个日期而不是抛出exception。

你只需要一个严格的ResolverStyle

解析文本字符串分两个阶段进行。 阶段1是根据添加到构建器的字段的基本文本解析。 阶段2将解析的字段 – 值对解析为日期和/或时间对象。 此样式用于控制阶段2的解析方式。

示例代码 – 其中withResolverStyle(ResolverStyle.STRICT)是重要的变化,以及使用uuuu而不是yyyy (其中uuuu是“年”而“yyyy”是“年代”,因此含糊不清):

 import java.time.*; import java.time.format.*; import java.util.*; public class Test { public static void main(String[] args) { String dateFormat = "HH:mm:ss MM/dd/uuuu"; String dateString = "11:30:59 02/31/2015"; DateTimeFormatter dateTimeFormatter = DateTimeFormatter .ofPattern(dateFormat, Locale.US) .withResolverStyle(ResolverStyle.STRICT); try { LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter); System.out.println(date); } catch (DateTimeParseException e) { // Throw invalid date message System.out.println("Exception was thrown"); } } } 

Java 8 DateTimeFormatter使用yyyy表示YEAR_OF_ERA,uuuu表示YEAR。 您需要修改模式字符串,如下所示:

 String dateFormat = "HH:mm:ss MM/dd/uuuu"; 

DateTimeFormatter默认使用SMART解析器样式,但您希望它使用STRICT解析器样式。 修改dateTimeFormatter初始化代码,如下所示:

 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US) .withResolverStyle(ResolverStyle.STRICT); 

它没有四舍五入。 2月从未有过31天,并且不可能使用validation日期/时间对象来表示不存在的日期。

因此,它会获取无效输入并为您提供正确日期(当年2月的最后日期)的最佳近似值。

SimpleDateFormatinheritance自DateFormat ,其上有一个setLenient(boolean value)方法。 我希望如果你在解析之前调用setLenient(true) ,它可能会抱怨更多, 如javadocs中详细说明的那样 。

 try { SimpleDateFormat df = new java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy"); df.setLenient(false); System.out.println(df.parse("11:30:59 02/29/2015")); } catch (java.text.ParseException e) { System.out.println(e); } 

我找到了一个解决方案,使用DateFormat.setLenient(boolean)将date识别为有效日期。 如果您尝试解析任何无效日期,它将抛出解析exception。

编辑:

Java 8 ,但如果一个月不在112之间,如果一天超过32 ,这将引发exception。 完全没有用。 但是一个月它的工作。

 try { TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015"); } catch (Exception e) { System.out.println(e); } 

输出:

 java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32 

如果传入的字符串包含无效字符,超过31天或超过12的月份,LocalDateTime.parse将仅引发错误。

例如,如果您修改了代码:

 String dateString = "11:30:59 0zz2/31/2015"; 

在给定日期内由无效的’zz’字符引起exception。 至于为什么它可以说是“四舍五入”的日期,我不知道。

资料来源: https : //docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-