我正在尝试将来自前端的值映射到 ZoneId 类,如下所示:
Optional.ofNullable(timeZone).map(ZoneId::of).orElse(null)
对于大多数时区,它工作正常,但是,对于某些值,Java 会抛出异常:
java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Punta_Arenas
但是,根据 IANA,它是一个有效的时区: https://www.iana.org/time-zones
Zone America/Punta_Arenas -4:43:40 - LMT 1890
我正在考虑为这样的时区使用偏移量(只是为了硬编码值),但我想应该有更方便的方法来解决这个问题。 Java 有办法处理吗?
不支持的其他时区:
我的 Java 版本:“1.8.0_121”Java(TM) SE 运行时环境(内部版本 1.8.0_121-b13)Java HotSpot(TM) 64 位服务器虚拟机(内部版本 25.121-b13,混合模式)
最佳答案
我已经用 Java 1.8.0_121 测试过,有些区域确实缺失了。
修复它的最明显方法是更新 Java 版本 - 在 Java 1.8.0_131 中,上述所有区域都可用 - 除了 3 个字母的名称(EST、HST 等),更多内容见下文。
但我知道生产环境中的更新并不像我们希望的那样容易(也不快)。在这种情况下,您可以使用 TZUpdater tool , 它可以在不改变 Java 版本的情况下更新 JDK 的时区数据。
唯一的细节是 ZoneId 不适用于 3 字母缩写(EST、HST 等)。那是因为这些名字是 ambiguous and not standard .
不过,如果您想使用它们,您可以使用自定义 ID 的映射。 ZoneId 带有内置 map :
ZoneId.of("EST", ZoneId.SHORT_IDS);
问题是 choices used in the SHORT_IDS map就像任何其他选择一样,是武断的,甚至是有争议的。如果您想为每个缩写使用不同的区域,只需创建您自己的 map :
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 字母名称的唯一异常(exception)当然是 GMT 和 UTC,但在这种情况下最好只使用 ZoneOffset.UTC 常量。
如果您不能更新您的 Java 版本,也不能运行 TZUpdater 工具,还有另一种(更难)的替代方法。
您可以扩展 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;
}
}
创建 ZoneRules 是最复杂的部分。
一种方法是获取最新的 IANA files并阅读它们。你可以看看JDK source code查看它如何从中创建 ZoneRules(尽管我不确定 JDK 中的文件是否与 IANA 文件的格式完全相同)。
无论如何,this link解释了如何阅读 IANA 的文件。那你可以看看ZoneRules javadoc了解如何将 IANA 信息映射到 Java 类。在 this answer我创建了一个非常简单的 ZoneRules,只有 2 个转换规则,因此您可以基本了解如何操作。
然后你需要注册提供者:
ZoneRulesProvider.registerProvider(new MissingZonesProvider());
现在新区域将可用:
ZoneId.of("America/Punta_Arenas");
ZoneId.of("Europe/Saratov");
... and any other you added in the MissingZonesProvider class
还有其他方法可以使用提供程序(而不是注册),check the javadoc更多细节。在同一个 javadoc 中还有更多关于如何正确实现区域规则提供程序的详细信息(我上面的版本非常简单,可能缺少一些细节,比如 provideVersions 的实现 - 它应该使用提供程序的版本作为 key ,而不是我正在做的区域 ID 等)。
当然,一旦您更新了 Java 版本,就必须丢弃该提供者(因为您不能让 2 个提供者创建具有相同 ID 的区域:如果新提供者创建一个已经存在的 ID,它会抛出异常当您尝试注册它时)。
关于Java 没有关于所有 IANA 时区的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45592878/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c