3

我有一个 java 程序,它以二进制格式的 Postgresql 的 COPY 命令所期望的二进制格式生成时区值。数据被写入二进制文件,然后我使用复制命令将其插入到 Postgresql 中,并插入到带有时间戳列(无时区)的表中。

该格式本质上是数字 8 作为 4 字节值,后跟自 2000-01-01 以来的微秒作为 8 字节值。

我发现 Postgresql 和 Java 对时区偏移的解释有所不同。当我尝试写日期时:

2004-11-01 09:34:42.432

在 postgres 二进制格式中是

0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x8a, 0xcd, 0xe3, 0x10, 0x68, 0x00

并且 postgres 正确报告日期。但是,如果我输入日期

2010-11-01 09:34:42.432

在二进制中是

0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x36, 0xf8, 0x72, 0xcb, 0x64, 0x00

我得到 2010-11-01 08:34:42.432 作为 Postgres 中的时间戳。

进一步的调查表明,Postgres 认为 2010 年的 UTC 偏移量是 -5,而 Java 认为它的 -4(我相信这是正确的)导致一小时的差异。有谁知道解决这个问题的方法是什么?

相关资料:

Postgresql 版本 9.2.4

爪哇:7

在东部时区(美国/纽约)工作。

操作系统:Linux(时区设置正确)

4

2 回答 2

1

弄清楚了。原来 Postgres 期望的时间戳列的微秒是自 2000 年 1 月 1 日 UTC 以来的微秒。换句话说,需要从 2000 年 1 月 1 日 UTC 减去当前时间,而不是从本地 2000 年 1 月 1 日减去当前时间。我做的是后者。

帮助他人的其他信息:

  1. 如果您的列是没有时区的时间戳:从当前时间发送微秒 - 2000 年 1 月 1 日 UTC + tz 偏移量(以微秒为单位)
  2. 如果您的列是带时区的时间戳:从当前时间发送微秒 - 2000 年 1 月 1 日 UTC。

(1) 在 UTC 中有效地“按原样”变为当前时间(即,如果您尝试当地时间上午 9:00,如果偏移量为 -3,则不要将其设为 UTC 下午 12:00,而是将其编码为 9: UTC 时间上午 00 点)减去 2000 年 1 月 1 日 UTC。重要的事实是,这与(本地时区的当前时间)-(本地时区的 2000 年 1 月 1 日)不同。

免费插件我有一个 Java 库,用于使用 JPA 注释实体集合中的 COPY 命令将行直接插入 Postgresql。可在 github 获得:https ://github.com/eclecticlogic/pedal-dialect

于 2013-11-14T14:59:32.910 回答
0

Linux 命令行的快速测试表明 America/New_York 的 2010-11-01 是 EDT (-4)。您在 Postgresql 和 Java 中是否有相同的时区规范?您使用的是哪个 Java 版本——它们使用相同的 TZif 数据库,但可能使用不同的版本。如果您使用 Postgresql 9.2.4 或更高版本进行测试,您会得到相同的结果吗?

于 2013-11-14T14:11:51.370 回答