UnsupportedTemporalTypeException: Unsupported field: InstantSeconds

社会主义新天地 提交于 2020-07-29 10:50:09

问题


I have this code which is producing a timestamp and then parsing.

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

When it runs, the last line produces an exception:

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**

I replace the formatter with DateTimeFormatter.ISO_INSTANT, it works correctly. The actual data produced are nearly identical. What is the disconnect?

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

I am required to use my format. What is the problem here?


回答1:


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


来源:https://stackoverflow.com/questions/48408688/unsupportedtemporaltypeexception-unsupported-field-instantseconds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!