2016-08-08 2 views
4

Почему возможно передать объект LocalDateTime в метод ZonedDateTime.from(), если невозможно разобрать простое datetime, следующим образом?Как преобразовать LocalDateTime в GregorianCalendar?

@Test 
public void test() throws Exception { 
    GregorianCalendar.from(ZonedDateTime.from(LocalDateTime.parse("2016-08-31T23:00:59"))); 
} 

Результат:

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2016-08-31T23:00:59 of type java.time.LocalDateTime 
    at java.time.ZonedDateTime.from(ZonedDateTime.java:565) 
+1

вы спрашиваете, как преобразовать в 'GregorianCalendar', или вы спрашиваете, почему он позволяет передать внедрение интерфейса «TemporalAccessor» и только жалуется на это во время выполнения? – RealSkeptic

+2

GeorgianCalendar требует часовой пояс, поэтому на самом деле вы можете сделать 'GregorianCalendar.from (ZonedDateTime.parse (« 2016-08-31T23: 00: 59 + 00: 00 »));' предоставление часового пояса. 'ZonedDateTime.from' может терпеть неудачу для разных типов ввода и указанного в javadoc. – vsminkov

+1

Диаграмма, показывающая преобразования из старых классов времени-времени в java.time в [мой ответ] (http://stackoverflow.com/a/36639155) в [Конвертировать java.util.Date в тип «java.time» ?] (http://stackoverflow.com/q/36639154) может оказаться полезным. Также найдите пример кода преобразования в обоих направлениях. –

ответ

4

Вы должны будете предоставить ZoneId, а также, я должен смотреть на поведение, почему это, я буду редактировать и отправлять как только я вижу это

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59"); 
GregorianCalendar gc = GregorianCalendar.from(ZonedDateTime.of(ldt, ZoneId.systemDefault())); 
System.out.println(gc); 

Это приводит:

java.util.GregorianCalendar [время = 1472664659000, areFieldsSet = Tru е, areAllFieldsSet = верно, мягок = верно, зона = sun.util.calendar.ZoneInfo [ID = "Азия/Калькутты", смещение = 19800000, dstSavings = 0, useDaylight = ложь, переходы = 6, lastRule = NULL], firstDayOfWeek = 2, minimalDaysInFirstWeek = 4, ERA = 1, ГОД = 2016, МЕСЯЦ = 7, WEEK_OF_YEAR = 35, WEEK_OF_MONTH = 5, DAY_OF_MONTH = 31, day_of_year = 244, DAY_OF_WEEK = 4, DAY_OF_WEEK_IN_MONTH = 5, AM_PM = 1, ЧАС = 11 , HOUR_OF_DAY = 23, МИНУТЫ = 0, ВТОРОЕ = 59, миллисекунду = 0, ZONE_OFFSET = 19800000, DST_OFFSET = 0]

редактирует Просто наткнулся на эту тему (Unable to obtain ZonedDateTime from TemporalAccessor when parsing a Date)

Java-8 java.time. * package - очень строгий пакет. Это не допускает гибкости между типами и входами - если вы хотите объект ZonedDateTime, вы должны построить его со входа, который имеет часовой пояс, дату & время.

5

Почему можно передать объект LocalDateTime в метод ZonedDateTime.from(), если это не представляется возможным разобрать простой DateTime?

Оба LocalDateTime и ZonedDateTime реализует интерфейс под названием Temporal, который простирается TemporalAccessor.

LocalDateTime является дата-время без временной зоны в календарной системе ISO-8601, например, 2007-12-03T10: 15: 30

ZonedDateTime является дата-время с временной зоной в ISO -8601, например, 2007-12-03T10: 15: 30 + 01: 00 Европа/Париж.

Теперь, если вы видите, что метод from(TemporalAccessor temporal), который ожидает TemporalAccessor. Как ZonedDateTime, так и LocalDateTime реализуют метод суперинтерфейса TemporalAccessor (Temporal extends TemporalAccessor), это нормально (полиморфное поведение), чтобы мы могли передавать как локальное, так и Zoned дату.

Код:

public static ZonedDateTime from(TemporalAccessor temporal) { 
      if (temporal instanceof ZonedDateTime) { 
       return (ZonedDateTime) temporal; 
      } 
      try { 
       ZoneId zone = ZoneId.from(temporal); 
       if (temporal.isSupported(INSTANT_SECONDS)) { 
        long epochSecond = temporal.getLong(INSTANT_SECONDS); 
        int nanoOfSecond = temporal.get(NANO_OF_SECOND); 
        return create(epochSecond, nanoOfSecond, zone); 
       } else { 
        LocalDate date = LocalDate.from(temporal); 
        LocalTime time = LocalTime.from(temporal); 
        return of(date, time, zone); 
       } 
      } catch (DateTimeException ex) { 
       throw new DateTimeException("Unable to obtain ZonedDateTime from TemporalAccessor: " + 
         temporal + " of type " + temporal.getClass().getName(), ex); 
      } 
     } 

Теперь мы подошли к вашей проблеме.

Вы передаете LocalDateTime.parse("2016-08-31T23:00:59") методу from(TemporalAccessor temporal).Таким образом, временный не является экземпляром ZonedDateTime, он приходит ZoneId zone = ZoneId.from(temporal);

Так вы получаете ошибку, так как LocalDateTime не содержит часовой пояс .

Как решить проблему?

Используйте Id зоны с ZonedDateTime

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59"); 
ZoneId zoneId = ZoneId.of("Europe/Paris"); 
ZonedDateTime zdt = ldt.atZone(zoneId); 
GregorianCalendar gc = GregorianCalendar.from(zdt); 

С теста JUnit

@Test 
public void test() throws Exception { 
    ZoneId zoneId = ZoneId.of("Europe/Paris"); 
    GregorianCalendar.from(LocalDateTime.parse("2016-08-31T23:00:59").atZone(zoneId)); 
}