Ren*_*nan 21 java timezone java-8 java-time
得到ZoneId
它像:
ZoneId.of("America/Sao_Paulo");
Run Code Online (Sandbox Code Playgroud)
要么
ZoneId.of(ZoneId.SHORT_IDS.get("BET"));
Run Code Online (Sandbox Code Playgroud)
为什么不存在Enum
这样的价值的原因,如:
ZoneId.of(ZoneIds.AMERICA_SAO_PAULO);
Run Code Online (Sandbox Code Playgroud)
这似乎不容易出错,而且更加自动完成友好?
小智 15
我相信这是因为无论Java版本如何,所有可能的时区名称列表都可以更改.
时区信息随Java安装一起提供(通常在文件夹中<java-home>/lib/zi
,或jre/lib/tzdb.dat
在较新版本的文件中).但是可以在不更改Java版本的情况下更新此信息(使用Timezone Updater Tool).
如果时区数据已更新(但Java版本保持不变)并且创建了新的区域ID,则不会有相应的区域ID Enum
,从而使API"不完整".时区数据的变化速度比JDK更新的速度快 - 即使它没有,但我们并不总是可以在生产环境中尽快更新JDK版本.
我不能代表API创建者,但我认为他们决定让它保持原样,因为命名空间可以比JDK更新更快,并且保持最新的枚举将是无穷无尽的 - 并且总是 - 工作不完整.
如果你真的想检查时区名称是否有效,你可以这样做:
if (ZoneId.getAvailableZoneIds().contains("America/Sao_Paulo")) {
// America/Sao_Paulo is a valid ID
}
Run Code Online (Sandbox Code Playgroud)
或者只是打电话来ZoneId.of("zone-name")
抓住ZoneRulesException
.
我刚刚调用ZoneId.getAvailableZoneIds()
了JDK 1.8.0_131,它有600个条目.可能没有人想要创建600枚枚举常数.
有人可能会争辩说,他们可以做类似于java.util.Locale
课程的课程,这些课程有一些语言(如英语,德语,法语等).但是如何确定哪个时区"值得"一个常数呢?也许他们只是决定不去想那么多,"嘿,忘记它,只需使用String
区域名称".
另一个可能的原因可以是以下事实ZoneId.of()
的方法被设计为还接收UTC的偏移(如+05:00
,-0300
,+09:30:15
等等).由于偏移量接受小时,分钟和秒,因此有数百种可能的偏移量,并且为每个偏移量创建枚举将是不切实际的.
再一次,人们可以争辩说"嘿,只为名字创造枚举,忘记抵消".但是上面已经讨论了不创建枚举名称的可能原因.
JDK中的时区集可以完全替换.因此,不可能enum
为区域定义.
此外,时区标识符相对不稳定.它们被重命名,合并并且通常会更改.(包括我在内的各种人都试图在IANA数据库中获得更多稳定性,但数据库维护者并不同意.)
将考虑ZoneIds
在ThreeTen-Extra提供常量中创建类的pull请求.
如果您看到ZoneId#getAvailableZoneIds方法的说明,那么您知道为什么吗?
该集合包括所有可用的基于区域的ID的字符串形式。基于偏移量的区域ID 不包含在返回的集中。可以传递ID
of(String)
来创建ZoneId。区域ID的集合会随着时间的推移而增加,尽管在典型的应用中ID的集合是固定的。对此方法的每次调用都是线程安全的。