Java SE 8 TemporalAccessor.from与Java.time.Instant对象一起使用时出现问题
Java SE 8 TemporalAccessor.from与Java.time.Instant对象一起使用时出现问题,java,java-8,java-time,Java,Java 8,Java Time,java.time有一个类,它封装了时间线上的位置(或“时刻”)。虽然我知道这是一个秒/纳秒值,因此与时区或时间偏移量没有直接关系,但它的toString返回一个格式化为UTC日期/时间的日期和时间,例如2014-05-13T20:05:08.556Z。另外,anistant.atZone(zone)和anistant.atOffset(offset)都会生成一个值,该值与将即时视为具有隐含的UTC时区/“零”偏移一致 因此,我原以为: ZoneOffset.from(instant)生成“零
java.time
有一个类,它封装了时间线上的位置(或“时刻”)。虽然我知道这是一个秒/纳秒值,因此与时区或时间偏移量没有直接关系,但它的toString
返回一个格式化为UTC日期/时间的日期和时间,例如2014-05-13T20:05:08.556Z。另外,anistant.atZone(zone)
和anistant.atOffset(offset)
都会生成一个值,该值与将即时
视为具有隐含的UTC时区/“零”偏移一致
因此,我原以为:
生成“零”ZoneOffset.from(instant)
ZoneOffset
生成偏移量为“零”的日期/时间OffsetDateTime.from(一个实例)
(可能)生成UTCZoneId.from(暂时)
ZoneId
(可能)生成一个带有UTCZonedDateTime。从(一个实例)
ZoneId的
ZonedDateTime
ZoneOffset.from(anistant)
会因DateTimeException
而失败,我想正是由于这个原因,OffsetDateTime.from(anistant)
也会失败,其他两个也一样
这是预期的行为吗?即时
类没有时区。它像在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]
ZoneOffset.from
和OffsetDateTime.from
的签名接受任何时间对象,但对于某些类型,它们失败java.time
似乎没有针对具有时区或偏移量的时间段的接口。这样的接口可以声明getOffset
和getZone
。由于我们没有这样的接口,这些方法在多个地方分别声明
如果您有一个zoneDateTime
,您可以调用它的getOffset
。如果您有一个OffsetDateTime
,您也可以调用它的offset-但是这是两个不同的getOffset
方法,因为这两个类不是从公共接口获取该方法的。这意味着,如果你有一个时态的
对象,它可能是其中的一个,那么你必须测试它是否是这两个对象的实例,以获得偏移量
OffsetDateTime.from通过为您这样做简化了过程,但由于它也不能依赖于公共接口,因此它必须接受任何临时的对象,并为那些没有偏移的对象抛出异常。简短回答:
JSR-310-designers不希望人们通过静态from()方法在机器时间和人工时间之间进行转换,这些方法的类型包括ZoneId
、ZoneOffset
、OffsetDateTime
、zoneDateTime
等。如果仔细研究javadoc,这是明确指定的。而是使用:
OffsetDateTime#toInstant():Instant
ZonedDateTime#toInstant():Instant
Instant#atOffset(ZoneOffset):OffsetDateTime
Instant#atZone(ZoneId):ZonedDateTime
静态from()方法的问题在于,否则人们可以在即时
和例如LocalDateTime
之间进行转换,而不考虑时区
长答案:
<>是否考虑“代码>即时/代码>作为计数器或字段元组,JSR-310团队给出的答案是所谓的机器时间和人类时间之间的严格分离。事实上,他们打算有一个严格的分离-看他们的。最后,他们希望即时仅被解释为机器时间计数器。因此,他们故意设计了一个不能要求年、小时等字段的Instant
但事实上,JSR-310团队根本不一致。他们已经将方法Instant.toString()
实现为一个字段元组视图,包括年、、小时、。。。和偏移符号Z(表示UTC时区)(脚注:在JSR-310之外,在此类机器时间上有基于字段的外观是很常见的-例如,请参见Wikipedia或其他网站上的关于)。规范负责人S.Colebourne曾在一篇评论中说:
“如果我们真的很强硬,那么瞬间的转瞬即逝就是从1970-01-01Z开始的秒数。我们选择不这样做,并输出一个更友好的toString来帮助开发人员,但这并没有改变一个基本事实,即瞬间只是秒数,如果没有某种时区,就无法转换为年/月/日。”
人们可能喜欢或不喜欢这个设计决策(像我一样),但结果是你不能要求年、小时和偏移量的即时。另请参阅支持字段的文档:
NANO_OF_SECOND
MICRO_OF_SECOND
MILLI_OF_SECOND
INSTANT_SECONDS
有趣的是,这里缺少了什么,最重要的是缺少了一个与区域相关的字段。作为一个原因,我们经常听到这样的说法,像Instant
或java.util.Date
这样的对象没有时区。在我看来,这是一个过于简单的观点。虽然这些对象在内部没有时区状态,这是事实(也不需要有这样的内在价值),这些对象必须与UTC时区相关,因为这是每个时区偏移计算和转换为本地类型的基础。因此正确的答案应该是:Instant
是一个机器计数器,以UTC时区计算UNIX历元以来的秒数和纳秒数(根据规范)。最后一部分——与UTC区域的关系——JSR-310-team没有明确规定,但他们无法否认。设计师希望从即时
取消时区方面,因为它看起来与人类时间相关。但是,他们不能完全取消它,因为这是任何内部偏移计算的基本部分.那么你的观察
LocalDateTime.ofInstant(myDate.toInstant(), ZoneId.systemDefault())