jOOQ使用本地时区偏移量存储时间戳

时间:2015-01-13 01:42:12

标签: postgresql jdbc timezone timestamp jooq

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

我有一个类型为timezone without time zone的列的表,这会生成具有适用的java.util.Timestamp属性的Object。

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

例如,对于unix时间戳1421109419(2015年1月13日00:36:59 GMT),该属性设置为new Timestamp(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偏移量。

鉴于TimeZone不可知容器(Timestamp)中提供的时间,我希望在创建insert语句时能够得到尊重。

如何让jOOQ创建时间戳不是在当地时间?

2 个答案:

答案 0 :(得分:5)

不幸的是,你有一些事情不利于你:

  1. PostgreSQL JDBC驱动程序在Postgres会话中为JVM时区设置时区。因此,即使您的数据库服务器以UTC格式运行,也会使用JVM的时区插入TIMESTAMP字段。插入或查询数据时,数据库服务器将始终使用JVM时区。
  2. 您正在使用TIMESTAMP而不是TIMESTAMPTZ。这些类型的描述并未反映其实际用途。 TIMESTAMPTZ实际上意味着时区不可知。无论您插入什么值,它都将使用会话时区调整为UTC。
  3. 由于这两个问题,如果您有两个不同的JVM - 一个使用洛杉矶时间而另一个使用纽约时间 - 每当您使用一个JVM编写TIMESTAMP时,它将是一个不同的" UTC时间& #34;在另一个JVM中。 TIMESTAMP获取调整后的值,并按指定使用它。如果将TIMESTAMP列更改为TIMESTAMPTZ,则两个JVM中的相同时间将始终为相同的UTC时间。

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

    所以解决这个问题的唯一理智方法是只使用TIMESTAMPTZ代替TIMESTAMP。以下是有关此内容的更多信息:

    PostgreSQL/JDBC and TIMESTAMP vs. TIMESTAMPTZ

    http://justatheory.com/computers/databases/postgresql/use-timestamptz.html

答案 1 :(得分:0)

以下(非常讨厌的)代码对我有用:

eventsRecord.setCreatedOn(new Timestamp(System.currentTimeMillis() 
  - TimeZone.getDefault().getOffset(new Date().getTime())));

Alas jOOQ在保存到PostgreSQL时只使用本地时区"时区没有时区"或MySQL" datetime"领域。此次歪曲的源代码证据是here,它没有指定时区,也没有任何设施供用户覆盖此功能并指定时区。这使得来自jOOQ的这种非常基本的数据类型的使用完全无用,大量客户端都使用不同的时区将数据写入同一字段而不记录其时区,也不将数据规范化为UTC。

JDBC提供了额外的three-argument setTimestamp,用户可以在其中指定所需的时区(UTC基本上是唯一有意义的值)。然而,jOOQ"摘要"远离JDBC并且不提供此功能。