如果无法解析简单的DateTime
,为什么可以将LocalDateTime
对象传递给ZonedDateTime. from()
方法,如下所示?
@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)
如果无法解析简单的日期时间,为什么可以将LocalDateTime对象传递给ZonedDateTime. from()方法?
LocalDateTime
和ZonedDateTime
都实现了名为Temporal
的接口,它扩展了TemporalAccator
。
LocalDateTime
是ISO-8601日历系统中没有时区的日期时间,如2007-12-03T10:15:30
ZonedDateTime
是ISO-8601日历系统中带有时区的日期时间,例如2007-12-03T10:15:30 01:00 Europe/Paris。
现在,如果你看到from(TemporalAcc制时间)
方法的实现,它需要TemporalAcc制…LocalDateTime
和ZonedDateTime
都实现了超级接口TemporalAcc制时间
(Temporal扩展TemporalAcc制时间
)的方法,这是正常的(即具有多态行为),允许我们传递本地和分区日期时间。
代码:
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
);
}
}
现在,我们来谈谈你的问题。
您正在将LocalDateTime. parse("2016-08-31T23:00:59")
传递给from(TemporalAcc不时态)
方法。因此,时态不是ZonedDateTime
的实例,它来自ZoneId zone=ZoneId.from(时态);
。
因此,您收到错误,因为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));
}
您还必须提供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[time=1472664659000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Calcutta",offset=19800000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=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,HOUR=11,HOUR_OF_DAY=23,MINUTE=0,SECOND=59,MILLISECOND=0,ZONE_OFFSET=19800000,DST_OFFSET=0]
编辑:刚刚遇到这个有趣的线索…
Java8 java. time.*包是一个非常严格的包。它不允许类型和输入之间的灵活性——如果你想要一个ZonedDateTime对象,你必须从一个有时区、日期的输入构造它