UnsupportedTemporalTypeException: Unsupported field: InstantSeconds

31,465

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

Solution 2

I know that this is an old question but if you're looking for a short answer just add a locale and zone to the DateTimeFormatter, you may also use the default ones: .withLocale(Locale.getDefault()).withZone(ZoneId.systemDefault())

Here is an example of code:

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

This code will use the current instant, output the sample, format it with the date time formatter and output the formatted instant.

Share:
31,465
Steve
Author by

Steve

Updated on July 09, 2022

Comments

  • Steve
    Steve almost 2 years

    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?