OffsetDateTime对象的LocalDateTime和ZoneOffset值在使用不同的实例化方法时不同。

huangapple go评论75阅读模式
英文:

OffsetDateTime object's LocalDateTime and ZoneOffset values differ when using differing instantiation methods

问题

使用以下方式创建 OffsetDateTime 对象:

  1. 使用 ofInstant(instant, zoneid) 方法,或者
  2. 使用流畅接口(fluent interface)

如果通过流畅接口进行实例化,且跨越了夏令时边界,可能会导致对象不相等(通过使用 compareTo 断言或比较 ZoneOffset 和 LocalDateTime 字段)。考虑以下示例:

OffsetDateTime inAMonth = OffsetDateTime.now().plusMonths(1);
OffsetDateTime inAMonth2 = OffsetDateTime.ofInstant(inAMonth.toInstant(), ZoneId.systemDefault());

在中欧(ZoneId 'Europe/Berlin')的中旬十月,由于 plusMonths() 重新使用了初始调用(now())的偏移量(offset),这将产生两个不相等的对象。

有人知道为什么不重新计算偏移量吗?

在单元测试中,我遇到了这个问题,我能想到的唯一解决方法是:a) 不使用流畅接口,或者 b) 在使用流畅接口时避免跨夏令时跳跃。不幸的是,除了 OffsetDateTime,我没有其他选择。

英文:

Creating OffsetDateTime objects using

  1. ofInstant(instant, zoneid) or via
  2. fluent interface

can lead to non-equal objects (by using compareTo assertions or comparing the ZoneOffset and LocalDateTime fields) if the instantiation via the fluent interface crosses a Daylight Saving Time boundary. Consider the following example:

OffsetDateTime inAMonth = OffsetDateTime.now().plusMonths(1);
OffsetDateTime inAMonth2 = OffsetDateTime.ofInstant(inAMonth.toInstant(), ZoneId.systemDefault());

In central Europe (ZoneId 'Europe/Berlin') in mid-October this will yield two non-equal objects due to plusMonths() re-using the offset of the initial call (now()).

Does anyone know why the offset is not recalculated?

I ran into this issue during a unit test and the only workarounds I could come up with were a) not using the fluent interface or b) refrain from using cross-DST jumps while using fluent interface. Using something other than OffsetDateTime is not an option, unfortunately.

答案1

得分: 1

因为OffsetDateTime.now()返回的OffsetDateTime值并没有与任何特定的时区关联,只有一个偏移量。偏移量是根据“系统默认时区中的当前偏移量”来确定的,但在此之后就不再与系统默认时区相关联。

如果您想要与时区关联的值,可以改用ZonedDateTime.now()。您可以将ZonedDateTime.now().plusMonths(1)的结果转换为OffsetDateTime

OffsetDateTime 一个月后 = ZonedDateTime.now().plusMonths(1).toOffsetDateTime();
英文:

> Does anyone know why the offset is not recalculated?

Because the OffsetDateTime value returned by OffsetDateTime.now() isn't associated with any particular time zone, only an offset. The offset is determined as "the current offset in the system default time zone", but after that there's no association with the system default time zone.

If you want a value that is associated with a time zone, use ZonedDateTime.now() instead. You can convert the result of ZonedDateTime.now().plusMonths(1) into an OffsetDateTime afterwards:

OffsetDateTime inAMonth = ZonedDateTime.now().plusMonths(1).toOffsetDateTime();

答案2

得分: 0

OffsetDateTime.plusMonth永远不会更改偏移量,因为它是一个OffsetDateTime——一个带有_恒定偏移量_的日期和时间。如果您想要更改偏移量,请使用ZonedDateTime,因为只有_区域的_偏移量可以更改。

然而,在使用时区和时刻创建OffsetDateTime时,它显然需要获取指定时刻的指定时区的偏移量。嗯,在_指定时刻_,夏令时转换已经发生了,所以inAMonth2具有夏令时后的偏移量。

英文:

OffsetDateTime.plusMonth never changes the offset, since it's an OffsetDateTime - a date, a time, with a constant offset. If you want the offset to change, use a ZonedDateTime, because only a zone's offset can change.

When creating an OffsetDateTime using an instant and zone, however, it obviously needs to get the offset of the specified zone at the specified instant. Well, at the specified instant, the DST transition has already happened, so inAMonth2 has the post-DST transition offset.

huangapple
  • 本文由 发表于 2020年10月19日 18:55:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/64425899.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定