在 Java 中将 sql UTC 时间戳转换为 Instant

问题描述 投票:0回答:1

我正在研究一个需要

compare date and time which are stored in a database with the current time in Java
的解决方案。存储的日期和时间采用 UTC 格式,它是一个 java.sql.Timestamp。我使用 java.time.Instant 进行比较,但我需要将存储的时间戳转换为即时。我使用了 Timestamp.toInstant() 但它返回了错误的时间。代码请参考下面的例子。

Timestamp timeStamp = 2023-08-08 07:52:09.877 // 这是 UTC 时间。

timeStamp.toInstant = 2023-08-08T02:22:09.877Z //转换后的UTC值。

尝试寻找一种方法可以将我们输入的时间的时区传递给toInstant方法,但找不到。

有人知道在 Instant 对象中获取相同 UTC 时间的解决方案吗?

问候。

java date java-11
1个回答
1
投票

Timestamp#toInstant
确实是UTC

将存储的时间戳转换为即时

调用

java.sql.Timestamp#toInstant
确实会给你一个日期和时间,与 UTC 的偏移量为零小时-分钟-秒。这两个类都在内部保存自 UTC 1970 年第一个时刻的纪元参考(1970-01-01T00:00Z)以来的计数。

Instant instant = myJavaSqlTimestamp.toInstant() ;

避免遗留日期时间类

Timestamp
类是存在严重缺陷的遗留日期时间类之一。这些几年前就被 JSR 310 中定义的现代 java.time 类所取代。

切勿使用

Timestamp
Calendar
Date
SimpleDateFormat
等。仅在 JDBC 4.2+ 中使用 java.time 类。

带区域/偏移

如果您的 Microsoft SQL Server 数据库中的列属于类型

datetimeoffset
,则在 JDBC 中检索匹配的类型:
OffsetDateTime

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

写作:

String input = "2023-08-08 07:52:09.877Z" ;  // `Z` on the end indicates an offset of zero hours-minutes-seconds from UTC. Pronounced "Zulu". 
Instant instant = Instant.parse( input ) ;  // Represents a moment as seen with an offset of zero from UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;  // Represents a moment as seen with a particular offset from UTC. In this case the offset is zero.
myPreparedStatement.setObject( … , odt ) ;

无区域/偏移

我怀疑您的问题是由于列上的数据类型不正确造成的。您忽略了指示数据类型,所以我只能猜测。但我猜该类型是旧版 Microsoft SQL Server 类型

datetime
或其现代替代品
datetime2

这两种

datetime
/
datetime2
类型都表示带有当天时间的日期,但缺少时区上下文或与 UTC 的偏移量。如果没有这个上下文,这样的值“不”代表一个时刻,“不”是时间线上的一个特定点。因此与 UTC 中的值进行比较是没有意义的 这些 datetime/

datetime2

类型的匹配 JDBC 类型是

LocalDateTime
— 一个表示带有日期时间但没有区域/偏移量的日期的类。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
写作:

myPreparedStatement.setObject( … , ldt ) ;
如果您正在跟踪某个时刻(时间轴上的特定点),

不要
使用这些 
datetime

/datetime2 类型,也不要使用 LocalDateTime

。这就像存储一笔钱而不注意货币一样。
如果您确实使用了这些 
datetime
/
datetime2

类型来尝试存储时刻,那么您现在手上一团糟。您需要使用

datetimeoffset
 来代替。要迁移数据,如果您“确定”知道存储值的预期偏移量,则可以分配一个偏移量,但您最终当然会猜测,因为您无法知道每行插入/更新的上下文。

© www.soinside.com 2019 - 2024. All rights reserved.