Java 8 LocalDateTime ZonedDateTime无法解析带有时区的日期

时间:2016-05-16 11:58:09

标签: datetime timezone java-8 jodatime java-time

我正在尝试使用Java 8新的Date模式而不是Joda,我有以下问题:

两者

ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS Z"))

LocalDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS Z"))

throw' java.time.format.DateTimeParseException'例外。 而

org.joda.time.DateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormat.forPattern("dd/MM/yy HH:mm.ss.SSS Z"))

工作正常。

异常的原因是:

  

java.time.format.DateTimeParseException:Text' 02/05/16 11:51.12.083 +04:30'无法在索引22处解析

我做错了吗?

4 个答案:

答案 0 :(得分:8)

如果您阅读the javadoc of DateTimeFormatter,您会找到一个详细说明如何使用Z偏移(强调我的)的部分:

  

偏移Z:根据图案字母的数量格式化偏移。一个,两个或三个字母输出小时和分钟,没有冒号,例如'+0130'。当偏移量为零时,输出将为“+0000”。四个字母输出完整形式的局部偏移,相当于Offset-O的四个字母。如果偏移为零,则输出将是相应的本地化偏移文本。 五个字母输出小时,分钟,可选秒输出非零,冒号 。如果偏移量为零,则输出“Z”。六个或更多字母抛出IllegalArgumentException。

因此,使用5 Z将按预期工作:

ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30",
                    DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS ZZZZZ"));

请注意,您可以通过以下方式获得类似的结果:

  • z
  • zz
  • zzz
  • zzzz
  • xxx
  • XXX
  • xxxxx
  • XXXXX

答案 1 :(得分:2)

我在这篇文章Unparsable Date with colon-separated timezone

中找到了答案

为了解析带有分号而不是X或Z的时区的时间戳,如DateFormatter javadoc所示,您需要使用XXX。以下所有工作:

LocalDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX"))

OffsetDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX"))

ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX"))

答案 2 :(得分:0)

您需要使用XXX作为区域偏移量。这适用于ZonedDateTimeOffsetDateTime

ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX"))

它也将与LocalDateTime进行解析,但区域偏移将被截断。

答案 3 :(得分:0)

使用DateTimeFormatterBuilder获取对解析器的精确控制并使用appendOffsetId有效:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
      .appendValue(ChronoField.DAY_OF_MONTH, 2)
      .appendLiteral('/')
      .appendValue(ChronoField.MONTH_OF_YEAR, 2)
      .appendLiteral('/')
      .appendValueReduced(ChronoField.YEAR, 2, 2, 2000)
      .appendLiteral(' ')
      .appendValue(ChronoField.HOUR_OF_DAY)
      .appendLiteral(':')
      .appendValue(ChronoField.MINUTE_OF_HOUR)
      .appendLiteral('.')
      .appendValue(ChronoField.SECOND_OF_MINUTE)
      .appendLiteral('.')
      .appendValue(ChronoField.MILLI_OF_SECOND)
      .appendLiteral(' ')
      .appendOffsetId()
      .toFormatter();

OffsetDateTime.parse("02/05/16 11:51.12.083 +04:30", formatter);