解析“YYYY-MM-dd HH:mm”时,SimpleDateFormat产生错误的日​​期时间

时间:2013-04-10 04:28:50

标签: java datetime simpledateformat datetime-parsing

我正在尝试将StringYYYY-MM-dd HH:mm)解析为Date,但错误的日期比预期错误。

CODE:

Date newDate = null;
String dateTime = "2013-03-18 08:30";
SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-dd HH:mm", Locale.ENGLISH);
df.setLenient(false);
try {
    newDate = df.parse(dateTime);
} catch (ParseException e) {
    throw new InvalidInputException("Invalid date input.");
}

产地:

  

Sun Dec 30 08:30:00 EST 2012(错误)

我试过设置Lenient但没有运气。

更新

感谢Sudhanshu的回答,它帮助我解决了Java转换问题。当我从上面的代码输入返回的日期到数据库时,我正确地得到了日期,但时间总是00:00

ps.setDate(3, new java.sql.Date(app.getDate().getTime()));

5 个答案:

答案 0 :(得分:46)

YYYY应该是yyyy -

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);

请在此处查看SimpleDateFormat的文档 Java 6:http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
Java 7:http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

答案 1 :(得分:7)

使用小盒子Y,而不是帽子。即yyyy不是YYYY

检查此处的评论:Java Simple Date Format以及其中引用的其他答案。

答案 2 :(得分:5)

有两个问题。

  1. 格式字符串应为"yyyy-MM-dd HH:mm"
  2. 在数据库中存储时间的数据类型为TimeStamp而非Date
  3. 纠正这两件事,你就可以随时间存储和检索日期。

答案 3 :(得分:2)

这是现代的答案。其他答案在2013年写完时是很好的答案。在那之后的一年,现代日期和时间API作为旧课程DateSimpleDateFormat和朋友的替代品而出现。恕我直言,你现在应该使用新的课程。他们对程序员友好得多。

    LocalDateTime newDate = null;
    String dateTime = "2013-03-18 08:30";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm", Locale.ENGLISH);
    try {
        newDate = LocalDateTime.parse(dateTime, dtf);
    } catch (DateTimeParseException e) {
        throw new InvalidInputException("Invalid date input.");
    }

除了类名,它与旧代码没有什么不同。通过其他示例会有差异,通常现代类将提供更清晰的代码和更少的错误机会。

对于差异的一点点演示,让我们尝试使用大写YYYY的格式模式字符串:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm", Locale.ENGLISH);

现在代码抛出java.time.format.DateTimeParseException: Text '2013-03-18 08:30' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MonthOfYear=3, DayOfMonth=18, WeekBasedYear[WeekFields[SUNDAY,1]]=2013},ISO resolved to 08:30 of type java.time.format.Parsed。我知道,这很长。需要注意的是,它所提到的领域中没有一年,只有一周的基础年份。这是不一样的;你可能现在已经想通了,这正是因为大写Y是基于周的年份(只有一周的数字),你应该使用小写的y年。我认为这种行为比旧课程更有帮助:他们给你一个错误的结果,假装一切都很好,让你完全不知道什么是错的。

接下来我知道您希望将日期时间存储到数据库中。在过去,您将转换为适当的java.sql类型。不再需要。我相信你可以使用JDBC 4.2驱动程序:

    ps.setObject(3, newDate);
但是,我还没有用数据库对此进行过测试。请注意,您使用setObject()代替setDate()

答案 4 :(得分:1)

尽管这里不是这种情况,但是请注意SimpleDateFormat不是线程安全的。因此,在多线程环境中使用时,可能会发生竞争情况并导致错误的解析结果。解决办法是

  • 在每次使用时创建一个新实例(可能会降低性能)
  • 实例化一次,然后在synchronized块中使用
  • 实例化一次,但使用ThreadLocal

ThreadLocal的示例:

class MyClass {
  private ThreadLocal<SimpleDateFormat> threadLocalFormat = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH));

  public void foo(String bar) {
    return threadLocalFormat.get().parse(bar);
  }
}