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月的最后日期)的最佳近似值。
SimpleDateFormat
inheritance自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
,但如果一个月不在1
到12
之间,如果一天超过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-