使用Locale格式化LocalDateTime实例时获取java.time.DateTimeException

时间:2019-03-04 20:45:40

标签: java java.time

我不清楚。由于某些原因,当我尝试使用LocalDateTime格式化DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withLocale(...)实例时,出现了异常:

  

java.time.DateTimeException:无法提取值:class   java.time.LocalDateTime

仅当我使用FormatStyle.LONG时,这种情况才会发生,例如,对于FormatStyle.MEDIUM来说效果很好。

这是我的考试:

@Test
public void dateTest() {
    LocalDateTime now = LocalDateTime.now();

    // this is ok. prints a value
    System.out.println("LocalDateTime now (formatted with locale): "
            + now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
                                                       .withLocale(new Locale("it"))));

    // this fails with java.time.DateTimeException: Unable to extract value: class java.time.LocalDateTime
    // only if FormatStyle.LONG (as it is now)
    System.out.println("LocalDateTime now (formatted with locale): "
            + now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                                       .withLocale(new Locale("it"))));
}

对此有什么好的解释吗?

3 个答案:

答案 0 :(得分:2)

对于FormatStyle.LONG,您必须使用:

ZonedDateTime.now()

代替:

LocalDateTime.now()

因为ZonedDateTime为您提供了很多细节,而不是LocalDateTime

使用FormatStyle.LONG时,格式化程序会搜索ZoneId中找不到的其他信息,例如LocalDateTime,因此会出现异常情况

答案 1 :(得分:2)

tl; dr

  

对此有什么好的解释吗?

是的

LONGFULL格式需要时区或UTC偏移量。您的LocalDateTime 缺少任何区域或偏移量。

您对 LocalDateTime.now的使用不正确。您只应使用Instant(或OffsetDateTime / ZonedDateTime)捕获当前时刻。

Instant.now()  // Capture the current moment as seen in UTC.

要更灵活地生成字符串,请使用OffsetDateTimeZonedDateTime

ZonedDateTime.now( 
    ZoneId.of( "Pacific/Auckland" )
)
.format(
    DateTimeFormatter.ofLocalizedDateTime(
        FormatStyle.LONG   // Or `FULL`.
    )
    .withLocale( Locale.ITALY ) 
)
  

6 marzo 2019 10:22:23 NZDT

还有FormatStyle.FULL

  

mercoledì2019年3月6日10:23:25 Ora legale della Nuova Zelanda

LocalDateTime暂时不是

LocalDateTime类仅是日期和时间。它故意缺少任何时区或从UTC偏移的概念。因此,根据定义,它不能代表片刻。

从不致电LocalDateTime.now()

  

LocalDateTime.now();

永远不要执行此操作,永远不要在LocalDateTime上调用now。我无法想到任何实际情况都需要这样做。

跟踪时刻时切勿使用LocalDateTimeLocalDateTime仅仅是日期和时间,仅此而已。没有time zoneoffset-from-UTC的上下文,LocalDateTime不能代表时刻。它表示大约26-27小时范围内的潜在时刻,这是全球各地时区的当前范围。

LocalDateTime就像是说“今年1月23日中午”。您是在日本东京或印度加尔各答(印度)中午吗?或者也许是法国巴黎?蒙特利尔魁北克省?这些地方的中午发生在不同的时刻,每个时刻之间经过了几个小时。

LocalDateTime中的“本地”表示任何本地,或每个本地,但是不是表示任何特殊的位置。

捕获当前时刻

要跟踪时刻,请使用以下类别之一:

  • Instant
    在UTC的时刻,总是在UTC的时刻
  • OffsetDateTime
    具有与UTC偏移的时刻,即比UTC的基线(在{ {3}}(格林威治)。
  • Royal Observatory
    通过特定地区(时区)的人们所使用的挂钟时间看到的时刻。

通常,最佳做法是在UTC工作,而忘记自己的时区。

Instant instant = Instant.now() ;

如果要使用某个地区的挂钟时间:

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( instant ) ;

instantzdt都表示相同的同时时刻,即时间轴上的相同单点。只有挂钟时间不同。

或者您可以跳过Instant

ZonedDateTime zdt = ZonedDateTime.now( z ) ;

格式LONGFULL需要时区

这两种格式样式:

... 都需要时区作为其显示的一部分。

如上所述,LocalDateTime对象没有区域或偏移量。因此,将LONGFUL格式与这样的对象一起使用是没有意义的。

提示LocalDateTime在大多数常见的面向业务的应用程序中并不是您想要的类。仅当您明确考虑到特定问题时才使用该类,例如,将来预约的时间足够长,以至于您冒着政治家重新定义时区偏移的风险(在大多数政体中,他们经常这样做)。跟踪特定时刻时,请先考虑使用Instant

答案 2 :(得分:0)

当前(Java“ 1.8.0_162”)FormatStyle.FULL和.LONG仅适用于.format(日期) LocalDateTime没有存储很多问题的细节。

详细信息: https://coderanch.com/t/690125/java/java-time-DateTimeException-FormatStyle-LONG