JDBC将日期转换为UTC

3

我有一些代码将时间戳插入到Postgres表中。下面是时间戳插入的字段定义:

datelast timestamp without time zone

我使用这段Java代码来更新字段中的数据:

PreparedStatement sqlStatement = connection.prepareStatement(
        "UPDATE datetest SET datelast = ? WHERE id = ? ");
    sqlStatement.setTimestamp(1, new java.sql.Timestamp((new Date()).getTime()));
    sqlStatement.setInt(2, 1);
    sqlStatement.executeUpdate();

我的问题是,它插入的是UTC时间戳,而不是我的本地时间戳(东部时间)。因此,当我在表中检查数据时,我看到的是“2010-02-08 19:07:21.261”,而不是“2010-02-08 14:07:21.261”。
实际上,我在旧服务器上运行了这段代码,它能够按照我想要的方式运行,但在迁移代码后,我遇到了这个问题。问题不在于Postgres,因为我仍然使用相同的数据库。我还检查了操作系统的时区,它们是相同的。我还尝试了一个“System.out.println("TZ = " + TimeZone.getDefault());”,并且在两台服务器上都得到了相同的时区。因此,我的结论是JDBC驱动程序在将日期转换为UTC之前将其插入表中。
有人能帮我弄清楚为什么会转换时间戳吗?
谢谢

如果你的列特别是“without time zone”,那么你想要所有日期都存储在协调世界时,以便你有一个恒定的参考点吗? - matt b
请查看以下链接中相关问题的答案:https://dev59.com/kXRB5IYBdhLWcg3wyqOo#3430957 - Derek Mahar
3个回答

3
正如Paul Clapham所提到的,postgres确实总是以UTC存储时间戳值

对于带有时区的时间戳,内部存储的值始终为UTC(协调世界时,传统上称为格林尼治标准时间,GMT)。具有明确时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中未指定时区,则假定其处于系统时区参数指示的时区,并使用时区的偏移量将其转换为UTC。

当输出带有时区的时间戳值时,它始终从UTC转换为当前时区,并在该时区中显示为本地时间。要查看另一个时区的时间,请更改时区或使用AT TIME ZONE结构(请参阅第9.9.3节)。

本手册部分涉及带时区的时间戳,但可以假设相同的内部存储适用于不带时区的时间戳

这很有趣,但这并不能解释为什么它从我的旧服务器上正常工作,而从新服务器上却不行... 我是否应该在我的Java代码中添加一些内容以使其像以前一样工作? - MaxP

1
当您说“检查我表中的数据”时,我想您在使用一些数据库查看工具?了解您如何获取这些值将有所帮助。
如果您的数据库内部存储了UTC时间,那么发现它并不会让我感到意外。然后提取数据的软件将显示选定时区的时间。实际上,我不希望发现它将数据存储为依赖于数据库服务器上默认时区的内容,因为更改默认时区(或将数据库移动到具有不同默认时区的不同服务器)将更改所有数据。那将是一件坏事。

我使用命令行“psql”界面,并执行简单的“select * from datetest”。 - MaxP

1

我的问题与Postgres的JAR文件有关。

在我的旧服务器上,我使用的是Postgres 7 JAR文件,一切都运行良好。由于某种原因,在我的新服务器上它不再工作了。我用Postgres 8的JAR文件替换了它,现在一切都正常了。当我在数据库中插入时间戳时,它现在插入的是我的本地时间,而不是GMT时间。

感谢大家的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接