Why is it possible to pass a LocalDateTime object into the
ZonedDateTime.from() method if it's not possible to parse a simple
datetime?
Both LocalDateTime and ZonedDateTime implement the interface called Temporal, which extends TemporalAccessor.
LocalDateTime is datetime without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30
ZonedDateTime is datetime with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.
Now, if you see the implementation of from(TemporalAccessor temporal) method that is expecting the TemporalAccessor… Both LocalDateTime and ZonedDateTime implements the method of super interface TemporalAccessor (Temporal extends TemporalAccessor), which is normal (i.e. has a polymorphic behavior) to allow us to pass both the local as well as zoned datetime.
Code:
public static ZonedDateTime from(final TemporalAccessor temporal) {
if (temporal instanceof ZonedDateTime) {
return (ZonedDateTime) temporal;
}
try {
final 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 (final DateTimeException exception) {
throw new DateTimeException(
"Unable to obtain ZonedDateTime from TemporalAccessor: " +
temporal + " of type " + temporal.getClass().getName(),
exception
);
}
}
Now, we come to your problem.
You are passing LocalDateTime.parse("2016-08-31T23:00:59") to the from(TemporalAccessor temporal) method. So, the temporal is not an instance of ZonedDateTime, it comes ZoneId zone = ZoneId.from(temporal);.
So, your are getting the error since the LocalDateTime does not contain the
timezone.
How to solve the issue?
Use the Zone ID with the 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);
with JUnit test
@Test
public void test() throws Exception {
ZoneId zoneId = ZoneId.of("Europe/Paris");
GregorianCalendar.from(LocalDateTime.parse("2016-08-31T23:00:59").atZone(zoneId));
}