2017-09-16 130 views
2

tl; dr

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

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

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

为什么?

详细

当让java.time通过DateTimeFormatter.ofLocalizedDateTime自动本地化OffsetDateTime的字符串表示,呼吁format作品,如果格式化携带SHORTMEDIUM一个FormatStyle。但是,如果格式化程序包含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分十四秒ž

坏。

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这个转换?

OffsetDateTime格式化失败的行为是一个错误还是一个功能?

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

回答

1

调试代码,我发现,格式化的this line结束(grepcode的路线是不完全一样的号码我的JDK安装的,但代码):

ZoneId zone = context.getValue(TemporalQueries.zoneId()); 

它试图提取该区域使用内置查询TemporalQueries.zoneId()。根据javadoc,该查询返回null如果时间对象是OffsetDateTime

这样一个ZonedDateTime将返回getZone()的结果,而是一个OffsetDateTime将返回null。

您可以致电odt.query(TemporalQueries.zoneId())确认 - 确实返回null

后来,这个查询的结果是checked by a DateTimePrintContext

R result = temporal.query(query); 
if (result == null && optional == 0) { 
    throw new DateTimeException("Unable to extract value: " + temporal.getClass()); 
} 

由于resultnull,它会抛出异常。由于这种模式在上述问题的行结束

// java.time.DateTimeException: Unable to extract value: class java.time.OffsetDateTime 
DateTimeFormatter.ofPattern("z").format(OffsetDateTime.now()); 


事实上,从OffsetDateTime试图让区域名称(模式z)将抛出一个异常。

,并检查所有语言环境的日期风格,采用getLocalizedDateTimePattern

// did this for all locales 
DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.LONG, FormatStyle.LONG, 
    IsoChronology.INSTANCE, locale); 

我没有检查所有,但大多有小写z模式,这意味着它会为最失败的(如果不是全部)语言环境。


没有直接关系,但你与ZoneOffset作为参数调用atZoneSameInstant,你可以简单地调用odt.toZonedDateTime()代替。

3

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

采用FormatStyle.LONGFormatStyle.FULLseems需要一个ZoneIdOffsetDateTime没有

请仔细阅读java.time 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}. 

你能创造的DateTimeFormatterOffsetDateTimeZoneOffset

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

在这种情况下的格式发生之前OffsetDateTime将被转换为一个ZonedDateTime

相关问题