java.time.ZoneId是否有原因不包括ZoneIds的枚举?

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等等).由于偏移量接受小时,分钟和秒,因此有数百种可能的偏移量,并且为每个偏移量创建枚举将是不切实际的.

再一次,人们可以争辩说"嘿,只为名字创造枚举,忘记抵消".但是上面已经讨论了不创建枚举名称的可能原因.


Jod*_*hen 6

JDK中的时区集可以完全替换.因此,不可能enum为区域定义.

此外,时区标识符相对不稳定.它们被重命名,合并并且通常会更改.(包括我在内的各种人都试图在IANA数据库中获得更多稳定性,但数据库维护者并不同意.)

将考虑ZoneIdsThreeTen-Extra提供常量中创建类的pull请求.


hol*_*ava 5

如果您看到ZoneId#getAvailableZoneIds方法的说明,那么您知道为什么吗?

该集合包括所有可用的基于区域的ID的字符串形式。基于偏移量的区域ID 不包含在返回的集中。可以传递ID of(String)来创建ZoneId。

区域ID的集合随着时间的推移而增加,尽管在典型的应用中ID的集合是固定的。对此方法的每次调用都是线程安全的。