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

How to get ZoneId values from given ZoneOffset in Java?

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

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

如果您想要当前具有偏移量的区域,例如从 UTC +02:00 开始,您可以尝试通过 getAvailableZoneIds()getRules()getOffset(Instant instant) 过滤来收集区域名称(不是直接 ZoneId 对象)。后者需要一个参数来定义该方法所基于的时间。
在这个例子中是nowInstant.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);
}

今天,2021 年 8 月 25 日,输出是

Africa/Blantyre
Africa/Bujumbura
Africa/Cairo
Africa/Ceuta
Africa/Gaborone
Africa/Harare
Africa/Johannesburg
Africa/Khartoum
Africa/Kigali
Africa/Lubumbashi
Africa/Lusaka
Africa/Maputo
Africa/Maseru
Africa/Mbabane
Africa/Tripoli
Africa/Windhoek
Antarctica/Troll
Arctic/Longyearbyen
Atlantic/Jan_Mayen
CET
Egypt
Etc/GMT-2
Europe/Amsterdam
Europe/Andorra
Europe/Belgrade
Europe/Berlin
Europe/Bratislava
Europe/Brussels
Europe/Budapest
Europe/Busingen
Europe/Copenhagen
Europe/Gibraltar
Europe/Kaliningrad
Europe/Ljubljana
Europe/Luxembourg
Europe/Madrid
Europe/Malta
Europe/Monaco
Europe/Oslo
Europe/Paris
Europe/Podgorica
Europe/Prague
Europe/Rome
Europe/San_Marino
Europe/Sarajevo
Europe/Skopje
Europe/Stockholm
Europe/Tirane
Europe/Vaduz
Europe/Vatican
Europe/Vienna
Europe/Warsaw
Europe/Zagreb
Europe/Zurich
Libya
MET
Poland

编辑: 考虑到@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());
}

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