解决异常 UnsupportedTemporalTypeException: Unsupported Field: InstantSeconds

1、概览

在处理日期时,我们经常使用 Date/Time API。但是,如果操作不当,操作或访问时间数据可能会导致错误和异常。其中一个经常遇到的异常就是 UnsupportedTemporalTypeException: “Unsupported Field: InstantSeconds”,通常表示指定的 Temporal(时态)对象不支持 InstantSeconds 字段 。

本将带你了解出现 UnsupportedTemporalTypeException 异常的原因,以及解决办法。

2、实例

在介绍解决方案之前,先通过一个实际例子来了解导致该异常的根本原因。

根据文档,UnsupportedTemporalTypeException 表示不支持 ChronoFieldChronoUnit。换句话说,当在不支持特定字段的时间(Temporal)对象上使用不支持的字段时,就会引发此异常。

异常堆栈中的 “Unsupported Field: InstantSeconds” 消息说明了一切。它表明字段 InstantSeconds 出了问题,该字段表示从纪元(Epoch)开始的秒数的连续计数的概念。

简而言之,并非所有 Date / Time API 提供的时间对象都支持该字段。例如,尝试将涉及 InstantSeconds 的操作应用到 LocalDateTimeLocalDateLocalTime 时,会导致 UnsupportedTemporalTypeException 异常。

现在,来看看如何重现异常。如下,尝试把 LocalDateTime 转换为 Instant

@Test
void givenLocalDateTime_whenConvertingToInstant_thenThrowException() {
    assertThatThrownBy(() -> {
        LocalDateTime localDateTime = LocalDateTime.now();
        long seconds = localDateTime.getLong(ChronoField.INSTANT_SECONDS);
        Instant instant = Instant.ofEpochSecond(seconds);
    }).isInstanceOf(UnsupportedTemporalTypeException.class)
        .hasMessage("Unsupported field: InstantSeconds");
}

上述测试代码会失败,因为我们试图使用 LocalDateTime 实例来访问 ChronoField.INSTANT_SECONDS

简而言之,LocalDateTime 不支持 INSTANT_SECONDS,因为同一个 LocalDateTime 对象可以根据时区代表多个不同的时刻。例如,纽约的 “2024-06-22T11:20:33” 不同于北京的 “2024-06-22T11:20:33”。

3、解决办法

如前所述,LocalDateTime 不支持 ChronoField.INSTANT_SECONDS 的主要原因是它缺乏关于时区的足够信息来确定全球时间线上的精确瞬时点(Instant)。

因此,最简单的解决方案是在将 LocalDateTime 转换为 Instant 之前设置时区。为此,可以使用 ZonedDateTime 类:

@Test
void givenLocalDateTime_whenConvertingUsingTimeZone_thenDoNotThrowException() {
    LocalDateTime localDateTime = LocalDateTime.now();
    ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());

    assertThatCode(() -> {
        Instant instant = zonedDateTime.toInstant();
    }).doesNotThrowAnyException();
}

如上,使用了 atZone() 方法,将给定的 LocalDateTime 转换为指定时区的 ZonedDateTime 对象。然后,调用 toInstant() 方法,根据提供的时区计算日期时间所代表的瞬时点(Instant)。

4、总结

本文介绍了导致 UnsupportedTemporalTypeException 异常的根本原因,以及解决该异常的方法。


Ref:https://www.baeldung.com/java-solve-unsupportedtemporaltypeexception-unsupported-field-instantseconds