Невозможно получить ZonedDateTime из TemporalAccessor, используя DateTimeFormatter и ZonedDateTime в Java 8

Я недавно перешел на Java 8, чтобы, надеюсь, легче справиться с местными и зонированными временами.

Тем не менее, я сталкиваюсь с, на мой взгляд, простой проблемой при разборе простой даты.

public static ZonedDateTime convertirAFecha(String fecha) throws Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            ConstantesFechas.FORMATO_DIA).withZone(
            obtenerZonaHorariaServidor());

    ZonedDateTime resultado = ZonedDateTime.parse(fecha, formatter);
    return resultado;
}

В моем случае:

  • fecha '15 / 06/2014 '
  • ConstantesFechas.FORMATO_DIA - это "дд / мм / гггг"
  • obtenerZonaHorariaServidor возвращает ZoneId.systemDefault()

Итак, это простой пример. Однако синтаксический анализ выдает это исключение:

java.time.format.DateTimeParseException: Text '15/06/2014' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2014-06-15 of type java.time.format.Parsed

Какие-нибудь советы? Я пробовал разные комбинации парсинга и использования TemporalAccesor, но пока безуспешно.

С наилучшими пожеланиями

5 ответов

Решение

Я не уверен, почему это не работает (вероятно, потому что ваш ввод не имеет информации о часовом / часовом поясе). Проще всего разобрать вашу дату как LocalDate сначала (без информации о часовом поясе), затем создайте ZonedDateTime:

public static ZonedDateTime convertirAFecha(String fecha) {
  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
  LocalDate date = LocalDate.parse(fecha, formatter);

  ZonedDateTime resultado = date.atStartOfDay(ZoneId.systemDefault());
  return resultado;
}

Это ошибка, см. JDK-bug-log. Согласно этой информации проблема была решена для Java 9 и Java 8u20. Попробуйте скачать последнюю версию Java 8. Сегодня, 2014-05-12: Доступен релиз раннего доступа 8u20.

ОБНОВИТЬ:

Лично я думаю, так как у вас есть только и ожидайте "dd/MM/yyyy" в качестве шаблона, который вы должны использовать LocalDate как ваш основной тип, как @assylias уже предложил. Что касается вашего контекста, то почти наверняка неудача проекта в использовании ZonedDateTime, Что вы хотите сделать с объектами этого типа? Я могу думать только о специализированных расчетах часового пояса как о сценарии использования. И вы не можете даже напрямую хранить эти ZonedDateTime-объекты в базе данных, поэтому этот тип гораздо менее полезен, чем считают многие.

То, что я описал как проблему вашего варианта использования, действительно является новым аспектом, представленным в Java-8 по сравнению со старым GregorianCalendar-класс (который является универсальным). Пользователи должны начать думать о выборе правильного временного типа для своих проблем и вариантов использования.

Проще говоря, линия

ZonedDateTime.parse('2014-04-23', DateTimeFormatter.ISO_OFFSET_DATE_TIME)

выдает исключение:

Text '2014-04-23' could not be parsed at index 10
java.time.format.DateTimeParseException: Text '2014-04-23' could not be parsed at index 10

Это похоже на ошибку для меня.

Я использовал этот обходной путь:

String dateAsStr = '2014-04-23';
if (dateAsStr.length() == 10) {
    dateAsStr += 'T00:00:00';
}
ZonedDateTime.parse(dateAsStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault()));

Если идет от Google:

Вместо того, чтобы делать:

ZonedDateTime.from(new Date().toInstant());

Попробуй это:

ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC")); 

Просто пример конверсии, я думаю, что некоторые люди получат исключение ниже

(java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2014-10-24T18:22:09.800Z of type java.time.Instant)

если они попытаются

LocalDateTime localDateTime = LocalDateTime.from(new Date().toInstant());

Чтобы решить проблему, перейдите в Зону -

LocalDateTime localDateTime = LocalDateTime.from(new Date()
        .toInstant().atZone(ZoneId.of("UTC")));
Другие вопросы по тегам