如果无法解析简单的日期时间,为什么可以将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)
答案 0 :(得分:7)
为什么可以将LocalDateTime对象传递给 ZonedDateTime.from()方法,如果不能解析一个简单的 日期时间?
LocalDateTime和ZonedDateTime都实现了名为Temporal的接口,扩展了TemporalAccessor。
LocalDateTime是ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30
ZonedDateTime是ISO-8601日历系统中带有时区的日期时间,例如2007-12-03T10:15:30 + 01:00欧洲/巴黎。
现在,如果您看到期望TemporalAccessor的from(TemporalAccessor temporal)
方法的实现。 ZonedDateTime和LocalDateTime都实现了超级接口TemporalAccessor的方法(Temporal extends TemporalAccessor),这是正常的(多态行为),允许我们传递Local和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)
方法。所以temporal不是ZonedDateTime的一个实例,而是ZoneId zone = ZoneId.from(temporal)
;
所以你得到的错误是因为LocalDateTime不包含 时区。
如何解决问题?
将Zone 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));
}
答案 1 :(得分: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 =真,areAllFieldsSet =真,宽大=真,区= sun.util.calendar.ZoneInfo [ID = “亚洲/加尔各答”,偏移= 19800000,dstSavings = 0 ,useDaylight =假,过渡= 6,lastRule =空],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,微差= 0,ZONE_OFFSET = 19800000,DST_OFFSET = 0]
编辑 刚刚遇到这个帖子(Unable to obtain ZonedDateTime from TemporalAccessor when parsing a Date)
Java 8 java.time。*包是一个非常严格的包。它不允许类型和输入之间的灵活性 - 如果您需要ZonedDateTime对象,则必须从具有时区,日期和时间的输入构造它。一段时间。