【问题标题】:How to get timezones in IANA format in java?如何在 java 中获取 IANA 格式的时区?
【发布时间】:2017-12-30 21:12:22
【问题描述】:

我的时区不是 IANA 格式,例如 PLTISTGMTNET 等。如何将这些转换为 java 中的 IANA 格式,如 Asia/KarachiAsia/KolkattaEtc/Greenwich 等。

我已经尝试使用TimeZone.getOffset() 处理偏移值,但它仍然需要 IANA 格式。

【问题讨论】:

  • 那不行。它只是缩写和显示,但不是 IANA 格式
  • 谢谢,但是我们应该在getMetaZoneID(String,Long) 中给出日期长值吗?有没有其他方法不长日期?
  • 作为@OleV.V.告诉,这些短名称是模棱两可的(例如,IST 可以是印度标准时间、爱尔兰标准时间和以色列标准时间,没有办法将 IST 映射到一个时区),所以你能做的最好的就是得到一个列表候选人(具有相同简称的 IANA 区域)。或许this可以帮到你
  • 您还可以通过Matt Johnson’s knowledgable answer here了解更多信息。

标签: java timezone timezone-offset


【解决方案1】:

我想您已经阅读了 cmets 说明这是多么(几乎)不可能以及多么脆弱。无论如何,我都敢于提出一些建设性的建议。

首先,您当然可以专门处理 GMT 和 UTC,因为它们的解释是相当安全的,您可能希望确保它们得到处理。

我认为,接下来最安全的做法有点复杂:试试ZoneId.of(yourNonIanaTimeZoneId)。这要么给你一个ZoneId,要么抛出一个异常(根据我的经验,通常是一个ZoneRulesException,但根据文档,它也可能抛出一些其他的DateTimeException)。它给了我一个ZoneId GMT,但既不是PLTIST 也不是NET。例如,它确实为EET 提供了ZoneId。如果你有一个ZoneId,你还没有走多远,因为它的 ID 就是你给的 ID。您现在可以搜索ZoneId.getAvailableZoneIds() 以查看是否可以找到具有 IANA 名称和相同区域规则的区域。您只需要知道如何识别 IANA 名称;我认为它至少应该有一个斜线。

接下来要尝试的事情,请在 ZoneId.SHORT_IDS 中查找。例如,所有PLTISTNET 都在那里。它们被翻译成亚洲/卡拉奇、亚洲/加尔各答和亚洲/埃里温。如果你想要,比如说,爱尔兰夏令时,那你就大错特错了。此外,SHORT_IDS 并不总是会给您一个 IANA 名称,但有时只是像 -05:00 这样的偏移量,这并不能真正让您获得任何帮助。对于执行此操作的三个条目,您可以对自己的转换进行硬编码,例如:

  • EST = 美国/纽约
  • HST = 太平洋/檀香山
  • MST = 美国/丹佛

同样,如果您想要澳大利亚东部标准时间(也称为 AEST 或 AET)的 EST,那您就错了。你会一遍又一遍地遇到这些模棱两可的问题。

您在评论中询问是否可以使用TimeZone.getAvailableIDs()。你可以,但它不会给你任何你从上面没有得到的东西。就我而言,我更喜欢使用现代类ZoneId,而不是过时的TimeZone。在 Java 8 中,他们将短 ID(已弃用)取出到 ZoneId.SHORT_IDS 中,并将所有其他 ID 包含在 ZoneId.getAvailableZoneIds() 中。所以TimeZone.getAvailableIDs() 的每个 ID 都在 ZoneId.getAvailableZoneIds()ZoneId.SHORT_IDS 中。

我的最后一个建议,我认为它很脏,可能无法满足您的需求:

    SimpleDateFormat sdf = new SimpleDateFormat("z");
    sdf.parse(yourNonIanaTimeZoneId);
    String ianaName = sdf.getTimeZone().getID();

我正在使用早已过时的SimpleDateFormat 类,所以我对此不太满意。对于 PLT 和 NET,它会抛出 ParseException。对于 GMT,它只是给了我 JVM 的默认时区!对于 IST,我得到了亚洲/耶路撒冷,所以如果你更喜欢亚洲/加尔各答?但是,一些以前的方法无法处理的缩写现在被转换了,例如:

  • 美国东部标准时间到美国/纽约
  • EET(东欧时间)到欧洲/布加勒斯特
  • WET(西欧时间)至非洲/卡萨布兰卡

我不保证转换的质量,尤其是最后一个在我眼里看起来很吓人。

使用风险自负! :-)

【讨论】:

  • 非常感谢您的解释 :) 我们也可以使用 TimeZone.getAvailableIDs() 吗?
  • 是的,你可以。 TimeZone.getAvailableIDs() 包含与 ZoneId.getAvailableZoneIds() 相同的 ID,此外还有 28 个三字母缩写,您可以在 ZoneId.SHORT_IDS 中找到它们作为键(这 28 个不在 ZoneId.getAvailableZoneIds() 中)。
猜你喜欢
  • 2022-01-04
  • 2020-09-24
  • 2020-05-10
  • 2016-02-06
  • 2019-01-25
  • 2015-10-16
  • 2023-04-03
  • 2021-01-20
  • 2020-05-27
相关资源
最近更新 更多