不支持的时间类型异常:不支持的字段:即时秒

2022-09-02 04:00:17

我有这个代码,它正在生成时间戳,然后解析。

DateTimeFormatter formatter = 
    DateTimeFormatter
        .ofPattern("yyyyMMdd kk:HH:ss.SSSZ")
        .withLocale(Locale.getDefault())
        .withZone(ZoneId.systemDefault());

Instant now = Instant.now();

String formatted = formatter.format(now);
Instant parsed = formatter.parse(formatted, Instant::from);

当它运行时,最后一行将生成异常:

java.time.format.DateTimeParseException: Text '20180123 12:12:45.648-0500' could not be parsed: Unable to obtain Instant from TemporalAccessor: {SecondOfMinute=45, NanoOfSecond=648000000, OffsetSeconds=-18000, MilliOfSecond=648, MicroOfSecond=648000, HourOfDay=12},ISO,America/New_York resolved to 2018-01-23 of type java.time.format.Parsed

Caused by: java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {SecondOfMinute=45, NanoOfSecond=648000000, OffsetSeconds=-18000, MilliOfSecond=648, MicroOfSecond=648000, HourOfDay=12},ISO,America/New_York resolved to 2018-01-23 of type java.time.format.Parsed

Caused by: java.time.temporal.UnsupportedTemporalTypeException: **Unsupported field: InstantSeconds**

我将格式化程序替换为DateTimeFormatter.ISO_INSTANT,它可以正常工作。实际产生的数据几乎相同。什么是断开连接?

ISO_INSTANT:  2018-01-23T16:51:25.516Z
My Format:    20180119 23:59:59.999-0800

我需要使用我的格式。这是什么问题?


答案 1

问题在于,您的格式不能完全表示即时,因为您的格式根本没有分钟的表示形式。格式化程序可以正确地从即时格式输出结果,因为即时格式包含您的格式所需的所有数据,但您的格式并不具有即时所需的一切。

尝试将模式更改为 ,您将看到您的代码现在工作正常。请注意添加的 .yyyyMMdd kk:HH:mm:ss.SSSmm

如果你绝对需要一个无分钟模式,你应该创建自己的TemporalQuery,从TemporalAccessor中提取你需要的信息在这种情况下,我只是将分钟设置为:0

public class MyQuery implements TemporalQuery<Instant> {

    @Override
    public Instant queryFrom(TemporalAccessor temporal) {
        LocalDate ld = LocalDate.from(temporal);
        LocalTime lt = LocalTime.of(temporal.get(ChronoField.HOUR_OF_DAY), 0, temporal.get(ChronoField.SECOND_OF_MINUTE), temporal.get(ChronoField.NANO_OF_SECOND));
        return ZonedDateTime.of(ld, lt, ZoneId.systemDefault()).toInstant();
    }

}

然后,我们可以像这样使用此 TemporalQuery:

public class Test {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("yyyyMMdd kk:HH:mm:ss.SSS")
            .withLocale(Locale.getDefault())
            .withZone(ZoneId.systemDefault());

        Instant now = Instant.now();

        String formatted = formatter.format(now);
        System.out.println(formatted);

        Instant ld = formatter.parse(formatted, new MyQuery());
    }
}

答案 2

我知道这是一个老问题,但如果你正在寻找一个简短的答案,只需向DateTimeFormatter添加一个区域设置和区域,你也可以使用默认的:.withLocale(Locale.getDefault()).withZone(ZoneId.systemDefault())

下面是一个代码示例:

    Instant now = Instant.now();
    System.out.println(now.toString());
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").withLocale(Locale.getDefault()).withZone(ZoneId.systemDefault());
    System.out.println(formatter.format(now));

此代码将使用当前即时,输出示例,使用日期时间格式化程序对其进行格式化,然后输出格式化的即时。