我不清楚。由于某些原因,当我尝试使用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"))));
}
有什么好的解释吗?
最佳答案
tl; dr
有什么好的解释吗?
是。LONG
和FULL
格式需要时区或从UTC偏移。您的LocalDateTime
缺少任何区域或偏移量。
您使用的LocalDateTime.now
不正确。您只能使用Instant
(或OffsetDateTime
/ ZonedDateTime
)捕获当前时刻。
Instant.now() // Capture the current moment as seen in UTC.
为了更灵活地生成字符串,请使用
OffsetDateTime
或ZonedDateTime
。ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
.format(
DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.LONG // Or `FULL`.
)
.withLocale( Locale.ITALY )
)
NZDT 2019年3月6日10:22:23
并且,使用
FormatStyle.FULL
:mercoledì6 marzo 2019 10:23:25 Ora legale della Nuova Zelanda
LocalDateTime
不是片刻LocalDateTime
类仅是日期和时间。它故意缺少任何时区或从UTC偏移的概念。因此,根据定义,它不能代表片刻。永远不要拨打
LocalDateTime.now()
LocalDateTime.now();
永远不要这样做,永远不要在
now
上调用LocalDateTime
。我无法想到任何实际情况都需要这样做。跟踪时刻时切勿使用
LocalDateTime
。 LocalDateTime
只是日期和时间,仅此而已。没有time zone或offset-from-UTC的上下文,LocalDateTime
不能代表时刻。它代表了大约26-27小时(当前全球时区范围)内的潜在时刻。LocalDateTime
就像说“今年1月23日中午”。您是在日本东京或印度加尔各答(印度)中午吗?也许是法国巴黎?蒙特利尔魁北克省?这些地方的中午发生在不同的时刻,每个时刻之间经过了几个小时。LocalDateTime
中的“本地”是指任何位置或每个位置,但并不表示任何特定位置。捕捉当前时刻
要跟踪时刻,请使用以下类别之一:
Instant
在UTC的时刻,总是在UTCOffsetDateTime
与UTC偏移的时刻,即在UTC基线(格林威治的Royal Observatory处子午线)的基线之前或之后的小时-分钟-秒数。通过特定地区(时区)的人们所使用的挂钟时间所看到的时刻。
通常,最佳做法是在UTC工作,而忘记自己的时区。
Instant instant = Instant.now() ;
如果要使用某个区域的挂钟时间:
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( instant ) ;
ZonedDateTime
和instant
都表示同一时刻,时间轴上的同一点。只有挂钟时间不同。或者,您可以跳过
zdt
。ZonedDateTime zdt = ZonedDateTime.now( z ) ;
格式
Instant
和LONG
需要一个时区这两种格式样式:
FULL
FormatStyle.LONG
…两者都需要时区作为显示的一部分。
如上所述,
FormatStyle.FULL
对象没有区域或偏移量。因此,将LocalDateTime
或LONG
格式与这样的对象一起使用是没有意义的。提示:
FUL
在大多数常见的面向业务的应用程序中通常不是您想要的类。仅在明确考虑到特定问题时才使用该类,例如,将来预约的时间足够长,以至于您冒着政治家重新定义时区偏移的风险(在大多数政体中,他们经常这样做)。跟踪特定时刻时,请先考虑使用LocalDateTime
。关于java - 使用Locale格式化LocalDateTime实例时获取java.time.DateTimeException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54991260/