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

mar*_*ers 1 postgresql timezone timestamp jdbc jooq

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

我有一个类型列的表timezone without time zone,这将生成我的具有适用java.util.Timestamp属性的对象.

在插入期间,我看到的是jOOQs绑定过程将a 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)
Run Code Online (Sandbox Code Playgroud)

确实在记录中的值是"2015-01-13 13:36:59".

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

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

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

rob*_*lco 5

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

  1. PostgreSQL JDBC驱动程序在Postgres会话中为JVM时区设置时区.因此,即使您的数据库服务器以UTC格式运行,也会使用JVM的时区插入TIMESTAMP字段.插入或查询数据时,数据库服务器将始终使用JVM时区.
  2. 您正在使用TIMESTAMP而不是TIMESTAMPTZ.这些类型的描述并未反映其实际用途.TIMESTAMPTZ实际上意味着时区不可知.无论您插入什么值,它都将使用会话时区调整为UTC.

由于这两个问题,如果您有两个不同的JVM - 一个使用洛杉矶时间而另一个使用纽约时间 - 每当您使用一个JVM编写TIMESTAMP时,它将是另一个JVM中不同的"UTC时间".TIMESTAMP获取调整后的值,并按指定使用它.如果将TIMESTAMP列更改为TIMESTAMPTZ,则两个JVM中的相同时间将始终为相同的UTC时间.

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

因此,处理此问题的唯一理智方法是仅使用TIMESTAMPTZ而不是TIMESTAMP.以下是有关此内容的更多信息:

PostgreSQL/JDBC和TIMESTAMP与TIMESTAMPTZ

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