Java 8 LocalDateTime正在分析无效的日期

Java 8 LocalDateTime正在分析无效的日期,java,parsing,datetime,Java,Parsing,Datetime,我想在客户端验证日期,所以我编写了以下代码。但是我没有得到一个异常,而是得到了一个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"; Dat

我想在客户端验证日期,所以我编写了以下代码。但是我没有得到一个异常,而是得到了一个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-28311:30:59

有人知道为什么
LocalDateTime
解析此日期而不是抛出异常。

您只需要一个严格的

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

示例代码-其中,
with ResolverStyle(ResolverStyle.STRICT)
是重要的更改,同时使用了
uuuu
而不是
yyyy
(其中
uuuu
是“年”,而“yyyy”是“纪年”,因此不明确):


LocalDateTime.parse仅在传入的字符串包含无效字符、天数超过31天或月份超过12个时才会引发错误

例如,如果对代码进行了如下修改:

String dateString = "11:30:59 0zz2/31/2015";
由于给定日期内的无效“zz”字符,将引发异常。至于为什么要把日期“四舍五入”,我不知道

资料来源:

我找到了一个解决方案,将日期识别为有效日期。若您试图解析任何无效日期,它将抛出解析异常

编辑:

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
Java8
,但如果一个月不在
1
12
之间,如果一天超过
32
,则会引发异常。完全不起作用。但就本月而言,它起作用了

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

Java8DateTimeFormatter使用yyyy表示年代,uuuu表示年份。您需要修改模式字符串,如下所示:

String dateFormat = "HH:mm:ss MM/dd/uuuu";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
                                                       .withResolverStyle(ResolverStyle.STRICT);
DateTimeFormatter默认使用智能解析器样式,但您希望它使用严格的解析器样式。修改dateTimeFormatter初始化代码,如下所示:

String dateFormat = "HH:mm:ss MM/dd/uuuu";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
                                                       .withResolverStyle(ResolverStyle.STRICT);

这不是四舍五入。二月从来没有31天,因此不可能使用验证日期/时间对象来表示不存在的日期

因此,它接受无效的输入,并为您提供正确日期的最佳近似值(该年2月的最后一个日期)


SimpleDataFormat
继承自
DateFormat
,其上有一个
setLenient(布尔值)
方法。我想,如果您在解析之前调用
setLenient(true)
,它可能会抱怨更多。

您为什么要等待异常?@AndrewTobilko,大概是因为2月31日不存在。但格式化程序不知道这一点。@Satya:您怎么会这么想?很明显,有人知道这个日期不存在,因为它正在将它转换为28日…@JonSkeet我为早些时候误导你而道歉,问题不是缺少毫秒。事实上,这是一个失落的时代。它仍然需要一个
DateTimeFormatterBuilder
,但默认为Era,而不是毫秒。如果您想编辑并取消删除答案,请随意。
SimpleDateFormat
不适用于Java 8
LocalDateTime
。我正在寻找一个使用Java8 LocalDateTime的解决方案,将yyyy更改为格式字符串中的UUU,这样就不需要再处理ERA了