tl;博士
if(
myResultSet.getObject( … , Instant.class ) // Retrieve `Instant` (a moment in UTC) from database using JDBC 4.2 or later.
.isBefore( Instant.now() ) // Comparing to the current moment captured in UTC.
)
{
…
}
java.util.Date 与 java.sql.Date
您可能会混淆这对不幸命名错误的类。第一个是日期与时间类型,以 UTC 为单位。第二种是仅日期类型。实际上,第二个 假装 是仅日期类型,但实际上将时间设置为 00:00:00。更糟糕的是,第二个继承自第一个,但文档指示我们忽略这一事实。
令人困惑?是的。这些糟糕的类设计得很糟糕。避开他们。
java.time
您正在使用非常麻烦的旧日期时间类,这些类在几年前已被 java.time 类取代。
Instant
java.util.Date 类已替换为 java.time.Instant。 Instant 类代表UTC 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
LocalDate
java.sql.Date 类已替换为 java.time.LocalDate。 LocalDate 类表示没有时间和时区的仅日期值。
JDBC 4.2
从 JDBC 4.2 及更高版本开始,您可以直接与数据库交换 java.time 类。无需再次使用 java.sql 或 java.util 日期时间类型。
提示:养成始终使用PreparedStatement 的习惯,以避免SQL Injection 的风险。习惯了就不用再工作了。
Instant instant = Instant.now() ; // Capture the current moment in UTC.
myPreparedStatement.setObject( … , instant ) ;
和检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
智能对象,而不是哑字符串
这是我使用的格式:yyyy-MM-dd HH:mm:ss`
存储在数据库中的日期时间值没有“格式”。这些值由一些与我们无关的内部定义的机制存储。它们是 not 字符串(也就是说,不在任何严肃的数据库中)。
您的数据库和 Java 日期时间对象可以解析一个表示日期时间值的字符串来创建该值。他们可以生成一个字符串来表示该值。但是字符串和日期时间值是不同的和分开的,不应该混为一谈。
使用 java.time 对象与您的数据库交换日期时间值,而不仅仅是字符串,就像您对数据库理解的数字和其他数据类型一样。仅使用字符串来传达文本值。
比较
要将检索到的值与当前时刻进行比较,请使用 Instant 类的 isBefore、isAfter 和 equals 方法。
Instant now = Instant.now() ;
…
Instant instant = myResultSet.getObject( … , Instant.class ) ;
boolean isPast = instant.isBefore( now ) ;
if ( isPast ) {
…
}
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。