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));
}