tl; dr
这失败了。
OffsetDateTime.now()
.format(
DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG )
) // throws DateTimeException.
但是在
ZonedDateTime
中具有相同偏移量的相同时刻有效。为什么?
细节
当让
java.time
通过OffsetDateTime
自动本地化DateTimeFormatter.ofLocalizedDateTime
的字符串表示形式时,如果格式化程序带有format
或FormatStyle
的SHORT
,则调用MEDIUM
是可行的。但是,当格式化程序带有LONG
或FULL
时,将抛出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
成功之处?为什么需要从OffsetDateTime
到ZonedDateTime
的转换?cc
OffsetDateTime
格式化失败的这种行为是错误还是功能?我会提交一个错误报告,但是我想确保我误会了一些东西。
最佳答案
看起来报告了here的Javadoc错误。在提供的示例中,他们使用LocalDateTime
,但是行为是相同的。
使用FormatStyle.LONG
和FormatStyle.FULL
seems来要求ZoneId
不具有OffsetDateTime
的java.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}.
您可以使用
OffsetDateTime
的ZoneOffset
创建OffsetDateTime
。DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withZone(odt.getOffset());
在这种情况下,
ZonedDateTime
将在格式化之前转换为。