DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

pgJDBC 42.7.9 把 0001-01-01 读偏两天

pgJDBC 42.7.9 的日历转换回归可能使历史日期偏移,42.7.10包含回滚修补,可用只读日期和 LocalDate 对照诊断。

PostgreSQL 中保存的是 0001-01-01,Java 调用 getDate() 或 getTimestamp() 却得到偏移后的历史日期,getObject(..., LocalDate.class) 又正常。pgJDBC 42.7.9 的日历转换回归可以造成这种差别;写入路径也可能把原值变成公元前日期。

相关变更把旧日历路径统一改为前推的 Gregorian 日历,影响了 java.sql.Date、Timestamp 与已有历史日期转换之间的约定。pgJDBC 42.7.10 回滚了这项改动。这个问题不能靠修改 SQL 列的时区解决,DATE 本来就不代表带时区的时刻。

先用只读值比较三条读取路径

下面的查询不需要建立表,也不会修改现有日期:

try (Statement st = connection.createStatement();
     ResultSet rs = st.executeQuery("SELECT DATE '0001-01-01'")) {
    if (!rs.next()) {
        throw new IllegalStateException("Missing test row");
    }
    System.out.println(rs.getString(1));
    System.out.println(rs.getDate(1));
    LocalDate date = rs.getObject(1, LocalDate.class);
    System.out.println(date);
    if (!LocalDate.of(1, 1, 1).equals(date)) {
        throw new IllegalStateException("Unexpected LocalDate");
    }
}

代码使用应用已有连接,并导入 java.sql.Statement、java.sql.ResultSet、java.time.LocalDate。先记录实际 pgJDBC 版本、JDK 和运行环境;字符串与 LocalDate 正常而旧日期类型偏移,是区分读取转换与数据库存值的重要线索。

42.7.10 包含回滚修补,应更新到包含该修正、符合项目要求的维护版本,再复核原有历史日期用例。对业务只表达日期的字段,可以使用 JDBC 明确支持的 LocalDate 类型;写入时也通过 setObject() 保留这个类型契约,而不要先走一次旧日期类型转换。

不要批量给日期加减两天

0001-01-01 是诊断样本,不是对所有年代都适用的修正公式。不同日历转换及日期区间需要分别判断,按一个样本把所有历史日期加减两天,会修改原本正确的数据。

如果之前已经执行过写入,应核对数据库中的真实日期、原始输入和应用路径,而不是仅看 Java 当前显示值。读取修补不会自动撤回早先写错的数据,也不能从偏移后的值推断所有记录的原值。

验收应覆盖现代日期、业务实际使用的历史日期,以及读取和写入的往返契约。旧 Date、Timestamp 路径与 LocalDate 不能混为一个测试结果;使用新类型也不代表所有公元前日期或超出 Java 类型范围的值都无需处理。