当前位置: 首页 > 知识库问答 >
问题:

Java SE 8临时加速器。与java一起使用时的问题。时间即时对象

娄德运
2023-03-14

<代码>java。时间有一个Instant类,它封装了时间线上的位置(或“时刻”)。虽然我知道这是一个秒/纳秒的值,因此与时区或时间偏移量没有直接关系,但它的toString返回的日期和时间格式为UTC日期/时间,例如2014-05-13T20:05:08.556Z。还有一个实例。atZone(zone)和持续时间。atOffset(offset)都会生成一个值,该值与将瞬间视为具有隐含的UTC时区/“零”偏移一致。

因此,我预计:

  • ZoneOffset.from(anInstant)生成一个'零'ZoneOffset
  • OffsetDateTime.from(anInstant)生成具有'零'偏移量的日期/时间
  • ZoneId.from(anInstant)(可能)生成一个UTCZoneId
  • ZonedDateTime.from(anInstant)(可能)生成带有UTCZoneId
  • ZonedDateTime

我读到的ZonedDateTime.from的留档似乎认可了这一点。

事实上,分区偏移。from(anInstant)失败,出现日期时间异常(DateTimeException),我想正是由于这个原因,偏移了日期时间(OffsetDateTime)。from(anInstant)也会失败,其他两个也会失败。

这是预期的行为吗?

共有3个答案

潘嘉佑
2023-03-14

仅仅是一个w.r.t转换的例子,我相信有些人会得到以下例外

(java.time.DateTimeException:无法获取LocalDateTime从时间访问: 2014-10-24T18:22:09.800Z类型java.time.即时)

如果他们尝试-

LocalDateTime localDateTime=LocalDateTime.from(new Date(). toInstant());

要解决此问题,请传入区域-

LocalDateTime LocalDateTime=LocalDateTime。自(新日期())。toInstant()。atZone(UTC所在地区)

万俟浩
2023-03-14

Instant类没有时区。它像在UTC区域中一样打印,因为它必须在某个区域中打印(您不希望它以记号打印,是吗?),但这不是时区-如以下示例所示:

Instant instant=Instant.now();
System.out.println(instant);//prints 2014-05-14T06:18:48.649Z
System.out.println(instant.atZone(ZoneId.of("UTC")));//prints 2014-05-14T06:18:48.649Z[UTC]

分区偏移的签名。从和偏移日期时间。从接受任何时间对象,但对于某些类型,它们会失败<代码>java。对于具有时区或偏移量的时间,时间似乎没有接口。这样的接口可以声明getOffset和getZone。由于我们没有这样的接口,这些方法在多个地方分别声明

如果您有一个ZonedDateTime,您可以将其称为getOffset。如果您有一个OffsetDateTime,您也可以调用它的偏移量-但这是两种不同的getOffset方法,因为这两个类不会从公共接口获取该方法。这意味着如果您有一个Temporal对象,它可能是其中之一,您必须测试它是否是instanceof以获取偏移量。

<代码>OffsetDateTime。from通过为您这样做简化了过程,但由于它也不能依赖于公共接口,因此它必须接受任何时间对象,并为那些没有偏移量的对象抛出异常。

董霖
2023-03-14

简短的回答:

JSR-310设计者不希望人们通过ZoneIdZoneOffsetOffsetDateTimeZonedDateTime等类型的静态from()方法在机器时间和人类时间之间进行转换。如果您仔细研究javadoc,这是明确指定的。相反,请使用:

OffsetDateTime#toInstant():Instant
ZonedDateTime#toInstant():Instant
Instant#atOffset(ZoneOffset):OffsetDateTime
Instant#atZone(ZoneId):ZonedDateTime

静态from()方法的问题是,否则人们可以在Instant和例如LocalDateTime之间进行转换,而无需考虑时区。

详细回答:

无论是将瞬间看作计数器还是字段元组,JSR-310-team给出的答案都是严格区分所谓的机器时间和人工时间。事实上,他们打算严格分离——参见他们的指导方针。因此,最后,他们希望仅将“即时”解释为机器时间计数器。因此,他们故意设计了一种不能对年份、小时等字段要求即时的设计。

但事实上,JSR-310团队根本不一致。他们立即实现了这个方法。toString()作为字段元组视图,包括年份。。。,小时和偏移符号Z(表示UTC时区)(脚注:在JSR-310之外,在此类机器时间上进行基于字段的查看是很常见的-例如,请参见维基百科或其他有关TAI和UTC的网站)。有一次,规范负责人S.Colebourne在对一个Three Ten github问题的评论中说:

“如果我们真的很强硬,那么一个瞬间的toString就是从1970-01-01Z开始的秒数。我们选择不这样做,并输出一个更友好的toString来帮助开发人员,但这并没有改变一个基本事实,即一个瞬间只是秒数,不能转换为没有某种时区的年/月/日。”

人们可以喜欢或不喜欢这个设计决策(像我一样),但结果是您不能向Instant询问年份、...、小时、...和偏移量。另请参阅支持字段的留档:

NANO_OF_SECOND 
MICRO_OF_SECOND 
MILLI_OF_SECOND 
INSTANT_SECONDS 

