如何从 Java 中的给定 ZoneOffset 获取 ZoneId 值?

Hen*_*nry 0 java timezone datetime timezone-offset java-time

我试图通过将区域偏移量(例如“GMT+2”)作为字符串来获取所有 zoneId。但是,我不确定是否可以使用任何 Java 8+ 库。是否可以获得具有给定区域偏移量的所有区域 id 值?

有一个名为getAvailableZoneIds()的方法,java.time但它不带偏移参数。

deH*_*aar 5

如果您想要当前与 UTC 有 +02:00 小时偏移的区域,您可以尝试ZoneId通过过滤来收集区域名称(不是直接对象)getAvailableZoneIds(),getRules()getOffset(Instant instant)。后者需要一个参数来定义该方法所基于的时间。
在这个例子中,现在是? Instant.now()

public static void main(String[] args) throws Exception {
    // define the desired offset
    ZoneOffset plusTwo = ZoneOffset.ofHours(2);
    // collect all the zones that have this offset at the moment
    List<String> zonesWithPlusTwo = 
            ZoneId.getAvailableZoneIds()
                  .stream()
                  // filter by those that currently have the given offset
                  .filter(zoneId -> ZoneId.of(zoneId)
                                          .getRules()
                                          .getOffset(Instant.now())
                                          .equals(plusTwo))
                  .sorted()
                  .collect(Collectors.toList());
    // print the collected zones
    zonesWithPlusTwo.forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

今天,即 2021 年 8 月 25 日,输出为

public static void main(String[] args) throws Exception {
    // define the desired offset
    ZoneOffset plusTwo = ZoneOffset.ofHours(2);
    // collect all the zones that have this offset at the moment
    List<String> zonesWithPlusTwo = 
            ZoneId.getAvailableZoneIds()
                  .stream()
                  // filter by those that currently have the given offset
                  .filter(zoneId -> ZoneId.of(zoneId)
                                          .getRules()
                                          .getOffset(Instant.now())
                                          .equals(plusTwo))
                  .sorted()
                  .collect(Collectors.toList());
    // print the collected zones
    zonesWithPlusTwo.forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

编辑: 考虑到@BasilBorque 的评论,这里有一个示例方法,它采用两个参数,一个偏移值和一个Instant用于计算的基础:

public static List<String> getZones(int offsetHours, Instant base) {
    // create the offset
    ZoneOffset offset = ZoneOffset.ofHours(offsetHours);
    // collect all the zones that have this offset at the moment 
    return ZoneId.getAvailableZoneIds()
                 .stream()
                 // filter by those that currently have the given offset
                 .filter(zoneId -> ZoneId.of(zoneId)
                                         .getRules()
                                         .getOffset(base)
                                         .equals(offset))
                 .sorted()
                 .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个局部变量(可能是类成员)以便将其传递给方法。这将减少对调用的数量,Instant.now()并使您能够使用Instant与调用方法不同的 s。