对于这个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会用服务器时间戳填充字段,但我希望在不更改数据类型的情况下解决它,因为表被其他程序和报告使用。
TimeZone
变量设置为JVM时区。它要求时间戳代码正确运行,并且(IIRC)正确遵守JDBC规范。(详见org/postgresql/core/v3/ConnectionFactoryImpl.java
中的createPostgresTimeZone
)。
now()
是current_timestamp
的别名,它返回一个timestamp with time zone
。
从timestamp with time zone
到timestamp 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,