无法将字符串日期解析为具有特定格式的java.time.LocalDateTime



以下代码打印带有时区偏移量的字符串中日期的输出。

String BERLIN_TIME_ZONE = "Europe/Berlin";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh:mm:ssZ");
String dateTimeInString = formatter
.format(ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(BERLIN_TIME_ZONE)));
System.out.println(dateTimeInString); // 2021-06-07T02:12:08+0200

这非常好用。现在,当我们有了dateTimeInString时,我想使用parse方法将它转换回LocalDateTime对象。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh:mm:ssZ");
System.out.println(LocalDateTime.parse(dateTimeInString,formatter));

但是这个解析抛出了一个异常。

Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-06-07T02:12:08+0200' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {SecondOfMinute=8, MinuteOfHour=12, HourOfAmPm=2, OffsetSeconds=7200, NanoOfSecond=0, MilliOfSecond=0, MicroOfSecond=0},ISO resolved to 2021-06-07 of type java.time.format.Parsed
at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
at de.finhome.A.main(A.java:19)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {SecondOfMinute=8, MinuteOfHour=12, HourOfAmPm=2, OffsetSeconds=7200, NanoOfSecond=0, MilliOfSecond=0, MicroOfSecond=0},ISO resolved to 2021-06-07 of type java.time.format.Parsed
at java.base/java.time.LocalDateTime.from(LocalDateTime.java:461)
at java.base/java.time.format.Parsed.query(Parsed.java:235)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
... 2 more
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {SecondOfMinute=8, MinuteOfHour=12, HourOfAmPm=2, OffsetSeconds=7200, NanoOfSecond=0, MilliOfSecond=0, MicroOfSecond=0},ISO resolved to 2021-06-07 of type java.time.format.Parsed
at java.base/java.time.LocalTime.from(LocalTime.java:431)
at java.base/java.time.LocalDateTime.from(LocalDateTime.java:457)
... 4 more

我检查了不同的资源,但找不出问题。

将小时标记从hh更改为HH。小写h为0-12,即文档所称的上午至下午的时钟小时。大写H为0-23,即文档所称的一天中的小时

虽然格式化程序在输出日期时可以很乐意地执行,但当您尝试读取同一字符串时,会产生歧义。解析器不知道...T01:...应该是1AM还是PM。由于它不能明确地解析,所以它失败了。

或者,在AM/PM的格式字符串中添加一些内容(可以使用a(。然后,解析器将能够明确地解释一个小时,例如01。

似乎您还想将LocalDateTime.parse更改为ZonedDateTime.parse,这样您就不会放弃该区域。

这看起来不像是应该使用LocalDateTime的情况。

有两种选择:ZonedDateTime(您已经使用过(和OffsetDateTime(您可能想要使用(。。。

如果您想提供一个区域,在该区域中获取当前时间,并在没有显式区域但带有该区域偏移的情况下打印结果,那么我建议在大部分时间内使用ZonedDateTime

这样做:

public static void main(String[] args) {
// provide a zone
String BERLIN_TIME_ZONE = "Europe/Berlin";
// use ZonedDateTime.now() directly and pass the zone
ZonedDateTime nowBerlin = ZonedDateTime.now(ZoneId.of(BERLIN_TIME_ZONE));
// then create a String that actually keeps the offset and omits the zone
String dateTimeInString = nowBerlin.format(
DateTimeFormatter.ISO_OFFSET_DATE_TIME
);
// print the result
System.out.println(dateTimeInString);

// if you now want to convert back, use an OffsetDateTime
OffsetDateTime nowPlus2h = OffsetDateTime.parse(dateTimeInString);
// and print the result
System.out.println(nowPlus2h.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
// if you want it to not just be a time of 2 hours offset, apply the zone again
ZonedDateTime nowAgainBerlin = nowPlus2h.atZoneSameInstant(
ZoneId.of(BERLIN_TIME_ZONE)
);
// check if that's the same as parsed in the beginning
if (nowAgainBerlin.equals(nowBerlin)) {
System.out.println("Same instant in Berlin");
} else {
System.out.println("Something went wrong in Berlin");
}

// and if you really want to get a LocalDateTime, you can get it like this
LocalDateTime localBerlin = nowBerlin.toLocalDateTime();
LocalDateTime localAgainBerlin = nowPlus2h.toLocalDateTime();

System.out.println(localBerlin + " == " + localAgainBerlin);
}

这只是输出

2021-06-07T15:16:47.259+02:00
2021-06-07T15:16:47.259+02:00
Same instant in Berlin
2021-06-07T15:16:47.259 == 2021-06-07T15:16:47.259

如果你想在输出中不包含millis,那么定义一个适合你需求的格式化程序,但仍然无法将区域或偏移解析为LocalDateTime

最新更新