首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用OffsetDateTime连接器/J直接检索UTC OffsetDateTime?

如何使用OffsetDateTime连接器/J直接检索UTC OffsetDateTime?
EN

Stack Overflow用户
提问于 2022-01-14 22:44:57
回答 1查看 398关注 0票数 3

我喜欢任何时候都在世界协调时,除了当他们显示。在最后一刻,它们可以转换为本地时间,仅供显示。

我以前一直将UNIX时间戳存储在MySQL中的整数字段中(自纪元以来的秒数)。我正在处理其他人的数据库模式,我无法更改它,它使用一个DATETIME,它存储原始时间,甚至没有偏移量。

如何在UTC中检索和发送带有数据库的时间对象,以便数据库完全不进行任何转换?

虽然是为PostgreSQL编写的,但我还是尝试遵循Bourque对以下问题的出色回答。我在任何地方都使用Instant,除非他展示了我在与JDBC交互时使用OffsetDateTime,因为它是JDBC4.2保证支持的唯一现代时刻类。

我使用的是MySQL连接器/J驱动程序版本8.0.27,并与&preserveInstants=false&connectionTimeZone=UTC连接。

让我们看看数据库中存储为"2022-01-14 11:00:00“的DATETIME,它被理解为UTC。

代码语言:javascript
复制
resultSet.getString(columnName); // "2022-01-14 11:00:00"
resultSet.getObject(columnName, OffsetDateTime.class).toString() // "2022-01-14T11:00-04:00"
resultSet.getObject(columnName, OffsetDateTime.class).toInstant().toString() // "2022-01-14T15:00:00Z"

当它创建OffsetDateTime时,它将分配"-04:00“的系统或服务器(同一台机器)偏移量,并将一切搞砸。我想我的&preserveInstants=false&connectionTimeZone=UTC连接选项应该已经停止了。

我知道我可以在使用.withOffsetSameLocal(ZoneOffset.UTC).toInstant()之后立即将偏移量设置为"+00:00“,但是如何避免这样做,并让它直接创建一个在UTC中的OffsetDateTime

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-15 16:56:58

TIMESTAMP WITHOUT TIME ZONE

您已经指出了核心问题:表的作者将列定义为MySQL DATETIME类型。该类型只表示一天中有时间的日期,但缺少时区或偏移的上下文。MySQL DATETIME列类似于TIMESTAMP WITHOUT TIME ZONE的标准类型。

java.time.LocalDateTime

因此,在从该DATETIME列检索值时,您使用了错误的Java类。与其使用OffsetDateTime,不如使用LocalDateTime。与DATETIME (和TIMESTAMP WITHOUT TIME ZONE)一样,Java类型的LocalDateTime表示一天的时间,但没有区域或偏移。

代码语言:javascript
复制
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

决定时刻

您可以指定一个偏移量或时区来精确地确定时间线上的某个时刻和一个点。

代码语言:javascript
复制
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ; 

或者:

代码语言:javascript
复制
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

你说过:

它指定系统或服务器(同一台机器)偏移量"-04:00“,并把一切都搞砸了。

遍历过程中的某些部分试图帮助您理解代码的意图,即只从日期和时间开始,而值以指定的偏移量结束。您的JDBC驱动程序很可能是分配偏移量的部分。由于没有使用MySQL DATETIME存储偏移量,因此需要分配一些偏移量以生成所请求的OffsetDateTime对象。

如上面所示,更好的方法是在使用缺少偏移量的数据库列时,不请求OffsetDateTime对象

你问:

如何检索和发送具有UTC数据库的时间对象,这样数据库就完全不进行任何转换了?

您不能像在UTC中看到的那样,用缺少从UTC偏移的概念的数据库列来交换时间。

如果要表示SQL数据库中的时刻,则必须使用适当的数据类型,这是一种类似于SQL标准类型TIMESTAMP WITH TIME ZONE的类型。

在用数据库列交换日期-时间-偏移值时所要求的只是日期-时间-时间--就像要求在一个数字栏中存储日元的价格一样。你可以假装这样的记录值代表了日元的价格,但你不知道。有人也可以在那里储存欧元或比索的价格。

因为对于当前的工作情况,您似乎陷入了困境,所以您可以假装您的TIMESTAMP WITHOUT TIME ZONE列存储UTC值。本质上,这就是我上面的代码示例所做的。

若要在编写值时假装,请调整到UTC,然后提取LocalDateTime

代码语言:javascript
复制
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
OffsetDateTime odt = zdt.withOffsetSameInstant( ZoneOffset.UTC ) ; 
LocalDateTime ldt = odt.toLocalDateTime() ;
myPreparedStatement.setObject( … , ldt ) ;

这种装模作样的做法充满了危险,而且不负责任。数据库是在追踪虚构的东西,而不是真相。请务必将此黑客记录在案,因为任何刚进入系统的程序员都会被彻底搞混。

顺便说一句,注意类型名称TIMESTAMP WITH TIME ZONETIMESTAMP WITHOUT TIME ZONE是用词不当的。据我所知,从我在草案中看到的情况来看,SQL标准实际上只意味着偏移,而不是真正的时区。这就是为什么OffsetDateTime是JDBC中唯一映射到TIMESTAMP WITH TIME ZONE匹配的Java类的原因。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70717342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档