tl; dr

这失败了。

OffsetDateTime.now()
              .format(
                  DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG )
              )  // throws DateTimeException.


但是在ZonedDateTime中具有相同偏移量的相同时刻有效。

为什么?

细节

当让java.time通过OffsetDateTime自动本地化DateTimeFormatter.ofLocalizedDateTime的字符串表示形式时,如果格式化程序带有formatFormatStyleSHORT,则调用MEDIUM是可行的。但是,当格式化程序带有LONGFULL时,将抛出DateTimeException。但是ZonedDateTime在相同的时刻使用相同的offset成功。为什么?

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ) ;

OffsetDateTime odt = OffsetDateTime.now( ZoneId.systemDefault() ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( odt.getOffset() ) ;  // Generate a `ZonedDateTime` with same moment and same offset as the `OffsetDateTime`.

// Succeeds.
String outputZdt = zdt.format( f ) ;
System.out.println( "outputZdt: " + outputZdt ) ;

// Fails. Throws exception.
if ( false ) {
String outputOdt = odt.format( f ) ;  // Throws exception.
System.out.println( "outputOdt: " + outputOdt ) ;
}


参见此code run live at IdeOne.com

运行时...

好。


  outputZdt:2017年9月16日上午8:42:14


不好

Exception in thread "main" java.time.DateTimeException: Unable to extract value: class java.time.OffsetDateTime
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:282)
    at java.time.format.DateTimeFormatterBuilder$ZoneTextPrinterParser.format(DateTimeFormatterBuilder.java:3682)
    at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
    at java.time.format.DateTimeFormatterBuilder$LocalizedPrinterParser.format(DateTimeFormatterBuilder.java:4347)
    at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
    at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746)
    at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720)
    at java.time.OffsetDateTime.format(OffsetDateTime.java:1674)
    at Ideone.main(Main.java:28)


我编写了该代码的核心,以解决抛出的异常odt.atZoneSameInstant( odt.getOffset() )。然后我意识到,为什么java.time在内部不做同样的事情?为什么OffsetDateTime不能格式化具有相同矩和相同偏移量的ZonedDateTime成功之处?为什么需要从OffsetDateTimeZonedDateTime的转换?

cc OffsetDateTime格式化失败的这种行为是错误还是功能?

我会提交一个错误报告,但是我想确保我误会了一些东西。

最佳答案

看起来报告了here的Javadoc错误。在提供的示例中,他们使用LocalDateTime,但是行为是相同的。

使用FormatStyle.LONGFormatStyle.FULL seems来要求ZoneId不具有OffsetDateTimejava.time


  请查看DateTimeFormatter javadoc改进以突出显示常见的问题
  关于格式化需要时区的元素的误解
  除了时间。
  
  使用特定于语言环境的格式时,如果语言环境有效
  格式化不需要时区,或者如果区域设置失败
  格式化需要一个时区,而未提供时区。


这就是为什么they clarified the 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}.




您可以使用OffsetDateTimeZoneOffset创建OffsetDateTime

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                  .withZone(odt.getOffset());


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

07-24 09:46
查看更多