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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32823368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:09:36  来源:igfitidea点击:

Java 8 LocalDateTime is parsing invalid date

javaparsingdatetime

提问by Zeeshan

I wanted to validate date in client side so I wrote the following code. But instead of getting an exception I am getting a proper date object for 31st of February date string, which is clearly an invalid date.

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

Output: 2015-02-28T11:30:59

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

Does anyone know why LocalDateTimeis parsing this date instead of throwing an exception.

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

采纳答案by Jon Skeet

You just need a strict ResolverStyle.

你只需要一个严格的ResolverStyle.

Parsing a text string occurs in two phases. Phase 1 is a basic text parse according to the fields added to the builder. Phase 2 resolves the parsed field-value pairs into date and/or time objects. This style is used to control how phase 2, resolving, happens.

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

Sample code - where withResolverStyle(ResolverStyle.STRICT)is the important change, along with the use of uuuurather than yyyy(where uuuuis "year" and "yyyy" is "year of era", and therefore ambiguous):

示例代码 -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");
        }
    }
}

回答by jste89

LocalDateTime.parse will only throw an error if the String passed in contains invalid characters, a number of days exceeding 31 or a month exceeding 12.

LocalDateTime.parse 只会在传入的 String 包含无效字符、天数超过 31 或一个月超过 12 时抛出错误。

For example, if you modified your code as such:

例如,如果您这样修改代码:

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

an exception would be thrown caused by the invalid 'zz' characters within your given date. As to why it's 'rounding-down' the date so to speak, that I don't know.

给定日期内的无效“zz”字符会引发异常。至于为什么它是“四舍五入”的日期可以这么说,我不知道。

Source: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-

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

回答by SatyaTNV

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);
}

I found one solution to recognize date as a valid date with DateFormat.setLenient(boolean). If you try to parse any invalid date it will throws parse exception.

我找到了一种使用DateFormat.setLenient(boolean)将日期识别为有效日期的解决方案。如果您尝试解析任何无效日期,它将引发解析异常。

Edit:

编辑:

Java 8, but this will raise exception if a month is not between 1and 12, if a day is more than 32. Exactly not working. But for month its working.

Java 8,但如果一个月不在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);
}

Output:

输出:

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

回答by Palamino

The Java 8 DateTimeFormatter uses yyyy to mean YEAR_OF_ERA, and uuuu to mean YEAR. You need to modify your pattern string as follows:

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

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

The DateTimeFormatter defaults to using the SMART resolver style, but you want it to use the STRICT resolver style. Modify your dateTimeFormatter initialization code as follows:

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

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

回答by Edwin Buck

It is not rounding down. February has never had 31 days, and it is impossible to use a validating date / time object to represent a day that doesn't exist.

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

As a result, it takes the invalid input and gives you the best approximation to the correct date (the last date of February that year).

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

SimpleDateFormatinherits from DateFormatwhich has a setLenient(boolean value)method on it. I would expect that if you called setLenient(true)prior to parsing, it would probably complain more, as detailed in the javadocs.

SimpleDateFormat继承自DateFormat其上有一个setLenient(boolean value)方法。我希望如果您setLenient(true)在解析之前调用,它可能会抱怨更多,如 javadocs 中所述