JDK 8 中的LocalDate不符合正常逻辑的解析报错: Unable to obtain LocalDateTime from TemporalAccessor: {Year=2019, ......

问题描述


import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@RunWith(JUnit4::class)
class DateTimeTest {

    @Test
    fun test1() {
        val dtf = DateTimeFormatter.ofPattern("yyyyMM")
        val a = LocalDate.parse("201906", dtf) // 报错!!!
        println(a)
    }

    @Test
    fun test2() {
        val formatter = DateTimeFormatter.ofPattern("yyyyMMdd")
        val b = LocalDate.parse("20190601", formatter) // OK
        println(b)
    }

}

报错


java.time.format.DateTimeParseException: Text '201906' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {Year=2019, MonthOfYear=6},ISO of type java.time.format.Parsed

    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at com.alibaba.alibrain.quotareport.util.DateTimeTest.test(DateTimeTest.kt:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {Year=2019, MonthOfYear=6},ISO of type java.time.format.Parsed
    at java.time.LocalDateTime.from(LocalDateTime.java:461)
    at java.time.LocalDateTime$$Lambda$7/1157740463.queryFrom(Unknown Source)
    at java.time.format.Parsed.query(Parsed.java:226)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
    ... 24 more
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {Year=2019, MonthOfYear=6},ISO of type java.time.format.Parsed
    at java.time.LocalDate.from(LocalDate.java:368)
    at java.time.LocalDateTime.from(LocalDateTime.java:456)
    ... 27 more

采用原生的实现类来实现解析

@Test
fun test2() {
    val s = "201906"
    val dtf = DateTimeFormatterBuilder()
            .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendValue(ChronoField.MONTH_OF_YEAR, 2)
            .toFormatter()
    val temporalAccessor = dtf.parse(s)
    val year = temporalAccessor.get(ChronoField.YEAR) // 2019
    val month = temporalAccessor.get(ChronoField.MONTH_OF_YEAR) // 6
    val ld = LocalDate.of(year, month, 1)
    val fmt = ld.format(DateTimeFormatter.ofPattern("yyyy-MM"))
    println(fmt) // 2019-06
}

相关问题

I am simply trying to convert a date string into a DateTime object in Java 8. Upon running the following lines:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dt = LocalDateTime.parse("20140218", formatter);

I get the following error:

Exception in thread "main" java.time.format.DateTimeParseException: 
Text '20140218' could not be parsed: 
Unable to obtain LocalDateTime from TemporalAccessor: 
{},ISO resolved to 2014-02-18 of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)
The syntax is identical to what has been suggested here, yet I am served with an exception. I am using JDK-8u25.

5个回答

答案1

It turns out Java does not accept a bare Date value as DateTime. Using LocalDate instead of LocalDateTime solves the issue:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate dt = LocalDate.parse("20140218", formatter);

参考答案2

Expanding on retrography's answer..: I had this same problem even when using LocalDate and not LocalDateTime. The issue was that I had created my DateTimeFormatter using .withResolverStyle(ResolverStyle.STRICT);, so I had to use date pattern uuuuMMdd instead of yyyyMMdd (i.e. "year" instead of "year-of-era")!

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
  .parseStrict()
  .appendPattern("uuuuMMdd")
  .toFormatter()
  .withResolverStyle(ResolverStyle.STRICT);
LocalDate dt = LocalDate.parse("20140218", formatter);

(This solution was originally a comment to retrography's answer, but I was encouraged to post it as a stand-alone answer because it apparently works really well for many people.)

参考答案3
If you really need to transform a date to a LocalDateTime object, you could use the LocalDate.atStartOfDay(). This will give you a LocalDateTime object at the specified date, having the hour, minute and second fields set to 0:

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime time = LocalDateTime.from(LocalDate.parse("20140218", formatter).atStartOfDay());

参考答案4
This is a really unclear and unhelpful error message. After much trial and error I found that LocalDateTime will give the above error if you do not attempt to parse a time. By using LocalDate instead, it works without erroring.

This is poorly documented and the related exception is very unhelpful.

参考答案5
For what is worth if anyone should read again this topic(like me) the correct answer would be in DateTimeFormatter definition, e.g.:

private static DateTimeFormatter DATE_FORMAT =  
            new DateTimeFormatterBuilder().appendPattern("dd/MM/yyyy[ [HH][:mm][:ss][.SSS]]")
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .toFormatter(); 

One should set the optional fields if they will appear. And the rest of code should be exactly the same.

Unable to obtain LocalDateTime from TemporalAccessor when parsing LocalDateTime (Java 8)

I am simply trying to convert a date string into a DateTime object in Java 8. Upon running the following lines:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dt = LocalDateTime.parse("20140218", formatter);

I get the following error:

Exception in thread "main" java.time.format.DateTimeParseException: 
Text '20140218' could not be parsed: 
Unable to obtain LocalDateTime from TemporalAccessor: 
{},ISO resolved to 2014-02-18 of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)

The syntax is identical to what has been suggested here, yet I am served with an exception. I am using JDK-8u25.

https://stackoverflow.com/questions/27454025/unable-to-obtain-localdatetime-from-temporalaccessor-when-parsing-localdatetime

你可能感兴趣的:(JDK 8 中的LocalDate不符合正常逻辑的解析报错: Unable to obtain LocalDateTime from TemporalAccessor: {Year=2019, ......)