Postgresql 与本地时区偏移一起存储的jOOQ时间戳

Postgresql 与本地时区偏移一起存储的jOOQ时间戳,postgresql,jdbc,timezone,timestamp,jooq,Postgresql,Jdbc,Timezone,Timestamp,Jooq,PostgreSQL 9.3/PostgreSQL-9.3-1100-jdbc41.jar 我有一个表,其列的类型为timestamp,不带时区,这将使用适用的java.util.timestamp属性生成我的对象 在insert过程中,我看到的是jOOQ的绑定过程将java.util.Timestamp转换为带有本地时区偏移的日期 例如,对于unix时间戳1421109419(2015年1月13日00:36:59 GMT),属性设置为新时间戳(1421109419*1000) 从jOOQ记录器

PostgreSQL 9.3/PostgreSQL-9.3-1100-jdbc41.jar

我有一个表,其列的类型为
timestamp,不带时区,这将使用适用的
java.util.timestamp
属性生成我的对象

在insert过程中,我看到的是jOOQ的绑定过程将
java.util.Timestamp
转换为带有本地时区偏移的日期

例如,对于unix时间戳1421109419(2015年1月13日00:36:59 GMT),属性设置为
新时间戳(1421109419*1000)

从jOOQ记录器中,我看到:

2015-01-13 14:14:31,482 DEBUG [http-bio-8002-exec-4] org.jooq.tools.LoggerListener#debug:255 - -> with bind values      : insert into "foo"."bar" ("start_date") values (timestamp '2015-01-13 13:36:59.0') returning "foo"."bar"."id"

2015-01-13 14:14:31,483 TRACE [http-bio-8002-exec-4] org.jooq.impl.DefaultBinding#trace:179 - Binding variable 3       : 2015-01-13 13:36:59.0 (class java.sql.Timestamp)
记录中的值无疑是“2015-01-13 13:36:59”

该软件在NZDT中的机器上运行,解释+13偏移

考虑到时间是在时区不可知的容器(Timestamp)中提供的,我希望在创建insert语句时遵守这一点


我如何让jOOQ创建非本地时间的时间戳?

不幸的是,您遇到了一些问题:

  • PostgreSQL JDBC驱动程序在Postgres会话中将时区设置为JVM时区。因此,即使数据库服务器在UTC中运行,也会使用JVM的时区插入时间戳字段。当您插入或查询数据时,数据库服务器将始终使用JVM时区
  • 您使用的是时间戳而不是时间戳。这些类型的描述并不反映它们的实际使用情况。TIMESTAMPTZ实际上意味着时区不可知论。无论插入什么值,都将使用会话时区将其调整为UTC 由于这两个问题,如果您有两个不同的JVM——一个使用洛杉矶时间,另一个使用纽约时间——每当您使用一个JVM编写时间戳时,另一个JVM中的“UTC时间”将不同。时间戳接受调整后的值,并按给定值使用它。如果将时间戳列更改为TIMESTAMPTZ,那么两个JVM中的相同时间将始终是相同的UTC时间

    如果查看Postgres JDBC驱动程序的ConnectionFactoryImpl#openConnectionImp,您可以看到它将本地JVM的时区设置为数据库服务器会话区域的时区的位置

    所以处理这个问题的唯一明智的方法就是只使用TIMESTAMP而不是TIMESTAMP。以下是有关这方面的更多信息:

    以下(非常讨厌的)代码适合我:

    eventsRecord.setCreatedOn(new Timestamp(System.currentTimeMillis() 
      - TimeZone.getDefault().getOffset(new Date().getTime())));
    
    Alas jOOQ在保存到PostgreSQL“timestamp without timezone”或MySQL“datetime”字段时只使用本地时区。这种讽刺的源代码证据是,它既没有指定时区,也没有任何工具让用户覆盖此功能并指定时区。这使得jOOQ中这种非常基本的数据类型的使用完全无用,因为许多具有不同时区的客户端都将数据写入同一字段,而不记录其时区,也不将数据标准化为UTC


    JDBC提供了一个额外的功能,用户可以在其中指定所需的时区(UTC基本上是唯一有意义的值)。然而,jOOQ“抽象”了JDBC,不提供这种功能。

    那么您的域模型有直接定义的
    时间戳
    字段吗?所以它没有经过jOOQ转换器?正确-
    java.util。Timestamp
    是由jOOQ生成的,也是由我填充的。没有中间转换器。我看到一些关于PostgreSQL驱动程序的引用是导致这种情况的原因。如果是这样的话,在jOOQ中是否有任何方法可以利用时间戳作为历元值的函数,例如
    没有时区“历元”+1421109419*间隔“1秒”
    ?我不确定这些信息是否适用于您的案例,但在我的案例中,我尝试使用
    介于(日期1,日期2)
    ;无论这两个日期对象位于哪个时区,查询总是将它们转换为本地时间。我可以在(date1.toString(),date2.toString())
  • 之间使用
    ,两个日期对象使用UTC。