SimpleDateFormat无法正确解析日期

时间:2018-03-28 17:08:48

标签: java date simpledateformat date-parsing

我很困惑为什么SimpleDateFormat无法正确解析以下输入数据。

我试图在String上测试各种可能允许的日期格式,看看它是否会使用其中一种格式正确解析。

注意:我使用的其他不正确的日期格式报告了解析错误。这就是我期望看到的。

我做错了什么?或者,我可以做什么作为解决方法?

String dformat = "MM-dd-yyyy";
String cDate = "2013-12-28";
SimpleDateFormat f = new SimpleDateFormat(dformat);
Date dd = f.parse(cDate); 

结果是成功。解析的日期是:

  

日期9月12日星期五00:00:00太平洋标准时间195

嗯,日期应该是 2013年12月28日。 在这种情况下,我希望看到(就像我看到的其他无效格式):

java.text.ParseException: Unparseable date: "2013-12-28"

6 个答案:

答案 0 :(得分:2)

您应该考虑使用java.util.Date的新java 8版本,即java.time.LocalDate和java.time.LocalDateTime作为SDK的一部分。由于您遇到问题,这些Date API被认为更稳定。这是一个例子。

String armisticeDate = "2013-12-28";

LocalDate aLD = LocalDate.parse(armisticeDate);
System.out.println("Date: " + aLD);

String armisticeDateTime = "2013-12-28T11:50";

LocalDateTime aLDT = LocalDateTime.parse(armisticeDateTime);
System.out.println("Date/Time: " + aLDT);

如果您想创建不同的格式,可以执行以下操作。

String anotherDate = "04 Apr 2016";

DateTimeFormatter df = DateTimeFormatter.ofPattern("dd MMM yyyy");
LocalDate random = LocalDate.parse(anotherDate, df);

System.out.println(anotherDate + " parses as " + random);

有关完整文档,请查看Oracle页面。

https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

答案 1 :(得分:2)

要收到错误消息:

java.text.ParseException: Unparseable date: "2013-12-28"

你需要打电话:

f.setLenient(false);

正如parse(String source, ParsePosition pos)的javadoc所说:

  

默认情况下,解析是宽松的:如果输入不是此对象的格式方法使用的形式,但仍可以解析为日期,则解析成功。客户可以通过致电setLenient(false)坚持严格遵守格式。

答案 2 :(得分:1)

您的代码应该是这样的:

  String dformat = "yyyy-MM-dd";
  String cDate = "2013-12-28";
  SimpleDateFormat f = new SimpleDateFormat(dformat);
  Date dd = f.parse(cDate);

您的问题中的日期格式有误。

答案 3 :(得分:1)

dformat不符合cDate格式。因此,您必须在dformat中提供cDate,或者您必须在"" yyyy-MM-dd"

中更改dformat

答案 4 :(得分:1)

您的格式模式和日期字符串不多。 改为:

String dformat = "yyyy-MM-dd";

答案 5 :(得分:1)

嗯,SimpleDateFormat已知为problematic and bugged classlots of strange behaviours

可能发生的事情类似于问题described in this article。考虑你的模式和输入:

MM-dd-yyyy
2013-12-28

它可能在本月读作" 20",日为" 3"和#34; -28"? (或者其他一些值,因为我不确定它如何将2-28解释为4位数字)。而这个混乱的最终结果是一个完全错误,奇怪的日期 - 并且不要问我它是如何达到最终结果的,这对我来说是一个谜。

无论如何,当模式与输入格式不匹配时会发生这种情况,并且SimpleDateFormat读取的实际值将是不可预测的并且有点违反直觉。但真正重要的是这个课程有很多问题和设计缺陷,而且默认情况下它很宽松,所以它试图成为聪明的"在发出错误之前做了很多奇怪的事情。

如果要验证输入,只需按照Andreas的建议调用f.setLenient(false)即可关闭宽松模式。当输入与模式不匹配时,这将抛出异常。

但是,如果你正在使用Java 8,那么你应该使用java.time API,这是非常优越的,它解决了SimpleDateFormat所带来的许多问题。

要检查字符串是否包含特定格式的日期,请使用java.time.format.DateTimeFormatter。默认情况下,此类不宽容为SimpleDateFormat,因此它应该按预期工作:

// use the format "month-day-year"
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM-dd-yyyy");
// try to parse a string in a different format (year-month-day)
LocalDate dt = LocalDate.parse("2013-12-28", fmt); // exception

上面的代码尝试创建一个LocalDate,一个代表日期(只有日,月和年)的类。但是,如果您只想验证输入(不将其分配给任何变量),您只需使用格式化程序:

fmt.parse("2013-12-28"); // exception