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

2022-09-01 03:56:29

要获得它,如下所示:ZoneId

ZoneId.of("America/Sao_Paulo");

ZoneId.of(ZoneId.SHORT_IDS.get("BET"));

为什么是不存在这样的值的原因,例如:Enum

ZoneId.of(ZoneIds.AMERICA_SAO_PAULO);

这似乎不那么容易出错,并且更自动完成友好?


答案 1

我相信这是因为无论Java版本如何,所有可能的时区名称列表都可以更改。

Java 安装附带时区信息(通常在文件夹 中,或在较新版本的文件中)。但是,此信息可以在不更改 Java 版本(使用时区更新程序工具)的情况下进行更新<java-home>/lib/zijre/lib/tzdb.dat

如果更新了时区数据(但 Java 版本保持不变)并创建了新的区域 ID,则不会有等效的区域 ID,从而使 API“不完整”。时区数据的变化速度比 JDK 更新快 - 即使没有,也并不总是能够尽快在生产环境中更新 JDK 版本。Enum

我不能代表API创建者,但我认为他们决定保持原样,因为命名空间的增长速度可以比JDK更新得更快,并且保持枚举最新将是一项无休止且始终不完整的工作。

如果您真的想检查时区名称是否有效,可以执行以下操作:

if (ZoneId.getAvailableZoneIds().contains("America/Sao_Paulo")) {
    // America/Sao_Paulo is a valid ID
}

或者只是打电话并接听.ZoneId.of("zone-name")ZoneRulesException


我刚刚调用了JDK 1.8.0_131,它有600个条目。可能没有人想创建600个枚举常量。ZoneId.getAvailableZoneIds()

有人可能会争辩说,他们可以做一些类似于class的事情,它为某些语言(如英语,德语,法语等)提供了一些条目。但是,如何确定哪些时区“值得”一个常数呢?也许他们只是决定不要想太多,“嘿,算了,就使用带有区域名称的字符串”。java.util.Locale


另一个可能的原因是,该方法被设计为也接收 UTC 偏移量(如 、等)。由于偏移量接受小时、分钟和秒,因此有数百个可能的偏移量,为每个偏移量创建枚举是不切实际的。ZoneId.of()+05:00-0300+09:30:15

同样,有人可能会争辩说“嘿,只为名称创建枚举,而忘记偏移量”。但是上面已经讨论了不创建枚举名称的可能原因。


答案 2

JDK中的时区集可以完全替换。因此,无法为区域定义 。enum

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

将考虑在 ThreeTen-Extra 中创建提供常量的类的拉取请求。ZoneIds


推荐