我正在尝试将来自前端的值映射到ZoneId
类,如下所示:
Optional.ofNullable(timeZone).map(ZoneId::of).orElse(null)
对于大多数时区,它工作正常,但是,对于某些值,Java 会抛出异常:
java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Punta_Arenas
但是,根据https://www.iana.org/time-zones IANA,这是一个有效的时区
美洲/Punta_Arenas区 -4:43:40 - LMT 1890
我在考虑对这样的时区使用offset(只是为了硬编码值),但是我想应该有更方便的方法来解决这个问题。Java有办法解决这个问题吗?
不支持的其他时区:
我的Java版本:“1 . 8 . 0 _ 121”Java(TM)SE运行时环境(build 1 . 8 . 0 _ 121-B13)Java HotSpot(TM)64位服务器VM (build 25.121-b13,混合模式)
我用Java 1.8.0_121测试过,有些区域真的不见了。
解决这个问题最明显的方法是更新Java的版本——在Java 1.8.0_131中,除了3个字母的名称(< code>EST、< code>HST,等等)之外,上面的所有区域都是可用的,下面将详细介绍。
但我知道生产环境中的更新并不像我们希望的那样容易(也不像我们想要的那么快)。在这种情况下,您可以使用 TZUpdater 工具,该工具可以在不更改 Java 版本的情况下更新 JDK 的时区数据。
唯一的细节是< code>ZoneId不支持3个字母的缩写(< code>EST、< code>HST等)。那是因为那些名字模棱两可,不规范。
但是,如果您想使用它们,您可以使用自定义ID的映射。< code>ZoneId带有内置地图:
ZoneId.of("EST", ZoneId.SHORT_IDS);
问题是,<code>SHORT_IDS</code>映射中使用的选项与任何其他选项一样,都是任意的,甚至是有争议的。如果您想为每个缩写使用不同的区域,只需创建自己的地图:
Map<String, String> map = new HashMap<>();
map.put("EST", "America/New_York");
... put how many names you want
System.out.println(ZoneId.of("EST", map)); // creates America/New_York
当然,3 个字母名称的唯一例外是 GMT 和 UTC,但在这种情况下,最好只使用 ZoneOffset.UTC
常量。
如果您既不能更新Java版本,也不能运行TZUpdater工具,还有另一种(更难的)选择。
您可以扩展<code>java.time.zone。ZoneRulesProvider类,并创建一个可以创建缺少ID的提供程序。大概是这样的:
public class MissingZonesProvider extends ZoneRulesProvider {
private Set<String> missingIds = new HashSet<>();
public MissingZonesProvider() {
missingIds.add("America/Punta_Arenas");
missingIds.add("Europe/Saratov");
// add all others
}
@Override
protected Set<String> provideZoneIds() {
return this.missingIds;
}
@Override
protected ZoneRules provideRules(String zoneId, boolean forCaching) {
ZoneRules rules = null;
if ("America/Punta_Arenas".equals(zoneId)) {
rules = // create rules for America/Punta_Arenas
}
if ("Europe/Saratov".equals(zoneId)) {
rules = // create rules for Europe/Saratov
}
// and so on
return rules;
}
// returns a map with the ZoneRules, check javadoc for more details
@Override
protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) {
TreeMap<String, ZoneRules> map = new TreeMap<>();
ZoneRules rules = provideRules(zoneId, false);
if (rules != null) {
map.put(zoneId, rules);
}
return map;
}
}
创建Zone规则
是最复杂的部分。
一种方法是获取最新的IANA文件并阅读它们。您可以查看JDK源代码,了解它如何从中创建Zone规则
(尽管我不确定JDK中的文件是否与IANA文件的格式完全相同)。
无论如何,这个链接解释了如何读取IANA的文件。然后,您可以查看ZoneRules
javadoc,了解如何将IANA信息映射到Java类。在这个答案中,我创建了一个非常简单的<code>ZoneRules</code>,只有两个转换规则,这样您就可以了解如何执行它。
然后您需要注册提供商:
ZoneRulesProvider.registerProvider(new MissingZonesProvider());
现在,新区域将可用:
ZoneId.of("America/Punta_Arenas");
ZoneId.of("Europe/Saratov");
... and any other you added in the MissingZonesProvider class
还有其他方法可以使用提供者(而不是注册),请查看javadoc以了解更多详细信息。在同一个javadoc中,还有关于如何正确实现区域规则提供程序的更多细节(我上面的版本非常简单,可能缺少了一些细节,比如provideVersions
的实现——它应该使用提供程序的版本作为键,而不是像我这样使用区域ID等)。
当然,一旦您更新 Java 版本,就必须立即丢弃此提供程序(因为您不能有 2 个提供程序创建具有相同 ID 的区域:如果新提供程序创建的 ID 已存在,则当您尝试注册它时会引发异常)。
问题内容: 众所周知,C#提供了一个AS关键字,该关键字会自动执行一次检查,检查对象是否属于某种类型,如果是,则将其强制转换为所需的类型,否则给出null。 在上面的示例中,这里的Object obj可以是User类型或其他类型。用户将获得User类型的对象或null。这是因为C#的As关键字首先执行检查,然后在可能的情况下将对象强制转换为结果类型。 那么Java中有没有与C#的AS关键字等效的关
我有一行代码: 当我这次尝试输出时,它返回: 然后我尝试格式化这个日期时间: 这让我想起: 这是错误的。这就像是在我的时区中减去6个小时,而不是加上它。为什么会这样?
问题内容: 如何在Oracle中获取有关表,表的列和约束等的所有信息?我在用 但这只是给我列名称,空值和类型。 问题答案: 尝试dbms_metadata软件包,您可以在此处找到更多信息
我一直在玩API、XAPI和OSM的天桥。但我无法获得所需的一些信息:获取街道的所有信息节点。 这里有一个例子:http://www.openstreetmap.org/browse/way/5671291 这提供了一种称为“瓦茨街”(在纽约)的方式的信息,但它不是所有的街道,只是其中的一部分。 另一部分:http://www.openstreetmap.org/browse/way/461163
我使用JaCoCo进行代码覆盖。单元测试报告是用junit创建的,它们被正确地导入,因此单元测试信息被正确地显示出来。问题是,我得到了错误消息:没有关于每个测试覆盖率的信息。代码覆盖率显示单元测试、集成测试和整体覆盖率的值为0%。我检查了sonar项目中所有需要的信息,如二进制、src、测试等属性。 我使用的是:<br>-SonarQube 4.5.1<br>-SonarRunner 2.4<br
本文向大家介绍关于IDEA git 只有Commit没有Push的问题,包括了关于IDEA git 只有Commit没有Push的问题的使用技巧和注意事项,需要的朋友参考一下 最近发现一个问题,是关于IDEA的一些骚操作的事儿~ 具体怎么回事,一起来看看。 我们都知道使用git分布式版本控制工具,提、拉 代码都会有一个本地暂存区,也就是本地仓。 这也就说我们的Commit提交到的是我们的本地仓库,