我正在提供现代答案。
java.time 和 JDBC 4.2
您应该避免使用 Timestamp 类。它的设计很糟糕而且非常令人困惑,这是对已经设计很糟糕的java.util.Date 类的真正破解。在我看来,其他答案导致不同结果的事实很好地说明了这种混淆。您已经在使用现代 Java 日期和时间 API java.time 中的OffsetDateTime,并且只要您拥有符合 JDBC 4.2 的 JDBC 驱动程序,您就可以并且应该坚持使用 java.time 中的类。
最好存储为timestamp with time zone
按照您的意愿在数据库中以 UTC 格式存储日期和时间是一种很好的推荐做法。如果可以,请将数据库中的数据类型更改为timestamp with time zone。虽然这不存储时区(尽管有名称),但它确保数据库“知道”时间戳是 UTC,这已经防止了许多错误。下一个优点是(只要我理解正确)您可以直接存储您的OffsetDateTime 并让转换为 UTC 自动发生。
OffsetDateTime odt = OffsetDateTime.of(
2015, 6, 4, 19, 15, 43, 210987000, ZoneOffset.ofHours(1));
PreparedStatement stmt = yourDbConnection.prepareStatement(
"insert into your_table (your_timestamp_with_time_zone) values (?);");
stmt.setObject(1, odt);
stmt.executeUpdate();
如果您想在 Java 代码中更清楚地表明时间是以 UTC 存储的,请先显式转换:
odt = odt.withOffsetSameInstant(ZoneOffset.UTC);
如果您的数据库存储timestamp 没有时区
如果您的数据库中的数据类型仅为timestamp(无时区)(不推荐),则在Java 端使用的类型为LocalDateTime。我会像这样转换为 UTC:
LocalDateTime ldt = odt.withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();
System.out.println("UTC datetime = " + ldt);
输出是:
UTC 日期时间 = 2015-06-04T18:15:43.210987
存入数据库与之前类似:
PreparedStatement stmt = yourDbConnection.prepareStatement(
"insert into your_table (your_timestamp) values (?);");
stmt.setObject(1, ldt);