使用 LONG 或 FULL 的 FormatStyle 进行本地化格式化程序时,OffsetDateTime 失败

Bas*_*que 3 java date-formatting timezone-offset java-time

太长了;博士

\n\n

这失败了。

\n\n
OffsetDateTime.now()\n              .format( \n                  DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG )\n              )  // throws DateTimeException.\n
Run Code Online (Sandbox Code Playgroud)\n\n

但作品中的同一时刻具有相同的偏移量ZonedDateTime

\n\n

为什么?

\n\n

细节

\n\n

当让自动本地化viajava.time的字符串表示形式时,如果格式化程序带有of或 ,则调用可以工作。但是当格式化程序携带or时,会抛出a 。然而,使用相同的时刻和相同的偏移量成功了。为什么?OffsetDateTimeDateTimeFormatter.ofLocalizedDateTimeformatFormatStyleSHORTMEDIUMLONGFULLDateTimeExceptionZonedDateTime

\n\n
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ) ;\n\nOffsetDateTime odt = OffsetDateTime.now( ZoneId.systemDefault() ) ;\nZonedDateTime zdt = odt.atZoneSameInstant( odt.getOffset() ) ;  // Generate a `ZonedDateTime` with same moment and same offset as the `OffsetDateTime`.\n\n// Succeeds.\nString outputZdt = zdt.format( f ) ;\nSystem.out.println( "outputZdt: " + outputZdt ) ;\n\n// Fails. Throws exception.\nif ( false ) {\nString outputOdt = odt.format( f ) ;  // Throws exception.\nSystem.out.println( "outputOdt: " + outputOdt ) ;\n} \n
Run Code Online (Sandbox Code Playgroud)\n\n

请参阅在 IdeOne.com 上实时运行的代码

\n\n

当运行\xe2\x80\xa6时

\n\n

好的。

\n\n
\n

输出Zdt: 2017 年 9 月 16 日 8:42:14 AM Z

\n
\n\n

不好的。

\n\n
OffsetDateTime.now()\n              .format( \n                  DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG )\n              )  // throws DateTimeException.\n
Run Code Online (Sandbox Code Playgroud)\n\n

我编写了该代码的核心来解决抛出的异常odt.atZoneSameInstant( odt.getOffset() )。然后我意识到,为什么 \xe2\x80\x99tjava.time在内部不做同样的事情?为什么在具有相同时刻和相同偏移量的OffsetDateTimea 成功的情况下格式化失败?ZonedDateTime为什么我需要进行从OffsetDateTime到 的转换ZonedDateTime

\n\n

\xe2\x9e\x9f 这种OffsetDateTime格式化失败的行为是错误还是功能?

\n\n

我会提交错误报告,但我想确保我误解了某些内容。

\n

Sot*_*lis 5

看起来像这里报告的 Javadoc bug 。在提供的示例中,他们使用LocalDateTime,但行为是相同的。

使用FormatStyle.LONGandFormatStyle.FULL 似乎需要一个ZoneIdwhichOffsetDateTime没有

请查看java.timejavadoc 改进,以突出显示关于除了时间之外还需要时区的格式化元素的常见误解。

使用特定于区域设置的格式时,如果区域设置格式不需要时区,则可能会起作用;如果区域设置格式需要时区,但未提供时区,则可能会失败。

这就是为什么他们澄清了 javadoc来提及

* The {@code FULL} and {@code LONG} styles typically require a time-zone.
* When formatting using these styles, a {@code ZoneId} must be available,
* either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
Run Code Online (Sandbox Code Playgroud)

DateTimeFormatter您可以使用OffsetDateTime's创建ZoneOffset

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                  .withZone(odt.getOffset());
Run Code Online (Sandbox Code Playgroud)

在这种情况下,将在格式化之前OffsetDateTime转换为 a 。ZonedDateTime