java.time
在 JSR-310 被合并到 Java SE 8 之前,这确实是java.util
日期时间 API 的一个问题。该java.util.Date
对象不像现代日期时间类型那样是真正的日期时间对象;相反,它表示自称为“纪元” January 1, 1970, 00:00:00 GMT
(或 UTC)的标准基准时间以来的毫秒数。当您打印 的对象时java.util.Date
,其toString
方法会返回 JVM 时区中的日期时间,根据此毫秒值计算得出。
您所描述的问题已通过现代日期时间 API *得到解决,我们拥有LocalDate
的只是一个日期。在下面的句子中,Oracle 教程很好地描述了它的目的:
例如,您可以使用 LocalDate 对象来表示出生日期,因为大多数人在同一天庆祝他们的生日,无论他们是在他们的出生城市还是在国际日期变更线的另一边的全球。
几页后,它再次描述如下:
LocalDate 表示 ISO 日历中的年月日,可用于表示没有时间的日期。您可以使用 LocalDate 来跟踪重要事件,例如出生日期或结婚日期。
我应该使用哪种数据类型LocalDate
?
它映射为DATE
ANSI SQL 类型。ANSI SQL 类型与类型的映射在Oracle 的文章java.time
中描述如下:
ANSI SQL |
Java SE 8 |
日期 |
本地日期 |
时间 |
当地时间 |
时间戳 |
本地日期时间 |
时区时间 |
偏移时间 |
带有时区的时间戳 |
偏移日期时间 |
如何在 JDBC 中使用它?
LocalDate
下面给出了一个插入a 的示例代码columnfoo
(它是DATE
类型):
LocalDate localDate = LocalDate.now();
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, localDate);
st.executeUpdate();
st.close();
LocalDate
下面给出了从检索 a 的示例代码columnfoo
:
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
// Assuming the column index of columnfoo is 1
LocalDate localDate = rs.getObject(1, LocalDate.class));
System.out.println(localDate);
}
rs.close();
st.close();
从Trail: Date Time了解有关现代日期时间 API *的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring和How to use ThreeTenABP in Android Project。