【问题标题】:How to translate between windows and IANA timezones in java如何在 java 中的 windows 和 IANA 时区之间进行转换
【发布时间】:2023-04-03 04:40:01
【问题描述】:

我需要在 IANA 时区和 Windows 时区之间进行转换,反之亦然。还有一个问题报:How to translate between Windows and IANA time zones?

它指定Noda时间库可以在.Net中使用

我们有任何可用于 Java 的库吗?或任何其他要在 java 中使用的实用程序?

【问题讨论】:

  • 已经有 code.google.com/p/java-time-zone-list 但那是几年前的事了——我怀疑它没有采用新的 CLDR 格式来适应 Windows 时区。但基本上这就是你想要的——来自 CLDR 的数据。
  • 您可能必须自己编写此代码,直接针对 CLDR 数据执行类似的逻辑。

标签: java timezone java-8


【解决方案1】:

这可能是您需要的,但我不知道它是否适用于您的所有用例:

for (String tzId : TimeZone.getAvailableIDs()) {
  TimeZone tz = TimeZone.getTimeZone(tzId);
  if (tz.getDisplayName(Locale.ENGLISH).equals("Eastern Standard Time")) {
    System.out.println("tz = " + tzId);
  }
}

【讨论】:

  • Java 的英文显示名称来自 CLDR(我认为)。它们不会将 1::1 与 Windows 时区标识符匹配。
  • 是的,Java 的英文显示名称与 Windows 时区 ID 的 1::1 不匹配。
  • @MattJohnson-Pint 在 Java 9 中,Unicode 联盟的 Common Locale Data Repository (CLDR) 成为包括时区名称在内的区域设置信息的默认值。见JEP 252: Use CLDR Locale Data by Default
【解决方案2】:

我已经在我的 Java 库 Time4J 中实现了 support for Windows zones。最新版本 v4.2 也是 interoperable with Java-8,因此很容易将所有基本 Time4J 类型转换为 java.time 等效项。例如,在构造和解析过程中可以将 Windows 区域识别为字符串:

  // conversion Windows to IANA
  WindowsZone wzn = WindowsZone.of("Eastern Standard Time");
  TZID winzone = wzn.resolveSmart(Locale.US);
  System.out.println(winzone.canonical()); // WINDOWS~America/New_York

  // usage in timezone calculation
  Timezone tz = Timezone.of(winzone);
  System.out.println(Moment.UNIX_EPOCH.toZonalTimestamp(winzone)); // 1969-12-31T19

  // usage in parsing and formatting
  ChronoFormatter<Moment> f =
    ChronoFormatter.ofMomentPattern(
      "MM/dd/uuuu hh:mm a zzzz", PatternType.CLDR, Locale.US, winzone);
  Moment pacificTime = f.parse("07/17/2015 02:45 PM Pacific Standard Time");
  System.out.println(f.format(pacificTime)); // 07/17/2015 05:45 PM Eastern Standard Time

如您所见,区域设置信息对于将“东部标准时间”等 Windows 区域映射到“美国/纽约”等 Olson/IANA 标识符是必需的。底层数据和映射信息取自 CLDR。

从 IANA 到 Windows 的反向方式可能会以这种简单的方式完成:

String iana = "America/New_York";
String winzone = "WINDOWS~" + iana;
NameStyle dummy = NameStyle.LONG_STANDARD_TIME; // does not really matter
String name = Timezone.of(winzone).getDisplayName(dummy, Locale.US);
System.out.println(name); // Eastern Standard Time

但是,这种反向转换可能不适用于所有 iana 标识符,因为与 IANA-TZDB 相比,Windows 仅支持非常简化的时区子集。我也认为在实践中几乎没有使用反向方式。用户应该默认使用 IANA 时区,并且仅在 Windows 时区是(不可避免的)要处理的输入时才使用(请参阅我的答案的第一部分)。

【讨论】:

  • 这似乎是个不错的选择。将 IANA 转换为 Windows 的问题仍然存在,因为一个 Windows 时区 ID 有多个 IANA Id。正如我在上面的回答中提到的,目前,我正在使用 windowsZones.xml 并通过维护 IANA ID 与 Windows TX ID 的映射来管理相互转换,反之亦然。
  • “如您所见,区域设置信息是映射 Windows 区域所必需的...” - 为什么会这样?例如unicode.org/repos/cldr/trunk/common/supplemental/… 中的数据是非本地化的,support.microsoft.com/en-ca/help/973627/… 也不是。
  • @MarcelStör 您提供的 unicode 链接清楚地显示了映射是如何本地化的,请注意 xml 文件中指向国家/地区 ISO 代码的区域属性。
  • @MenoHochschild 感谢您的反馈。让我意识到我的评论有点不准确,对不起。再次引用 XML……让我们以“夏威夷标准时间”为例。据我了解,根据您的领土,您会获得不同的 TZ 标识符。但是,对于偏移量计算等,是否使用“Pacific/Rarotonga”、“Pacific/Honolulu”甚至“Etc/GMT+10”都无关紧要,是吗?
  • @MarcelStör Rarotonga 和 Honolulu 实际上具有相同的 UTC-10 偏移量,但它们的偏移历史对于过去的日期不同,请参阅 Paul 网站上的 northamericaaustralasia 文件Eggert,IANA-TZDB 的维护者。
【解决方案3】:

我最终不得不自己实现。 windowsZones.xml 需要更新大量缺少的时区条目。我没有发布更新的文件,因为有许多时区在 Windows 偏移量和 IANA 偏移量之间没有完美匹配。

此外,对于一个 Windows 时区,可能会有多个 IANA 时区。因此,我必须根据其他可用信息(例如用户(地址)的地理位置等)来选择最合适的实施方式。

有了这个,我只是使用 windowsZones.xml 从 Windows 时区获取 IANA 时区,反之亦然。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2017-12-30
    • 2010-10-13
    • 2010-09-12
    • 2017-03-16
    相关资源
    最近更新 更多