【问题标题】:java.time.DateTimeException: Invalid ID for region-based ZoneId, invalid format: Javajava.time.DateTimeException:基于区域的 ZoneId 的 ID 无效,格式无效:Java
【发布时间】:2019-05-30 14:41:35
【问题描述】:

我想按城市 UTC 和 GMT 时间不带下划线。首先,我正在写信以获取区域 ID:

 List<String> utc = new ArrayList<>(ZoneId.getAvailableZoneIds());
 List<String> gmt = new ArrayList<>(ZoneId.getAvailableZoneIds());

但我有下划线,我要改成空白:

  List<String> newList_utc = new ArrayList<>();
  List<String> newList_gmt = new ArrayList<>();

    for (String anUtc : utc) {
        if (anUtc.contains("_")) {
            newList_utc.add(anUtc.replace("_", " "));
        } else {
            newList_utc.add(anUtc);
        }
    }

    for (String aGmt : gmt) {
        if (aGmt.contains("_")) {
            newList_gmt.add(aGmt.replace("_", " "));
        } else {
            newList_gmt.add(aGmt);
        }
    }

拆分后我有特定的城市,例如-El Salvador。拆分和更改之前的格式是America/El_Salvador

我正在使用以下代码输出带有偏移的时区:

newList_utc.stream().filter(it -> it.contains("El Salvador")).collect(Collectors.toList());
newList_utc.stream().filter(it -> it.contains("America/El Salvador")).map(Class::getOffset).collect(Collectors.toList());

...
...

private static String getOffset(String zone) {
       ZonedDateTime zdt = LDT.atZone(ZoneId.of(zone));
       return zdt.getOffset().getId().replace("Z", "+00:00");
}

最后,我得到了错误:

java.time.DateTimeException: Invalid ID for region-based ZoneId, invalid format: America/El Salvador
    at java.time.ZoneRegion.checkName(ZoneRegion.java:151)
    at java.time.ZoneRegion.ofId(ZoneRegion.java:116)
    at java.time.ZoneId.of(ZoneId.java:411)
    at java.time.ZoneId.of(ZoneId.java:359)
    at project.Bot.getOffset(Bot.java:5822)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at project.Bot.getOutputZone(Bot.java:6070)
    at project.Bot.getTimeZone(Bot.java:6041)
    at project.Bot.onUpdateReceived(Bot.java:399)

在调试过程中,这是因为 getOffset()method 在这一行 ZonedDateTime zdt = LDT.atZone(ZoneId.of(zone)); 上我设置了 America/El Salvador。如果我写America/El_Salvador,那么我没有这个问题。

但是为什么我不能用空格代替下划线呢?

【问题讨论】:

  • ZoneID 由an external database 定义。如果用下划线定义,则需要下划线。
  • @Compass,哦,有道理。谢谢你。我想如果我改变它,我会得到另一个结果。

标签: java time timezone


【解决方案1】:

时区 ID 实际上不是由 Java 标准定义的,而是在 Java 之外的一个称为 tz database 的数据集中定义的,这是一个公共域时区标准,旨在实现应用程序和编程语言之间的互操作性。

时区名称背后的规则是:

时区具有“区域/位置”形式的唯一名称,例如“美国/纽约”。还选择使用英文名称或等效名称,并省略标点符号和常用后缀。 下划线字符用于代替空格。连字符用于出现在位置名称中的位置。区域和位置名称的最大长度为 14 个字符。

因此,根据格式需要下划线,因此使用带空格而不是下划线的时区将不起作用,不是因为 Java 不支持它,而是因为它没有匹配的 tz 条目。

如果您想从 tz 转换为干净的显示,可以将下划线替换为空格,反之亦然,将干净的显示转换回时区 id。

Ref: relatively current tz codes

【讨论】:

  • 是的,为了解决这个问题,我在使用 getOffset() 方法之前将空格替换为下划线。
猜你喜欢
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
  • 1970-01-01
  • 2022-07-11
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
相关资源
最近更新 更多