为什么SimpleDateFormat.parse在这里不引发异常?

时间:2019-07-26 19:38:27

标签: java simpledateformat

首先请注意,我在这里使用java6。

我正在尝试从可能采用不同格式的字符串中获取日期。 出于某种原因,我没有得到希望的ParseException ...

trying yyyyMMdd
trying yyyy/MM/dd
trying yyyy-MM-dd
Fri Apr 25 00:00:00 EST 1980

运行: java test1 1980-04-25

我希望得到:

trying yyyyMMdd
Tue Dec 04 00:00:00 EST 1979

但是我只能得到:

sklearn

你知道怎么了吗?

2 个答案:

答案 0 :(得分:4)

SimpleDateFormat在默认情况下宽大,即使给定日期的格式可能与其配置为解析的格式不匹配,也不会引发异常。您可以像这样设置它的宽松程度:

SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setLenient(false);

通过这种方式,它将检查字符在该日期实际上是否有效。

答案 1 :(得分:1)

  

你知道怎么了吗?

这是SimpleDateFormat确实很麻烦的地方之一。尝试使用模式1980-04-25解析yyyyMMdd时,它会按预期将1980解析为年,然后将-0解析为月,因为它应该是两个字符,然后是{{1 }}作为一个月的一天,即使它也应该是两个字符也是如此。它忽略了4,因为它已经完成了解析。

具有标准设置的-25也忽略了没有月份SimpleDateFormat的事实。它取为0,所以是1980年1月之前的一个月,这就是为什么获得1979年12月。

-0非常麻烦,而且SimpleDateFormat的设计也很差。两者早已过时。我建议您不要使用Date。曾经。

java.time

SimpleDateFormat

让我们尝试使用示例字符串:

private static final String[] dateFormats
        = "yyyyMMdd,yyyy/MM/dd,yyyy-MM-dd,dd/MM/yyyy,dd-MM-yyyy,dd-MMM-yyyy,yyyy MM dd"
                .split(",");

public static LocalDate parseAllDateFormats(String date) {
    if (date == null) {
        return null;
    }
    for (String format : dateFormats) {
        try {
            System.out.println("trying " + format);                
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH);
            return LocalDate.parse(date, dateFormatter);
        }
        catch (DateTimeParseException e) {
            // Ignore, try next format
        }
    }
    return null;
}

预期输出:

    System.out.println(parseAllDateFormats("1980-04-25"));

我正在使用java.time(现代Java日期和时间API)。与旧的日期时间类相比,使用它要好得多。现代trying yyyyMMdd trying yyyy/MM/dd trying yyyy-MM-dd 1980-04-25 可以将解析的值解析为三种样式的日期:严格,精明和宽松。 Smart是默认值,它只接受1到12之间的月份。此外,DateTimeFormatter将坚持解析整个字符串,否则将引发异常。

与您的代码相比,我还做了一些小的修改。在大多数情况下,我做成LocalDate.parse的数组(而不是DateTimeFormatter的数组),但是它不允许我打印String,所以在这里没有。我在第一个trying yyyyMMdd语句中加上了花括号。我在格式化程序上指定了语言环境,因为语言的月份缩写不同,并且我想控制使用哪种语言。我捕获了特定的if,并添加了一条注释,为什么我忽略它,因为否则忽略异常是一件很不好的事情。在方法的底部,如果没有有效的格式,还应该考虑引发异常,而不是返回DateTimeParseException

Java 6

  

请注意,我在这里一直使用java6。

  • java.time 类内置于Java 8和更高版本以及Android 26和更高版本中。
  • ✅在ThreeTen-Backport项目中,大多数 java.time 功能都被反向移植到Java 6和Java 7。
  • 进一步适用于ThreeTenABP中的早期Android(<26)。参见How to use ThreeTenABP…

链接