使用 ZonedDateTime 解析日期时出现 DateTimeParseException
我有下面的程序,看起来 ZonedDateTime 无法解析日期字符串。我应该使用不同的日期格式或不同的库来解析吗?
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
class Scratch {
public static void main(String[] args) {
final String inputDate = "2022-03-12T03:59:59+0000Z";
ZonedDateTime.parse(inputDate, DateTimeFormatter.ISO_DATE_TIME).toEpochSecond();
}
}
Exception in thread "main" java.time.format.DateTimeParseException: Text '2022-03-12T03:59:59+0000Z' could not be parsed, unparsed text found at index 19
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2053)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:599)
at Scratch.main(scratch_29.java:7)
Process finished with exit code 1
I have the below program and looks like ZonedDateTime is not able to parse the date string. Should I use a different date format or different library to parse?
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
class Scratch {
public static void main(String[] args) {
final String inputDate = "2022-03-12T03:59:59+0000Z";
ZonedDateTime.parse(inputDate, DateTimeFormatter.ISO_DATE_TIME).toEpochSecond();
}
}
Exception in thread "main" java.time.format.DateTimeParseException: Text '2022-03-12T03:59:59+0000Z' could not be parsed, unparsed text found at index 19
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2053)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:599)
at Scratch.main(scratch_29.java:7)
Process finished with exit code 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这不是 ISO_DATE_TIME 格式。这需要类似
2022-03-12T03:59:59+0000
(没有“Z”)。一个有效的格式化程序看起来像:源自这篇文章。您可以在一处创建该格式化程序并再次使用它。
That isn't a ISO_DATE_TIME format. That would require something like
2022-03-12T03:59:59+0000
(no 'Z'). A formatter that works looks something like:as derived from this post. You can create that formatter in one place and use it over again.
tl;dr
您的输入恰好是
java.time.Instant
类默认使用的标准 IS0 8601 格式的扭曲变体。修复您的输入字符串并解析。或者,重新格式化:
查看此代码在 IdeOne.com 上实时运行。
但最好的解决方案是在交换日期时间值时仅使用 ISO 8601 格式。
详细信息
ZonedDateTime
此处不合适ZonedDateTime
是您输入的错误类。您的输入有一个Z
,它是与 UTC 零小时-分钟-秒的偏移量的标准缩写。但没有指示时区,仅显示偏移量。因此,请使用OffsetDateTime
或Instant
而不是ZonedDateTime
。+0000
和Z
冗余+0000
还意味着零时-分-秒的偏移。这与Z
的含义相同。所以这部分是多余的。我建议您向数据发布者介绍标准 ISO 8601 格式。无需发明输入中看到的格式。字符串操作而不是自定义格式化程序
如果您的所有输入都具有相同的
+0000Z
结尾,我建议您清理传入数据而不是定义格式化模式。其他格式
您稍后发表评论:
这两个都是标准的 ISO 8601 格式。两者都可以解析为
OffsetDateTime
对象按原样,无需更改。因此,我仍然认为,考虑到可能的输入范围,最简单的方法是执行
replace
首先进行字符串操作,其中没有如果你的其他两种格式有效 到达。然后将所有三个变体解析为 OffsetDateTime 对象。有时,程序员往往会过度思考问题,并过度设计复杂的解决方案,而一个简单的解决方案就足够了。示例代码:
请参阅此 代码在 IdeOne.com 上实时运行。
解析时捕获
DateTimeParseException
以检测另一种意外格式。当然,最好的解决方案是教育数据发布者如何一致使用 ISO 8601 格式(例如后两个示例),同时避免使用第一个示例的古怪格式。
从纪元开始计数
我建议不要将时间作为从纪元开始计数的方式进行跟踪。这样的计数本质上是不明确的并且容易出错。相反,请使用标准 ISO 8601 格式的文本。但如果你坚持要数的话,就在这里。
要获取自 1970-01-01T00:00Z 纪元引用以来的秒数,请从
OffsetDateTime
中提取Instant
并进行询问。tl;dr
Your input happens to be a screwy variation of the standard IS0 8601 format used by default with the
java.time.Instant
class. Fix your input string, and parse.Or, reformatted:
See this code run live at IdeOne.com.
But the very best solution is to use only ISO 8601 formats when exchanging date-time values.
Details
ZonedDateTime
inappropriate hereZonedDateTime
is the wrong class for your input. Your input has aZ
which is a standard abbreviation for an offset from UTC of zero hours-minutes-seconds. But no time zone indicated, only a mere offset. So useOffsetDateTime
orInstant
rather thanZonedDateTime
.+0000
andZ
redundantThe
+0000
also means an offset of zero hours-minutes-seconds. This is the same meaning as theZ
. So this part is redundant. I suggest you educate the publisher of your data about the standard ISO 8601 formats. No need to invent formats such as seen in your input.String manipulation rather than custom formatter
If all your inputs have the same ending of
+0000Z
, I suggest you clean the incoming data rather than define a formatting pattern.Other formats
You later commented:
Both of those are standard ISO 8601 formats. Both can be parsed as
OffsetDateTime
objects as-is, without alteration.So I still maintain that the simplest approach, given your range of possible inputs, is to do the
replace
string manipulation first, which has no effect if your other two formats arrive. Then parse all three variations asOffsetDateTime
objects. Sometimes programmers tend to over-think a problem, and over-engineer an elaborate solution where a simple one suffices.Example code:
See this code run live at IdeOne.com.
Trap for
DateTimeParseException
while parsing to detect yet another unexpected format.Of course, the best solution is to educate the publisher of your data about consistent use of ISO 8601 formats such as the latter two examples, while avoiding the screwy first example’s format.
Count since epoch
I recommend against tracking time as a count-since-epoch. Such a count is inherently ambiguous and error-prone. Instead, use text in standard ISO 8601 format. But if you insist on a count, here it is.
To get a count of seconds since the epoch reference of 1970-01-01T00:00Z, extract a
Instant
from theOffsetDateTime
, and interrogate.