我正在研究一个需要
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 时间的解决方案吗?
问候。
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
来代替。要迁移数据,如果您“确定”知道存储值的预期偏移量,则可以分配一个偏移量,但您最终当然会猜测,因为您无法知道每行插入/更新的上下文。