有趣的是,这里缺少了什么,最重要的是缺少了一个与区域相关的字段。作为一个原因,我们经常听到这样一种说法,即像Instant或java这样的对象。util。日期没有时区。在我看来,这是一个过于简单的观点。虽然这些对象确实在内部没有时区状态(也不需要有这样的内部值),但这些对象必须与UTC时区相关,因为这是每个时区偏移计算和转换为本地类型的基础。因此,正确的答案应该是:即时计数器是一个机器计数器,它以UTC时区(按照规范)计算自UNIX纪元以来的秒数和纳秒数。最后一部分——与UTC区域的关系——JSR-310-team没有明确规定,但他们无法否认这一点。设计师们想取消即时时区,因为它看起来与人类时间相关。然而,他们不能完全废除它,因为这是任何内部偏移计算的基本部分。那么你对

"此外,Instant.atZone(zone)Instant.atOffset(偏移量)都生成一个值,该值与将Instant视为具有隐含的UTC时区/'零'偏移量一致。"

是对的。

虽然ZoneOffset.from(anInstant)可能会产生ZoneOffset。UTC可能非常直观,但它会引发异常,因为它的from()方法搜索不存在的OFFSET_SECONDS字段。JSR-310的设计者出于同样的原因决定在规范中这样做,即让人们认为Instant与UTC时区没有正式关系,即“没有时区”(但在内部,他们必须在所有内部计算中接受这一基本事实!)。

出于同样的原因,OffsetDateTime。从(恒定)和分区ID。from(anInstant)也会失败。

关于ZonedDateTime.from(anInstant)我们阅读:

转换将首先从临时对象获取ZoneId,必要时返回ZoneOffset。然后尝试获取Instant,必要时返回LocalDateTime。结果将是ZoneId或ZoneOffset与Instant或LocalDateTime的组合

因此,由于相同的原因,此转换将再次失败,因为ZoneIdZoneOffset都无法从Instant获得。异常消息如下:

“无法从java.time.Instant类型的临时Accessor:1970-01-01T00:00:00Z获取ZoneId”

最后,我们看到,所有静态from()方法都无法在人工时间和机器时间之间进行转换,即使这看起来很直观。在某些情况下,比如说,LocalDate和Instant之间的转换是有问题的。这种行为是特定的,但我预测您的问题不是最后一个此类问题,许多用户将继续感到困惑。

我认为真正的设计问题是:

a)人类时间和机器时间之间不应该有明显的分离。像Instant这样的时间对象应该更好地表现为两者。量子力学中的一个类比:您可以将电子视为粒子和波。

b)所有静态from()-方法都太公开了。在我看来,Ihat太容易访问了,最好从公共API中删除,或者使用比TemporalAccess更具体的参数。这些方法的弱点是人们可能会忘记在这种转换中考虑相关的时区,因为它们以本地类型开始查询。考虑例如:LocalDate.from(anInstant)(在哪个时区???)。但是,如果您直接向Instant询问其日期,例如instant.getDate(),我个人会认为UTC-timezone中的日期是有效的答案,因为这里的查询是从UTC的角度开始的。

c) 总之:我与JSR-310-team完全分享了一个好主意,即避免在本地类型和全局类型之间进行转换,如不指定时区的情况下进行即时转换。我只是在API设计方面有所不同,以防止用户进行这种无时区转换。我的首选方法是限制from()-方法,而不是说全局类型不应该与日历日期、墙时间或UTC时区偏移量等人工时间格式有任何关系。

无论如何,由于保留了向后兼容性,以及所有想要使用新java的人,这种(不合理的)机器时间和人工时间分离的设计现在已经一成不变。时间API必须适应它。

很抱歉回答得太长,但要解释所选择的JSR-310设计是相当困难的。

 类似资料:
  • 它给出了准备好的SQL语句字符串: 无论我指定的时区如何,返回的时间戳都是相同的时间戳。它忽略了我指定的带有时区的Calendar对象。这是怎么回事,我做错了什么?

  • 从我的数据库我检索值为: 我想要上面的: 我试着用当前的时间戳跟踪 实际时间戳:2018年6月22日星期五16:07:35 更新了,我不想更新,有没有办法保持原样?

  • 本文向大家介绍MySQL使用临时表加速查询的方法,包括了MySQL使用临时表加速查询的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了MySQL使用临时表加速查询的方法。分享给大家供大家参考。具体分析如下: 使用MySQL临时表,有时是可以加速查询的,下面就为您详细介绍使用MySQL临时表加速查询的方法。 把表的一个子集进行排序并创建MySQL临时表,有时能加速查询。它有助于避免多重排

  • 我需要访问现有的MySQL数据库,该数据库使用列存储时间戳: 现在我更喜欢使用或实例而不是整数,所以我试图让Hibernate直接转换值。不幸的是,Hibernate不会识别这样注释的列: 或者像这样: 这确实会在将来返回类似。如何使Hibernate convert列正确转换,从而不必在getter和setter中转换它们?

  • 问题内容: 假设我们使用Unix timestamp列将事件记录在Sqlite数据库中: 并且我们想要快速查找日期时间范围,例如: 与此类似,给人这是不好的,所以一个显而易见的解决方案是 创建一个索引 用。 这样就解决了问题,但是要为已经增加的序列/已经排序的列维护索引是一个很 糟糕的解决方案,我们可以 直接在O(log n)中 使用 B树搜索 来为其建立索引。在内部,这将是索引: 这浪费了数据库

  • 我试图将Hibernate与我的spring应用程序上下文联系起来。我正在成功地连接SessionFactory,但当我尝试调用getCurrentSession时,我看到以下错误: 我正在配置数据源会话工厂和事务管理器。我还指定了事务处理将是注释驱动的 下面是我的上下文XML: null 下面是我发现错误的类: 当这被称为sessionFactory时不是null,而是带有上述错误的错误。如果我