Java 在使用jdbc时如何使用时区保存正确的日期时间
我正在使用Java和JDBC连接到PostgreSQL数据库。我在将时间保存到数据库时遇到问题。我的数据库中有一个表student,其列如下所示Java 在使用jdbc时如何使用时区保存正确的日期时间,java,postgresql,jdbc,timezone,Java,Postgresql,Jdbc,Timezone,我正在使用Java和JDBC连接到PostgreSQL数据库。我在将时间保存到数据库时遇到问题。我的数据库中有一个表student,其列如下所示 Id,Name,Created_at(timestamp) //some row here 我使用JDBC连接到PostgreSQL并保存数据 jdbc:postgresql://localhost:3306/someDatabase?useSSL=false&serverTimezone=UTC 当我插入数据时,我的数据看起来像 Stu
Id,Name,Created_at(timestamp)
//some row here
我使用JDBC连接到PostgreSQL并保存数据
jdbc:postgresql://localhost:3306/someDatabase?useSSL=false&serverTimezone=UTC
当我插入数据时,我的数据看起来像
Student student = new Student()
student.name = "some name";
student.createdAt = LocalDateTime.now()
//一些逻辑保存
但是,当我插入数据库时,PostgreSQL保存的时间与我的服务器保存的时间相同。我想如果我的时间服务器是“2021-10-10 00:00:00”,当我保存到数据库时,它必须以
"2021-10-09 15:00:00". 我想当它保存它必须转换为时区日本
当我选择数据库时,PostgreSQL+9上的时区。如果我更改代码,例如:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
这对我没有帮助。您使用了错误的类和类型 切勿使用
时区
和时间戳
类。这些是Java最早版本中糟糕的日期时间类的一部分,多年前被JSR310中定义的现代Java.time类所取代。特别被ZoneId
和Instant
/OffsetDateTime
取代
在Postgres中,确保在列创建的类型为带时区的时间戳
,而不是不带时区的
通常最好将当前时刻捕捉为瞬间
。该类表示UTC中的一个时刻
Instant instant = Instant.now() ;
不幸的是,编写JDBC 4.2规范的人莫名其妙地需要对OffsetDateTime
的支持,而不是对两个更常用的类Instant
和ZonedDateTime
的支持。不管怎样,如果您的特定JDBC驱动程序不支持Instant
,我们可以轻松地来回转换
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
或者,跳过即时
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
发送到数据库
myPreparedStatement.setObject( … , odt ) ;
检索
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
这里的LocalDateTime
类是错误的。该类表示不带时区上下文或UTC偏移量的日期和时间。所以这个类不能代表一个时刻,时间线上的一个点。所以这个类不能用来记录什么时候发生了什么。我想不出调用LocalDateTime.now()
是正确的做法
这些主题已经在许多现有的问题和答案中讨论过。搜索了解更多信息。需要对OffsetDateTime
的支持,而不是Instant
和zoneDateTime
:SQL标准只定义了对基于偏移的时区类型的支持,因此JDBC也是如此。使用Instant
不会保留任何已存储的偏移量信息,存储与使用偏移量为零的OffsetDateTime
没有太大区别。@markrotVeel使用ZoneOffset在Instant
和OffsetDateTime
之间来回转换。UTC
非常简单。为什么不要求JDBC驱动程序执行转换以方便调用程序的程序员呢?关于ZonedDateTime
,感谢您的解释,这现在是有意义的。因为瞬间不是OffsetDateTime,并且选择仅使用直接映射到等效SQL标准类型的类型。