gpt4 book ai didi

java - 如何找到对应于给定 LocalDateTime 和 ZoneId 的所有 Instants?

转载 作者:行者123 更新时间:2023-12-03 21:06:11 26 4
gpt4 key购买 nike

转换时 InstantLocalDateTime可能会发生几个不同的Instant s 转换为相同的 LocalDateTime .例如。在有夏令时的时区。
我的问题是是否可以编写一个适用于任何 ZoneId 的通用函数和 LocalDateTime并返回所有 Instant位于给定时区的 s 映射到给定 LocalDateTime :

List<Instant> localToInstants(LocalDateTime dt, ZoneId zone)

最佳答案

是的✔️
编辑
M. Prokhorov 使用 ZoneRules.getValidOffset() 的想法提供了比我原来的答案更优雅的代码。这是一个返回 Instant 列表的版本s 按要求:

public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return zone.getRules()
.getValidOffsets(dt)
.stream()
.map(dt::atOffset)
.map(OffsetDateTime::toInstant)
.collect(Collectors.toList());
}
让我们用几个重要的例子来尝试一下。马耳他将于 3 月 28 日过渡到夏令时。在凌晨 2 点,时钟向前调至 3。因此这一天不存在 2:30 时间。这意味着我们期望从以下调用中得到一个空列表:
    LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:

[]


这是 Java 打印空列表的方式。工作原理:由于时间不存在, ZoneRules.getValidOffsets()返回一个空列表。剩下的很无聊:没有偏移量可以转换为 OffsetDateTime并进一步到 Instant ,因此返回空列表。
我的另一个例子来自食岛。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 点,时钟将回到 21 点。因此 21:30 时间出现两次。让我们来看看:
    LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));

[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]


由于 UTC 偏移量从 -05:00 更改为 -06:00,因此瞬间是正确的。在这种情况下 getValidOffsets()返回了两个有效的偏移量,-05:00 和 -06:00,所以代码产生了两个 OffsetDateTime依次转换为两个不同的对象 Instant对象。
原答案
如果有人有兴趣获得合适的 ZonedDateTime对象。
public static List<Instant> localToInstants(LocalDateTime dt, ZoneId zone) {
return Stream.of(dt.atZone(zone).withEarlierOffsetAtOverlap(),
dt.atZone(zone).withLaterOffsetAtOverlap())
.filter(zdt -> zdt.toLocalDateTime().equals(dt))
.map(ZonedDateTime::toInstant)
.distinct()
.collect(Collectors.toList());
}
让我们用几个重要的例子来尝试一下。马耳他将于 3 月 28 日过渡到夏令时。在凌晨 2 点,时钟向前调至 3。因此这一天不存在 2:30 时间。这意味着我们期望从以下调用中得到一个空列表:
    LocalDateTime dt = LocalDateTime.of(2021, Month.MARCH, 28, 2, 30);
System.out.println(localToInstants(dt, ZoneId.of("Europe/Malta")));
输出确实是:

[]


这是 Java 打印空列表的方式。工作原理:由于时间不存在, dt.atZone(zone)给我们 3:30 而不是 2:30。 Java 增加了间隔的长度,对于夏季时间过渡,像往常一样一小时。调用 withEarlierOffsetAtOverlap()withLaterOffsetAtOverlap()在这种情况下没有区别(我会回到他们身上),所以我们只是得到相同的 ZonedDateTime两次。调用 filter()区别在于:我们转换 ZonedDateTime返回 LocalDateTime并发现我们没有得到相同的时间,因此我们丢弃了结果。剩下的很无聊:没有 ZonedDateTime s 转换为 Instant ,所以我们最终得到一个空列表。
我的另一个例子来自食岛。根据我的 Java 9 夏令时将在 5 月 8 日结束。在 22 点,时钟将回到 21 点。因此 21:30 时间出现两次。让我们来看看:
    LocalDateTime dt = LocalDateTime.of(2021, Month.MAY, 8, 21, 30);
System.out.println(localToInstants(dt, ZoneId.of("Pacific/Easter")));

[2021-05-09T02:30:00Z, 2021-05-09T03:30:00Z]


由于 UTC 偏移量从 -05:00 更改为 -06:00,因此瞬间是正确的。工作原理:这里是调用 withEarlierOffsetAtOverlap() 的地方和 withLaterOffsetAtOverlap()参加进来。 dt.atZone(zone)给了我们一个选项( 2021-05-08T21:30-05:00[Pacific/Easter] ,所以是较早的一个,但没有理智的人会记住这一点)。由于 Java 知道此时存在重叠, withEarlierOffsetAtOverlap()withLaterOffsetAtOverlap()给我们两种不同的可能性。由于两者都转换回正确的 LocalDateTime ,没有过滤掉任何东西。由于两者是不同的时刻, distinct()也不会过滤掉任何东西。我们最终得到两个 Instant对象。
文档链接
ZoneRules.getValidOffsets()

关于java - 如何找到对应于给定 LocalDateTime 和 ZoneId 的所有 Instants?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66606960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com