java.time.DateTimeException:基于区域的 ZoneId 的 ID 无效,格式无效:Java



我想按城市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()行上的方法ZonedDateTime zdt = LDT.atZone(ZoneId.of(zone));我设置America/El Salvador。如果我写America/El_Salvador那么我没有这个问题。

但是为什么我不能使用空格而不是下划线?

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

时区名称背后的规则是:

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

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

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

参考:相对最新的tz代码

最新更新