使用JSR 310(DateTime API)的军事时区 [英] Military time zones using JSR 310 (DateTime API)

查看:102
本文介绍了使用JSR 310(DateTime API)的军事时区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the JSR 310 DateTime API* in my application, and I need to parse and format military date times (known as DTG or "date time group").

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

The format I'm parsing looks like this (using 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).有关完整列表,请参见军事时区.

This format is fairly easy to parse as described above. The problem arises when the dates contains a different time zone than 'Z' (Zulu time zone, same as UTC/GMT), for example 'A' (Alpha, UTC+1:00) or 'B' (Bravo, UTC+2:00). See Military time zones for the full list.

如何解析这些时区?或者换句话说,除了字面的"Z"之外,我还能在上面加上什么格式以使其正确解析所有区域?我尝试使用"ddHHmmX MMM yy""ddHHmmZ MMM yy""ddHHmmVV MMM yy",但是它们都不起作用(在解析时,上面的示例都将抛出DateTimeParseException: Text '312359A DEC 14' could not be parsed at index 6).不允许使用单个V格式(尝试实例化DateTimeFormatter时使用IllegalArgumentException).

How can I parse these time zones? Or in other words, what can I put in the format above other than the literal 'Z' to have it parse all zones correctly? I have tried using "ddHHmmX MMM yy", "ddHHmmZ MMM yy" and "ddHHmmVV MMM yy", but none of them work (all will throw DateTimeParseException: Text '312359A DEC 14' could not be parsed at index 6 for the example above, when parsing). Using a single V in the format is not allowed (IllegalArgumentException when trying to instantiate DateTimeFormatter).

如果不是以下问题,似乎符号z可能有效.

It seems that the symbol z could have worked, if it wasn't for the issue below.

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

I should also mention that I have created a ZoneRulesProvider with the all the named zones and correct offset. I have verified that these are registered correctly using the SPI mechanism, and my provideZoneIds() method is invoked as expected. Still won't parse. As a side issue ( this now seems to be the main issue), single character time zone ids (or "regions") other than 'Z' are not allowed by the API.

例如:

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

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

Will throw DateTimeException: Invalid zone: A (without even accessing my rules provider to see if it exists).

这是对API的监督吗?还是我做错了什么?

Is this an oversight in the API? Or am I doing something wrong?

*)实际上,我正在使用Java 7和 ThreeTen Backport ,但是我认为这并不重要问题.

*) Actually, I'm using Java 7 and ThreeTen Backport, but I don't think that matters for this question.

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

PS: My current workaround is to use 25 different DateTimeFormatters with literal zone id (ie. "ddHHmm'A' MMM yy", "ddHHmm'B' MMM yy", etc), use a RegExp for extracting the zone id, and delegating to the correct formatter based on the zone. Zone ids in the provider are named "Alpha", "Bravo", etc to allow ZoneId.of(...) to find the zones. It works. But it's not very elegant, and I'm hoping there's a better solution.

推荐答案

java.time中,ZoneId不得超过2个字符.具有讽刺意味的是,这是为了保留空间,以便在证明JDK的需求量很大时,可以在将来的JDK版本中添加军用ID.因此,遗憾的是您的提供程序将无法运行,并且无法用这些名称创建您想要的ZoneId实例.

In java.time, the ZoneId is limited to be 2 characters or more. Ironically, this was to reserve space to allow the military IDs to be added in a future JDK release if it proved to be heavily in demand. As such, sadly your provider will not work, and there is no way to create the ZoneId instances you desire with those names.

考虑使用ZoneOffset而不是ZoneId时,解析问题就可以解决了(考虑到军事区是固定偏移量,这是解决问题的好方法).

The parsing problem is soluble once you consider working with ZoneOffset instead of ZoneId (and given that military zones are fixed offsets, that is a good way to look at the problem).

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

The key is the method DateTimeFormatterBuilder.appendText(TemporalField, Map) which allows a numeric field to be formatted and parsed as text, using text of your choice. And ZoneOffset is a numeric field (the value being the total number of seconds in the offset).

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

I this example, I've setup the mapping for Z, A and B, but you'd need to add them all. Otherwise, the code is pretty simple, setting up a formatter that can print and parse the military time (use OffsetDateTime for date and time).

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));

这篇关于使用JSR 310(DateTime API)的军事时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