невозможно разобрать String-Date на 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
поэтому я хочу преобразовать его обратно в
LocalDateTime
объект с помощью
parse
метод.
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
Я проверял разные ресурсы, но не могу понять, в чем проблема.
2 ответа
Измените жетон часа с
hh
к
HH
. Строчные буквы
h
0–12, или то, что в документах называется « часы-час-до-вечера» . Верхний регистр
H
0–23, или то, что в документах называется часом дня.
В то время как форматировщик может довольно успешно выполнять вывод даты, когда вы пытаетесь прочитать ту же строку, это создает двусмысленность. Парсер не знает,
...T01:...
должно быть 1:00 или PM. Поскольку он не может разобрать однозначно, он терпит неудачу.
В качестве альтернативы добавьте что-нибудь в строку формата для AM / PM (вы можете использовать
a
для этого). Тогда парсер сможет однозначно интерпретировать час, например 01.
Кажется, ты тоже хочешь изменить
LocalDateTime.parse
к
ZonedDateTime.parse
так что вы не выбрасываете зону.
Это не похоже на ситуацию, когда нужно использовать.
Есть две альтернативы: как вы уже используете и
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
Если вы не хотите, чтобы в вашем выводе были миллисекунды, определите средство форматирования, которое соответствует вашим желаниям, но все же вы не сможете анализировать зоны или смещения до
LocalDateTime
.