英文:
OffsetDateTime object's LocalDateTime and ZoneOffset values differ when using differing instantiation methods
问题
使用以下方式创建 OffsetDateTime 对象:
- 使用
ofInstant(instant, zoneid)
方法,或者 - 使用流畅接口(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
- ofInstant(instant, zoneid) or via
- 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论