PostgreSQL(PolarDB PG 16)在通过JDBC执行SELECT now() 时,总是返回Asia/Shanghai时区,即使数据库时区设置为UTC

后端开发 2026-07-12

我正在使用 PolarDB for PostgreSQL 16,以及一个使用PostgreSQL JDBC驱动的Java应用。

在我的Java代码中,我执行一个简单查询:

String query = "SELECT now();";
try {
    conn2 = driver2.connect(url2, info2);
    stmt2 = conn2.prepareStatement(query);
    rs2 = stmt2.executeQuery();
    while (rs2.next()) {
        String result = rs2.getString(1);
        System.out.println("Query Result: " + result);
    }
} catch (SQLException e) {
    System.out.println("Connection failed!");
    e.printStackTrace();
} finally {
    try {
        if (rs1 != null) rs1.close();
        if (rs2 != null) rs2.close();
        if (stmt1 != null) stmt1.close();
        if (stmt2 != null) stmt2.close();
        if (conn1 != null) conn1.close();
        if (conn2 != null) conn2.close();
        System.out.println("Resources closed!");
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

无论我如何修改数据库时区设置,这段Java代码输出的结果始终是Asia/Shanghai。

我在psql中看到的情况

如果我用psql连接:

youyou=> show timezone;
 TimeZone
----------
 UTC
(1 row)

youyou=> select now();
              now
-------------------------------
 2026-02-25 02:17:23.056023+00
(1 row)

并且

youyou=> show timezone;
   TimeZone
---------------
 Asia/Shanghai
(1 row)

youyou=> select now();
              now
-------------------------------
 2026-02-25 10:18:05.671536+08
(1 row)

psql的行为符合预期。

在Java中看到的情况

在同一数据库下,当我在两种配置(DB时区 = UTC,DB时区 = Asia/Shanghai)下运行我的Java代码时,输出始终为:

Connected!
Query Result: 2026-02-25 10:19:03.137973+08
Resources closed!

Connected!
Query Result: 2026-02-25 10:19:51.019322+08
Resources closed!

因此通过JDBC,SELECT now() 总是返回+08,即使psql的 show timezone显示为UTC。

我的问题

  1. 为什么JDBC总是给我Asia/Shanghai时区,即使数据库时区设置为UTC,且psql显示UTC?
  2. 在应用代码中控制这一点的推荐/优雅做法是什么?例如:
  3. 我应该在获得连接后显式设置会话时区吗?
  4. 还是应该在JDBC URL中传递一个时区参数? 对PostgreSQL / PolarDB + JDBC如何处理时区,以及如何在我的Java应用中获得一致的UTC时间戳,若能给出详细解释,将不胜感激。

解决方案

The timezone 参数不是数据库时区,而是会话时区。数据库服务器上的设置(在 postgresql.conf 中)只是会话时区的默认值。其思路是每个数据库客户端都应将 timezone 设置为合适的值——毕竟不同的客户端可能处在不同的时区。

JDBC驱动程序将会话时区设置为 JVM的默认时区,因此你要么修改它,要么在你的数据库会话中显式地 SET timezone

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章