如何将LocalDateTime转换为GregorianCalendar?

2022-09-04 19:33:34

如果无法解析简单的 ,为什么可以将对象传递到方法中,如下所示?LocalDateTimeZonedDateTime.from()DateTime

@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

如果无法解析简单的日期时间,为什么可以将 LocalDateTime 对象传递到 ZonedDateTime.from() 方法中?

LocalDateTimeZonedDateTime 都实现了名为 Temporal 的接口,该接口扩展了 TemporalAccessor

LocalDateTime是 ISO-8601 日历系统中没有时区的日期时间,例如 2007-12-03T10:15:30

ZonedDateTime是 ISO-8601 日历系统中具有时区的日期时间,例如 2007-12-03T10:15:30+01:00 欧洲/巴黎。

现在,如果您看到期望临时访问的方法的实现...两者都实现了超级接口()的方法,这是正常的(即具有多态行为),以允许我们传递本地和分区的日期时间。from(TemporalAccessor temporal)LocalDateTimeZonedDateTimeTemporalAccessorTemporal extends TemporalAccessor

法典:

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(TemporalAccessor temporal)ZonedDateTimeZoneId 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));
}

答案 2

您还必须提供。我将不得不查找行为,以了解为什么会这样。一旦我看到它,我会立即编辑和发布。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]

编辑:刚刚遇到这个有趣的线程...

Java 8 java.time.* 包是一个非常严格的包。它不允许类型和输入之间的灵活性 - 如果你想要一个ZonedDateTime对象,你必须从具有时区,日期和时间的输入来构造它。


推荐