20

我正在尝试将String( YYYY-MM-dd HH:mm) 解析为Date,但是错误的日期比预期的要多。

代码:

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

产生:

2012 年 12 月 30 日星期日 08:30:00 EST (错误)

我尝试关闭 Lenient,但没有运气。

更新

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

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

5 回答 5

57

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

于 2013-04-10T04:30:18.777 回答
7

使用小写字母 Y,而不是大写字母。即 yyyy 不是 YYYY

在此处查看评论:Java Simple Date Format和此处引用的其他答案。

于 2013-04-10T04:54:25.463 回答
6

有两个问题。

  1. 格式字符串应该是"yyyy-MM-dd HH:mm".
  2. 存储时间的数据类型是TimeStamp而不是Date在数据库中。

更正这两件事,您将能够随时间存储和检索日期。

于 2013-04-10T05:30:58.227 回答
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. 很长,我知道。需要注意的是,它提到的字段中没有年份,只有一个 WeekBasedYear。这是不一样的; 并且您现在可能已经知道这正是因为大写Y是基于周的年份(仅适用于周数),您应该使用小写y的年份。我认为这种行为比旧课程更有帮助:他们给你一个错误的结果,假装一切都很好,让你完全不知道哪里出了问题。

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

    ps.setObject(3, newDate);

不过,我还没有用数据库对此进行过测试。请注意,您使用setObject()而不是setDate().

于 2017-06-21T19:37:10.510 回答
1

Although this was not the case here, beware that SimpleDateFormat is not thread-safe. So when used in a multi-threaded environment, race conditions can happen and cause wrong parsing results. Solution is to either

  • create a new instance on each usage (might decrease performance)
  • instantiate once but use it in a synchronized block
  • instantiate once but use ThreadLocal

Example with 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);
  }
}
于 2020-04-22T09:42:42.343 回答