【问题标题】:Make SimpleDateFormat.parse() fail on invalid dates (e.g. month is greater than 12)使 SimpleDateFormat.parse() 在无效日期失败(例如,月份大于 12)
【发布时间】:2010-12-26 16:58:38
【问题描述】:

我正在使用java.text.SimpleDateFormat 解析"yyyyMMdd" 形式的字符串。

如果我尝试解析一个月大于 12 的字符串,而不是失败,它会滚动到下一年。完整的可运行重现:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ParseDateTest {

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        Date result = format.parse("20091504"); // <- should not be a valid date!
        System.out.println(result); // prints Thu Mar 04 00:00:00 CST 2010
    }
 }

我宁愿抛出ParseException

是否有任何强制异常发生的非hacky方式?我的意思是,我不想手动检查月份是否大于 12。这有点荒谬。

感谢您的任何建议。

注意:我已经知道 Joda Time,但我需要在没有外部库的普通 JDK 中完成。

【问题讨论】:

    标签: java parsing date


    【解决方案1】:

    您需要将其设为non-lenient。因此,

    format.setLenient(false);
    

    应该这样做。

    【讨论】:

    • 非常感谢。那成功了。令人惊讶的是,在这里提问比在谷歌上搜索更快地给出结果(或者我不擅长搜索:)。
    • stackoverflow 应该允许用户给出超过 1 分的答案,这就是其中一个答案。在使用SimpleDateFormat 解析之前,我正在做一些荒谬的模式匹配。非常感谢。
    • 当我们给出像“MM/dd/yyyy HH:mm”这样的格式并且我们传递像“10/25/16 17:46”这样的日期时,setLenient(false) 仍然不起作用。它没有检查那一年没有指定为 2016。
    • @AjaySharma:这不是一个无效的日期。
    • 对于日期格式,请确保您有大写月份。例如dd/mm/yyyy 将不起作用,因为mm 代表分钟而不是月份。在这种情况下,有效格式应为“dd/MM/yyyy”。 see here in documentation
    【解决方案2】:

    您可以使用 Java 8 时间 API。例如,如果您使用值为 15 的月份:

    String strDate = "20091504";
    TemporalAccessor ta = DateTimeFormatter.ofPattern("yyyyMMdd").parse(strDate);
    

    你会直接有异常

    Exception in thread "main" java.time.format.DateTimeParseException:
    Text '20091504' could not be parsed:
    Invalid value for MonthOfYear (valid values 1 - 12): 15
    

    【讨论】:

    • 在以下情况下似乎无法正常工作。如果我使用格式“dd-MM-yy”并解析日期值“31-02-19”,它不会引发任何解析错误,而是提供结果“28-02-99”但我期待抛出解析异常,因为给定的日期不是有效的。你遇到过这种情况吗?
    • 使用 Java 11 和 JShell,我得到:jshell&gt; DateTimeFormatter.ofPattern("dd-MM-yy").parse("31-02-19"); $1 ==&gt; {},ISO resolved to 2019-02-28,但这是 OP 要求的另一种无效日期。
    【解决方案3】:

    通过使用 Java 8 LocalDate 你可以这样写,

    String strDate = "20091504";
    LocalDate date1 = LocalDate.parse(strDate, DateTimeFormatter.BASIC_ISO_DATE);
    System.out.println(date1);
    

    这里是解析时抛出的异常

    Exception in thread "main" java.time.format.DateTimeParseException: Text '20091504' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 15
    at java.time.format.DateTimeFormatter.createError(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalDate.parse(Unknown Source)
    at com.katte.infa.DateFormatDemo.main(DateFormatDemo.java:22)
    
    Caused by: java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 15
    at java.time.temporal.ValueRange.checkValidIntValue(Unknown Source)
    at java.time.temporal.ChronoField.checkValidIntValue(Unknown Source)
    at java.time.chrono.IsoChronology.resolveYMD(Unknown Source)
    at java.time.chrono.IsoChronology.resolveYMD(Unknown Source)
    at java.time.chrono.AbstractChronology.resolveDate(Unknown Source)
    at java.time.chrono.IsoChronology.resolveDate(Unknown Source)
    at java.time.chrono.IsoChronology.resolveDate(Unknown Source)
    at java.time.format.Parsed.resolveDateFields(Unknown Source)
    at java.time.format.Parsed.resolveFields(Unknown Source)
    at java.time.format.Parsed.resolve(Unknown Source)
    at java.time.format.DateTimeParseContext.toResolved(Unknown Source)
    at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    ... 3 more
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多