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
作为区域偏移。这将适用于 ZonedDateTime
和 OffsetDateTime
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 Z
s 将按预期工作:
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
我正在尝试使用 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
作为区域偏移。这将适用于 ZonedDateTime
和 OffsetDateTime
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 Z
s 将按预期工作:
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