UnsupportedTemporalTypeException:不支持的字段:InstantSeconds

时间:2018-01-23 18:41:11

标签: java datetime java-8 formatting

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

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

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

2 个答案:

答案 0 :(得分:4)

The problem is that your format does not completely represent an Instant because your format does not have a representation for minutes at all. The formatter can correctly go from Instant and output the result in your format because an Instant has all of the data that your format requires, but your format does not have everything that an Instant requires.

Try changing your pattern to yyyyMMdd kk:HH:mm:ss.SSS, and you will see that your code now works. Note the addition of mm.

If you absolutely require a minuteless pattern, you should make your own TemporalQuery to extract the information you require from the TemporalAccessor In this case, I simply set minutes to 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();
    }

}

We can then use this TemporalQuery like this:

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

答案 1 :(得分:1)

我知道这是一个老问题,但如果您正在寻找简短的答案,只需向 DateTimeFormatter 添加区域设置和区域,您也可以使用默认设置:yourObject.Select(x => x.RecordedFormID);

这是一个代码示例:

.withLocale(Locale.getDefault()).withZone(ZoneId.systemDefault())

此代码将使用当前时刻,输出样本,使用日期时间格式化程序对其进行格式化并输出格式化的时刻。