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 类型范围的值都无需处理。


