JDBC inserting now()与服务器时间戳不同



对于这个PostgreSQL测试表:

CREATE TABLE public.test (
  id BIGSERIAL,
  "datetime" TIMESTAMP WITHOUT TIME ZONE DEFAULT now(),
  value INTEGER,
  CONSTRAINT test_pkey PRIMARY KEY(id)
) 

我正在使用此SQL插入:

INSERT INTO it.test (value) VALUES (1);

当我从EMS或PgAdmin这样的远程客户端执行INSERT时没有问题。字段datetime完全由服务器时间戳填充,但当我使用Postgres/JDBC驱动程序(postgresql-9.2-1002.jdbc4.jar)从Java程序执行INSERT时,字段datetime填充的时间戳与服务器不同。

我读到JVM使用本地PC时区。有什么办法可以避免这种情况吗?

如果我将数据类型从timestamp更改为timestampz,java会用服务器时间戳填充字段,但我希望在不更改数据类型的情况下解决它,因为表被其他程序和报告使用。

这里的问题是PgJDBC在连接时将TimeZone变量设置为JVM时区。它要求时间戳代码正确运行,并且(IIRC)正确遵守JDBC规范。(详见org/postgresql/core/v3/ConnectionFactoryImpl.java中的createPostgresTimeZone)。

now()current_timestamp的别名,它返回一个timestamp with time zone

timestamp with time zonetimestamp without time zone的转换与写入current_timestamp at time zone [the current server TimeZone]相同,即它将时间戳重新解释为在新时区中。

由于当您通过其他客户端连接时,TimeZone是不同的,因此会得到不同的结果。因此,对于将TimeZone设置为本地时间的客户端来说,DDL也是错误的。

为了使其一致,使列timestamp with time zone(通常更可取),或将default重新定义为:

"datetime" TIMESTAMP WITHOUT TIME ZONE DEFAULT now() AT TIME ZONE 'CEST',

或者服务器时区是什么。如果这样做,请小心!有三种方法可以指定时区,并且必须确保使用与服务器配置中相同的时区,否则会有不同的节约时间处理!

不用说,我强烈建议只使用UTC:

"datetime" TIMESTAMP WITHOUT TIME ZONE DEFAULT current_timestamp AT TIME ZONE 'UTC',

或优选CCD_ 13:

"datetime" TIMESTAMP WITH TIME ZONE DEFAULT current_timestamp,

相关内容

  • 没有找到相关文章

最新更新