java.time.OffsetDateTime:无法从TemporalAccessor获取OffsetDateTime

时间:2018-01-15 12:49:58

标签: java java-time timezone-offset datetime-parsing java.time.instant

我正在尝试使用"20140726080320+0400"格式解析"yyyyMMddHHmmssZ",如下所示:

System.out.println("********************" + OffsetDateTime
    .parse("20140726080320+0400",
        DateTimeFormatter.ofPattern("yyyyMMddHHmmssZ").withChronology(IsoChronology.INSTANCE).withResolverStyle(STRICT))
    .toEpochSecond()); 

我一直遇到这个例外:

java.time.format.DateTimeParseException: Text '20140726080320+0400' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {OffsetSeconds=14400, DayOfMonth=26, YearOfEra=2014, MonthOfYear=7},ISO resolved to 08:03:20 of type java.time.format.Parsed
    at java.time.format.Parsed.getLong(Parsed.java:203)
    at java.time.Instant.from(Instant.java:373)
    at java.time.OffsetDateTime.from(OffsetDateTime.java:365)
    at java.time.format.Parsed.query(Parsed.java:226)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.OffsetDateTime.parse(OffsetDateTime.java:402)

我做错了什么?

2 个答案:

答案 0 :(得分:2)

格式模式字符串中的

yyyy表示年代。严格地说,2014年可以表示2014年BCE(“在基督之前”)或2014年CE(“anno Domini”)。显然,具有严格解析器样式的格式化程序反对这种歧义。

解决方案是使用uuuu年份。这是签名年份,其中0表示1 BCE,-1表示2 BCE等。所以没有歧义:

    System.out.println("********************"
            + OffsetDateTime.parse("20140726080320+0400",
                                DateTimeFormatter.ofPattern("uuuuMMddHHmmssZ")
                                        .withChronology(IsoChronology.INSTANCE)
                                        .withResolverStyle(STRICT))
                        .toEpochSecond());

打印

  

******************** 1406347400

这与IsoChronology解析不同解析器样式的日期的方式有关,如javadoc中所述:

  

如果仅存在YEAR_OF_ERA,并且模式是智能或宽松的,则假设当前时代(CE / AD)。在严格模式下,不会假设时代,并且YEAR_OF_ERA保持不变。

答案 1 :(得分:0)

试试这个:

LocalDateTime.parse("20140726080320+0400",
    new DateTimeFormatterBuilder().appendPattern("yyyyMMddHHmmssZ").toFormatter())
.atOffset(ZoneOffset.UTC)

回报:

  

2014-07-26T08:03:20

这是错误的,因为它忽略了偏移量(+0400),然后将日期/时间设置为UTC - 这将为epochSecond提供不正确的值