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

Java 8 LocalDateTime ZonedDateTime cannot parse date with time zone

我正在尝试使用 Java 8 新日期模式而不是 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"))

抛出 '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' could not be parsed at index 22

我是不是做错了什么?

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

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

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

我在这个postUnparsable Date with colon-separated timezone

中找到了答案

为了解析带有分号而不是 DateFormatter javadoc 指示的 X 或 Z 的时区的时间戳,您需要使用 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"))

使用 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);

如果你阅读 the javadoc of DateTimeFormatter,你会发现一节详细介绍了如何使用 Z 偏移量(强调我的):

Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

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

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