java - 使用 JSR 310(DateTime API)的军事时区

标签 java datetime timezone java-time

我在我的应用程序中使用 JSR 310 DateTime API*,我需要解析和格式化军事日期时间(称为 DTG 或“日期时间组”)。

我正在解析的格式如下所示(使用 DateTimeFormatter):

"ddHHmm'Z' MMM yy" // (ie. "312359Z DEC 14", for new years eve 2014)

如上所述,这种格式相当容易解析。当日期包含与“Z”(祖鲁时区,与 UTC/GMT 相同)不同的时区时,就会出现问题,例如“A”(Alpha,UTC+1:00)或“B”(Bravo,UTC+ 2:00)。参见 Military time zones查看完整列表。

如何解析这些时区?或者换句话说,除了文字“Z”之外,我可以在上面的格式中输入什么来让它正确解析所有区域?我试过使用 "ddHHmmX MMM yy""ddHHmmZ MMM yy""ddHHmmVV MMM yy",但它们都不起作用(全部将抛出 DateTimeParseException: Text '312359A DEC 14' could not be parsed at index 6 对于上面的例子,解析时)。不允许在格式中使用单个 V(IllegalArgumentException 尝试实例化 DateTimeFormatter 时)。

编辑:如果不是下面的问题,符号 z 似乎可以工作。

我还应该提到,我已经创建了一个 ZoneRulesProvider,其中包含所有命名区域和正确的偏移量。我已验证这些已使用 SPI 机制正确注册,并且我的 provideZoneIds() 方法已按预期调用。仍然不会解析。作为附带问题(编辑:这现在似乎是主要问题),API 不允许除“Z”以外的单字符时区 ID(或“区域”)。

例如:

ZoneId alpha = ZoneId.of("A"); // boom

将抛出 DateTimeException: Invalid zone: A(甚至无需访问我的规则提供程序以查看它是否存在)。

这是对 API 的疏忽吗?还是我做错了什么?


*) 实际上,我使用的是 Java 7 和 ThreeTen Backport ,但我认为这对这个问题并不重要。

PS:我目前的解决方法是使用 25 个不同的 DateTimeFormatter 和文字区域 ID(即 "ddHHmm'A' MMM yy""ddHHmm 'B' MMM yy" 等),使用 RegExp 提取区域 ID,并根据区域委托(delegate)给正确的格式化程序。提供商中的区域 ID 被命名为“Alpha”、“Bravo”等,以允许 ZoneId.of(...) 查找区域。有用。但它不是很优雅,我希望有更好的解决方案。

最佳答案

java.time 中,ZoneId 限制为 2 个字符或更多。具有讽刺意味的是,这是为了预留空间,以便在未来的 JDK 版本中添加军事 ID,如果它被证明有大量需求的话。因此,遗憾的是您的提供者将无法工作,并且无法使用这些名称创建您想要的 ZoneId 实例。

一旦您考虑使用 ZoneOffset 而不是 ZoneId,解析问题就迎刃而解了(考虑到军事区域是固定的偏移量,这是查看问题)。

关键是方法 DateTimeFormatterBuilder.appendText(TemporalField, Map),它允许使用您选择的文本将数字字段格式化并解析为文本。 ZoneOffset 是一个数字字段(值为偏移量中的总秒数)。

在这个例子中,我已经为 ZAB 设置了映射,但是您需要将它们全部添加.否则,代码非常简单,设置一个可以打印和解析军事时间的格式化程序(使用 OffsetDateTime 日期和时间)。

Map<Long, String> map = ImmutableMap.of(0L, "Z", 3600L, "A", 7200L, "B");
DateTimeFormatter f = new DateTimeFormatterBuilder()
    .appendPattern("HH:mm")
    .appendText(ChronoField.OFFSET_SECONDS, map)
    .toFormatter();
System.out.println(OffsetTime.now().format(f));
System.out.println(OffsetTime.parse("11:30A", f));

关于java - 使用 JSR 310(DateTime API)的军事时区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28064988/

相关文章:

java - 如何生成与 java TimeZone(s) 相对应的良好时区下拉列表

javascript - 我们如何在 Sencha ExtJS 版本 6.0.2 中全局设置我们想要使用的时区?

java - YARN hadoop错误java堆空间

python - 从日期 python 中提取年/月到新列

c# - using 命名空间指令只能应用于命名空间

javascript - 使用 JavaScript 将日期时间类型发布到数据库

php - 在 PHP 中将 DateTime 字符串转换为不同的时区

java - 存储压缩图像

java - SSLException : hostname in certificate didn't match: <50. 19.233.255> != <*.heroku.com>

java - 如何避免用户注销后的缓存?