对于这个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 Driver(postgresql-9.2-1002.jdbc4.jar)从Java程序执行INSERT时,字段datetime填充了与服务器不同的时间戳
我读到JVM使用本地PC时区。有什么方法可以避免这种情况吗?
如果我将数据类型从timestamp更改为timestampz,java会使用服务器时间戳填充该字段,但我想在不更改数据类型的情况下解决它,因为该表由其他程序和报告使用。
答案 0 :(得分:2)
这里的问题是PgJDBC在连接时将TimeZone
变量设置为JVM时区。它要求它的时间戳代码能够正确运行,并且(IIRC)要正确地遵守JDBC规范。 (有关详细信息,请参阅createPostgresTimeZone
中的org/postgresql/core/v3/ConnectionFactoryImpl.java
。)
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',
或最好是timestamp with time zone
:
"datetime" TIMESTAMP WITH TIME ZONE DEFAULT current_timestamp,