java.time.Instant could not be parsed from string like '2016-07-02T00:00:00Z'

1k Views Asked by At

In REST API Response I am getting date as '2016-07-02T00:00:00Z'

In code, I have a column like below

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "UTC")
private Instant effectiveDate;

// getter & setter  
public Instant getEffectiveDate() {
    return effectiveDate;
}

public OfferTerm setEffectiveDate(Instant effectiveDate) {
    this.effectiveDate = effectiveDate;
    return this;
}

Getting below error:

java.time.format.DateTimeParseException: Text '2016-07-02T00:00:00Z' could not be parsed, unparsed text found at index 19

Please help me here.

2

There are 2 best solutions below

0
On

Your date-time string is already in the format that Instant#parse uses by default. Given below is a demo to illustrate the same:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2016-07-02T00:00:00Z";
        Instant instant = Instant.parse(strDateTime);
        System.out.println(instant);
    }
}

Output:

2016-07-02T00:00:00Z

Since an Instant represents an instantaneous point on the UTC time-line (i.e. it is independent of timezone), mentioning timezone = "UTC" is unnecessary. The Z in your date-time string is already specifying UTC. Moreover, the pattern, "yyyy-MM-dd'T'HH:mm:ss" does not match the pattern of your date-time string. I hope, you understand that using the timezone and pattern for Instant is not only unnecessary but also the root cause of the error you have faced.

Simply remove @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "UTC") to resolve the issue.

0
On

Upon elaborating on Andreas answers in the comments, the following summary may be offered to parse the Instant from a string containing time zone information:

  1. @JsonFormat may be omitted if the input strings contain time zone information in the form Z or ±[hh]:[mm]:
class Wrapper {
    private Instant effectiveDate;
    // getter/setter
}

// Parseable JSON strings
String[] jsons = {
    "{\"effectiveDate\":\"2016-07-02T00:00:00Z\"}",
    "{\"effectiveDate\":\"2016-07-05T00:00:00+00:00\"}",
    "{\"effectiveDate\":\"2016-07-06T00:00:00+02:00\"}",
    "{\"effectiveDate\":\"2016-07-07T00:00:00-02:00\"}",
}; 

Results:

2016-07-02T00:00:00Z      -> 2016-07-02T00:00:00Z
2016-07-15T00:00:00+00:00 -> 2016-07-15T00:00:00Z
2016-07-16T00:00:00+02:00 -> 2016-07-15T22:00:00Z
2016-07-17T00:00:00-02:00 -> 2016-07-17T02:00:00

Note: "shortcut" timezones like ±[hh][mm] or ±[hh] cannot be parsed here.

  1. If the timezone suffix is not available (no Z or timezone) and/or shortcut timezone info is available, the following format needs to be applied:
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss['Z'][XXX][X]", timezone="UTC")
private Instant effectiveDate;

The following data can be successfully parsed with it:

String[] jsons = {
    "{\"effectiveDate\":\"2016-07-02T00:00:00Z\"}",      // Z
    "{\"effectiveDate\":\"2016-07-09T00:00:00\"}",       // no timezone
    "{\"effectiveDate\":\"2016-07-10T00:00:00+01\"}",    // +hh
    "{\"effectiveDate\":\"2016-07-11T00:00:00-09\"}",    // -hh
    "{\"effectiveDate\":\"2016-07-12T00:00:00+0200\"}",  // +hhmm
    "{\"effectiveDate\":\"2016-07-13T00:00:00-0400\"}",  // -hhmm
    "{\"effectiveDate\":\"2016-07-15T00:00:00+00:00\"}", // +hh:mm
    "{\"effectiveDate\":\"2016-07-16T00:00:00+02:00\"}", // +hh:mm
    "{\"effectiveDate\":\"2016-07-17T00:00:00-02:00\"}"  // -hh:mm
};

Parsing results:

2016-07-02T00:00:00Z      -> 2016-07-02T00:00:00Z
2016-07-09T00:00:00       -> 2016-07-09T00:00:00Z
2016-07-10T00:00:00+01    -> 2016-07-09T23:00:00Z
2016-07-11T00:00:00-09    -> 2016-07-11T09:00:00Z
2016-07-12T00:00:00+0200  -> 2016-07-11T22:00:00Z
2016-07-13T00:00:00-0400  -> 2016-07-13T04:00:00Z
2016-07-15T00:00:00+00:00 -> 2016-07-15T00:00:00Z
2016-07-16T00:00:00+02:00 -> 2016-07-15T22:00:00Z
2016-07-17T00:00:00-02:00 -> 2016-07-17T02:00:00Z
  1. (Hypothetical) If some other timezone suffix such as GMT or UTC with an optional whitespace is present in the input string, the following format will handle it:
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss['Z'][[' ']['GMT']][[' ']['UTC'][XXX][X]", timezone="UTC")
private Instant effectiveDate;