Mop*_*mar 1 java hibernate sql-server-2014
我想UTC在 sql server 2014 中使用时区保存日期。我曾经ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("UTC"))使用 Hibernate 会话对象获取当前日期时间并将其持久化到 db。在调试时,我可以看到在 Java 程序中日期是这样的2019-09-25T13:22:29.573Z[UTC],但是在数据库列中保存后它是这样的2019-09-25 18:53:23.3630000。它会根据系统时间自动转换时间部分。任何人都可以请建议是什么问题?我datetime2在数据库中创建此列时使用了数据类型。
您的列使用了错误的数据类型。
类型datetime2不能代表片刻。该类型仅存储日期和时间,但缺少时区或 UTC 偏移量的上下文。因此,如果您存储“2020 年 1 月 23 日中午”,我们无法知道您是指日本东京的中午、突尼斯突尼斯的中午还是美国俄亥俄州托莱多的中午,这三个不同的时刻相隔几个小时。这种错误类型类似于 SQL 标准类型TIMESTAMP WITHOUT TIME ZONE。Java 中的等效类是LocalDateTime.
如果您已经存储了数据,则需要重构数据库。基本上,添加一个正确类型的新列,为每一行复制数据,随时转换。当然,这仅在您知道保存的每个值中不存在的预期时区时才有效。
虽然我不使用 Microsoft SQL Server,但根据文档,您应该使用类型datetimeoffset为column to record a moment。此类型将任何提交的值调整为 UTC 以进行查询和排序,同时还记录偏移量。此类型类似于 SQL 标准类型TIMESTAMP WITH TIME ZONE。
通常最好以 UTC 格式存储您的时刻,偏移量为零时-分-秒。
本Instant类表示UTC片刻。
Instant instant = Instant.now() ;
Run Code Online (Sandbox Code Playgroud)
如果您有ZonedDateTime,则可以提取Instant.
Instant instant = zdt.toInstant() ;
Run Code Online (Sandbox Code Playgroud)
我们想将其Instant直接保存到数据库中。不幸的是,JDBC 4.2 soec 不需要支持两个最常用的java.time类:Instant和ZonedDateTime. 该规范确实需要支持OffsetDateTime. 所以我们转换。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
Run Code Online (Sandbox Code Playgroud)
提交到数据库。
myPreparedStatement.setObject( … , odt ) ;
Run Code Online (Sandbox Code Playgroud)
取回。
OffsetDateTime odt = MyResultSet.getObject( … , OffsetDateTime.class ) ;
Run Code Online (Sandbox Code Playgroud)
提取 anInstant以在您的代码中明确您需要 UTC。
Instant instant = odt.toInstant() ;
Run Code Online (Sandbox Code Playgroud)
通过特定地区(时区)的人们使用的挂钟时间查看这一刻。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
695 次 |
| 最近记录: |