【问题标题】:How to convert LocalDateTime to GregorianCalendar?如何将 LocalDateTime 转换为 GregorianCalendar?
【发布时间】:2016-08-08 07:27:11
【问题描述】:

如果无法解析简单的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)

【问题讨论】:

  • 您是在问如何转换为GregorianCalendar,还是在问为什么它允许您传递TemporalAccessor 接口的实现并且只在运行时抱怨它?
  • GeorgianCalendar 需要一个时区,所以实际上您可以通过GregorianCalendar.from(ZonedDateTime.parse("2016-08-31T23:00:59+00:00")); 提供一个时区。 ZonedDateTime.from 可能会因不同类型的输入以及 javadoc 中提到的输入而失败。
  • 显示从旧日期时间类到 my Answer 中的 java.time 到 Convert java.util.Date to what “java.time” type? 的转换的图表可能很有用。还可以找到双向转换的示例代码。
  • @BasilBourque 这图真的很棒!

标签: java java-time


【解决方案1】:

您还必须提供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]

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

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

【讨论】:

    【解决方案2】:

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

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

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

    ZonedDateTime 是日期时间带有 ISO-8601 日历系统中的时区,例如 2007-12-03T10:15:30+01:00 Europe/Paris。

    现在,如果你看到from(TemporalAccessor temporal)方法的实现期待TemporalAccessor... LocalDateTimeZonedDateTime都实现了超接口TemporalAccessorTemporal 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) 方法。所以,temporal 不是ZonedDateTime 的实例,它来自ZoneId 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));
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-11
      • 1970-01-01
      • 2021-11-26
      • 2016-04-10
      • 2010-09-19
      相关资源
      最近更新 更多