java - JDBC 插入与服务器时间戳不同的 now()

标签 java postgresql jdbc timezone timestamp

对于这个 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 [当前服务器 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',

或者最好是带有时区的时间戳:

"datetime" TIMESTAMP WITH TIME ZONE DEFAULT current_timestamp,

关于java - JDBC 插入与服务器时间戳不同的 now(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26162964/

相关文章:

java - Android 必须有 id 为的 Expandableview

Java - 如何查看一个字符是否与多个字符匹配?

java - 如何读取hibernate生成的所有表名?

jdbc - Hive JDBC 与 CLI 客户端

java - JDBC未连接到Web服务中的数据库

java - Spring Cloud 流卡夫卡 : Duplicate @StreamListener mapping for 'input'

java - 改变Sprite在unity中的位置

function - 在 PostgreSQL 中截断模式中的所有表

arrays - 在 begin 和 end 中动态创建数组

hadoop - Hive 将值插入数组复杂类型列