不带时区的 PostgreSQL 时间戳与带时区的 java.util.Date 的比较

Comparsion between PostgreSQL timestamp without timezone and java.util.Date with timezone

我想知道如何执行以下查询中的比较:

StringBuilder queryStr = new StringBuilder();
queryStr.append("SELECT o FROM PRDBook as o WHERE ")
        .append("o.publicationDate < :now");

Query query = entityManager.createQuery(queryStr.toString());
Date now = new Date();
query.setParameter("now", now);

在数据库中,列 publicationDate 的类型为 timestamp without time zone。此列中的示例值:

2018-03-01 18:00:00

now.toString()的结果是:

Wed Aug 22 16:14:03 CEST 2018

是否会以这种方式执行上述数据之间的比较:

2018-03-01 18:00:00 < 2018-08-22 16:14:03

或者那样:

2018-03-01 18:00:00 < 2018-08-22 14:14:03

有趣的问题。

当 PostgreSQL 的 JDBC 驱动程序读取类型为 timestamp without time zone 的列时,它通常可以将其读取为 java.sql.Timestampjava.util.Date

如果您选择将其读取到 java.util.Date(您的情况),PostgreSQL 的 JDBC 驱动程序会自动将本地 JVM 时区添加到其中。这是有道理的,因为 timestamp without time zone 类型的列的整个点将被视为 "local" 时间戳。

相反,当您向数据库发送 java.util.Date 时,它会立即删除时区。因此查询条件将采用以下形式:

2018-03-01 18:00:00 < 2018-08-22 16:14:03

顺便说一下,这意味着 建议您显式设置 JVM 时区,以确保 JDBC 驱动程序正在将数据库 timestamp without time zone 重新组装成一个java.util.Date 正确的方法。

否则,不同时区的不同服务器在读取同一数据库中的相同行时会将时间戳解释为不同的时刻。然而,对于使用 "local" 时间戳的应用程序,这可能不是一个有效的用例。