美文网首页禅与计算机程序设计艺术编程笔记
JDK 8 中的LocalDate不符合正常逻辑的解析报错: U

JDK 8 中的LocalDate不符合正常逻辑的解析报错: U

作者: 光剑书架上的书 | 来源:发表于2019-06-24 17:04 被阅读28次

    问题描述

    
    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


    Kotlin 开发者社区

    国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。
    Kotlin 开发者社区 QRCode.jpg

    相关文章

      网友评论

        本文标题:JDK 8 中的LocalDate不符合正常逻辑的解析报错: U

        本文链接:https://www.haomeiwen.com/subject/zckoqctx.html