PostgreSQL 9.2 JDBC驱动程序使用客户端时区?

PostgreSQL 9.2 JDBC驱动程序使用客户端时区?,postgresql,jdbc,timezone,Postgresql,Jdbc,Timezone,我在使用带有PostgreSQL JDBC驱动程序的PostgreSQL数据库时遇到了一个有趣的挑战。最新版本的驱动程序9.2似乎在执行日期/时间匹配时使用了客户端时区 当服务器(JasperReports服务器)设置为UTC,而数据库服务器设置为US/Eastern时,这将成为一个问题 如果从设置为UTC时区的客户端运行以下查询,则使用9.0 JDBC驱动程序和9.2 JDBC驱动程序会得到不同的结果 select now(), extract(timezone FROM now()), cu

我在使用带有PostgreSQL JDBC驱动程序的PostgreSQL数据库时遇到了一个有趣的挑战。最新版本的驱动程序9.2似乎在执行日期/时间匹配时使用了客户端时区

当服务器(JasperReports服务器)设置为UTC,而数据库服务器设置为US/Eastern时,这将成为一个问题

如果从设置为UTC时区的客户端运行以下查询,则使用9.0 JDBC驱动程序和9.2 JDBC驱动程序会得到不同的结果

select now(), extract(timezone FROM now()), current_setting('TIMEZONE'), now()-interval '1 hour' as "1HourAgo"
使用9.0 JDBC驱动程序的结果:

now                         date_part   current_setting     1HourAgo
2013-08-26 15:33:57.590089  -14,400     US/Eastern          2013-08-26 14:33:57.590089
now                         date_part   current_setting     1HourAgo
2013-08-26 15:41:49.067903  0           UTC                 2013-08-26 14:41:49.067903
使用9.2 JDBC驱动程序的结果:

now                         date_part   current_setting     1HourAgo
2013-08-26 15:33:57.590089  -14,400     US/Eastern          2013-08-26 14:33:57.590089
now                         date_part   current_setting     1HourAgo
2013-08-26 15:41:49.067903  0           UTC                 2013-08-26 14:41:49.067903
这会导致查询中的WHERE语句返回不正确的结果。比如说,

WHERE end_time between now() - interval '1 hour' and now()
使用9,0驱动程序可按预期工作,但使用9,2驱动程序不会返回任何结果,因为驱动程序似乎正在偏移end_time的值以匹配UTC(客户端时区)。以下是一个解决方案,但很难看:

WHERE end_time at time zone 'EDT' between now() - interval '1 hour' and now()
问题:

  • 以前有没有人遇到过这个
  • 这种行为的改变有什么解释吗?我在JDBC发行说明中找不到任何东西
  • 除了将驱动程序回滚到旧版本之外,还有什么其他建议吗

  • 谢谢

    使用本地时区作为默认时区是JDBC标准(和API文档)所要求的,并且由。但是,它也适用于JDBC设置或检索时间相关数据的所有其他区域


    另请参见我对

    的回答,我自己也遇到了这个问题。我验证了postgres jdbc驱动程序确实从jvm中获取了连接时区,但我无法找到覆盖此行为的方法。如果他们为此提供一个JDBCURL连接参数,那就太好了

    作为一种解决方法,我发现我的连接池库(HikariCP)可以为每个新连接执行sql语句:

    hikariConfig.setConnectionInitSql("set time zone 'UTC'");
    

    以防其他人对此感到困惑-您可以编辑启动SQLDeveloper的“conf”文件并添加以下行:

    AddVMOption -Duser.timezone=UTC
    
    我在以下位置的计算机上找到此文件:

    /opt/sqldeveloper/ide/bin/ide.conf
    

    感谢您在另一个答案中给我指出了正确的方向,我不知道JasperReports,但是一般来说,使用JSR-310(Java 8)日期/时间类型(由JDBC 4.2支持)应该可以工作,而不必担心数据库服务器和客户机之间的时区不匹配

    请参阅PostgreSQL JDBC驱动程序文档中的。

    短版本请尝试:

    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    

    您好,我们遇到了这个问题,客户端和服务器时区不匹配,我们需要使用“UTC”运行单元测试。通过查看postgres jdbc驱动程序的源代码(这是测试代码),我们通过在获得连接之前更改jvm内部的TZ来“修复”它。

    感谢您的回答,Mark。然而,它并没有真正回答我的问题,这个问题是针对PostgreSQL的JDBC驱动程序在9.0和9.2之间的变化而提出的。9.2似乎选择了客户端时区,而不是驱动程序所在的服务器时区,而9.0没有。这是驱动程序工作方式的一个严重变化,不管标准应该是什么。我浏览了JDBC驱动程序的发行说明,但没有看到任何表示变化的内容。我建议您在pgsql jdbc邮件列表上询问。以防万一:在连接阶段添加
    时区
    会话参数,它使DB在无法判断数据所在时区的情况下使用客户端时区进行计算。JVM使用操作系统报告的时区-如果这不正确,您可能应该更改操作系统设置。但是您可以在启动JVMSure时通过指定
    -Duser.timezone=UTC
    来覆盖这一点,但是您并不总是希望使用与jvm相同的时区。我可以通过进入我的“/opt/sqldeveloper/ide/bin/ide.conf”并添加“AddVMOption-Duser.timezone=UTC”来实现这一点这似乎对我没有影响@JimN@JimN的解决方案也可以使用C3P0实现。您需要实现
    com.mchange.v2.c3p0.ConnectionCustomizer
    接口(
    onAcquire
    方法),并设置
    c3p0.connectionCustomizerClassName
    配置属性。