我正在尝试将输入字符串解析为本地日期时间。
下面是我的代码
ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z", MY_DATE_TIME_FORMATTER);
其中
MY_DATE_TIME_FORMATTER= new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.appendLiteral('Z')
.appendOffset("+HH:mm", "+0000")
.toFormatter();
我收到以下异常
java.time.format.DateTimeParseException:无法在索引19处解析文本'2019-11-26T19:30:00Z'
您能告诉我我在做什么错吗?
答案 0 :(得分:4)
Instant.parse
不需要格式化模式。
Instant.parse( "2019-11-26T19:30:00Z" )
您的输入格式符合ISO 8601标准。该特定格式的末尾有一个Z
。该字母的意思是UTC(offset,零小时-分钟-秒),发音为“ Zulu”。
java.time 中的Instant
类表示UTC中的时刻,始终为UTC。
使用ZonedDateTime
类作为输入不是最合适的。我们有:
Instant
表示始终以UTC表示的值。 OffsetDateTime
仅适用于距UTC偏移量而不是时区的情况。当您需要更大的灵活性(例如生成各种格式的字符串)时,也可以将此类用于UTC值。 `instant.atOffset(ZonedDateTime
表示时区中的值。时区是特定区域的人们过去,现在和将来对偏移量的更改的历史。要查看调整到特定区域(时区)的人们所使用的偏移量的同一时刻,请应用ZoneId
以获取ZonedDateTime
对象。
Instant instant = Instant.parse( "2019-11-26T19:30:00Z" ) ; // Default format for parsing a moment in UTC.
ZoneId z = ZoneId.of( "America/Edmonton" ) ; // A time zone is a history of past, present, and future changes to the offset used by the people of a particular region.
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, different wall-clock time.
请参阅此code run live at IdeOne.com。
instant.toString():2019-11-26T19:30:00Z
zdt.toString():2019-11-26T12:30-07:00 [美国/埃德蒙顿]
答案 1 :(得分:2)
添加
.appendZoneOrOffsetId()
代替这两行:
.appendLiteral('Z')
.appendOffset("+HH:mm", "+0000")
整个构建器示例:
MY_DATE_TIME_FORMATTER= new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.appendZoneOrOffsetId()
.toFormatter();
P.S。在您的特定情况下,我宁愿使用标准的ISO格式程序(如Hristo所述):
ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z", DateTimeFormatter.ISO_ZONED_DATE_TIME);
此外,即使没有显式格式化程序,ZonedDateTime::parse
方法也可以使用。由于默认使用它:
ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z");
答案 2 :(得分:1)
使用内置的ISO时区格式化程序
ZonedDateTime.parse("2019-11-26T19:30:00Z", DateTimeFormatter.ISO_ZONED_DATE_TIME);