繁体   English   中英

postgresql JDBC驱动程序使用客户端时区

[英]postgresql JDBC driver uses client time zone

我正在使用postgresql-42.2.2.jar jdbc驱动程序和postgresql 9.6服务器。

如何配置连接以使用服务器时区而不是客户端时区?

查询:

select id, TO_TIMESTAMP(tbl.ended_time / 1000)
FROM tbl
where TO_TIMESTAMP(tbl.ended_time / 1000) >= now()::date + interval '1m'

使用pgadmin运行查询我得到以下结果(正确)

"2185"  "2018-06-22 00:02:02-05"
"2186"  "2018-06-22 00:03:01-05"
"2187"  "2018-06-22 00:13:02-05"

但是使用JDBC驱动程序运行相同的查询,结果是:

2169 2018-06-22 07:13:01.0
2181 2018-06-22 08:33:02.0
2180 2018-06-22 08:23:01.0
2185 2018-06-22 09:02:02.0
2186 2018-06-22 09:03:01.0
2187 2018-06-22 09:13:02.0

如果没有使用pgadmin运行的查询,结果将是:

"2169"  "2018-06-21 22:13:01-05"
"2181"  "2018-06-21 23:33:02-05"
"2180"  "2018-06-21 23:23:01-05"
"2185"  "2018-06-22 00:02:02-05"
"2186"  "2018-06-22 00:03:01-05"
"2187"  "2018-06-22 00:13:02-05"

这是代码:

static String URL = "jdbc:postgresql://some_ip:7000/db";
static String USERNAME = "test";
static String PASSWORD = "test";
static String JDBC_DRIVER = "org.postgresql.Driver";

public static void main(String[] args) {
    String query = "select id, TO_TIMESTAMP(tbl.ended_time / 1000) FROM tbl where TO_TIMESTAMP(tbl.ended_time / 1000) >= now()::date + interval '1m'";
    Connection conn = null;

    try {
        Class.forName(JDBC_DRIVER);
        conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        Statement st = conn.createStatement();          
        ResultSet rs = st.executeQuery(query);
        while (rs.next()) {             
            System.out.println(rs.getObject(1) + "--" + rs.getObject(2));
        }
        rs.close();
        st.close();
        conn.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

}

正如解释这里的JDBC驱动程序使用本地时区而不是服务器时区。

不幸的是,没有简单的方法可以更改该行为或查询服务器的时区。

另请注意,使用OffsetDateTime检索数据并没有太大帮助:

rs.getObject(2, OffsetDateTime.class)

因为不幸的是,驱动程序返回了所有偏移量为0的 OffsetDateTime ,所以时区信息丢失了。

因此,最好的选择似乎是对数据库的时区进行硬编码并使用Java计算时限,或者将时区分别存储在数据库中并进行查询。

TL; DR:与JDBC驱动程序无关。 SQL有缺陷。

比较timestamp WITH time zone timestamp withOUT time zone timestamp WITH time zone timestamp withOUT time zone timestamp WITH time zone您会有什么期望? 您的SQL完全是错误的,因此会产生奇怪的结果。

您对now()::date有何期待? 注意:PostgreSQL文档没有说明now()将产生哪个时区。 它仅指定“时区将存在”,但是它甚至可以从一个PG版本更改为另一个PG版本。 因此,您基本上是在要求“随机值”。

请阐明您要实现的目标,然后编写适当的SQL。 例如,如果要获取带有时间戳的记录“欧洲/柏林时区的当前日期的00:00:00之后”,则可以使用类似

where TO_TIMESTAMP(tbl.ended_time / 1000) >= ((now() at time zone 'Europe/Berlin')::date + interval '4m')::timestamp at time zone 'Europe/Berlin'

关键是没有“一天的开始”,除非您指定要表示的时区。 pgjdbc填充使用默认时区的会话( TimeZone.getDefault()因此被隐式转换使用,但是我强烈对比,从建议你withwithout时区同类SQL数据类型的,不管你用什么来执行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM