简体   繁体   中英

java.text.ParseException: Unparseable date “yyyy-MM-dd'T'HH:mm:ss.SSSXXX” - SimpleDateFormat

I used the follow code to parse datetime :

String parseDate(String tranDateTime, String originalDateFormat, String toDateFormat) throws ParseException {
    SimpleDateFormat originalMonthYear = new SimpleDateFormat(originalDateFormat);
    Date date = originalMonthYear.parse(tranDateTime);

    SimpleDateFormat formatter = new SimpleDateFormat(toDateFormat);
    return formatter.format(date);
}

And tried to parse a datetime value as below :

parseDate("2017-08-16T00:00:00Z", 
          "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", "yyyy-MM-dd HH:mm:ss");

An exception is thrown :

java.text.ParseException: Unparseable date: "2017-08-16T00:00:00Z"

However, when I change date value to "2017-08-16T02:54:15.537Z" , the function worked fine. I don't know why.

The problem is coming from :

Date date = originalMonthYear.parse(tranDateTime);

This date

2017-08-16T00:00:00Z

Doesn't match the pattern

yyyy-MM-dd'T'HH:mm:ss.SSSXXX

Because milliseconds are missing ( SSS part)

So

Date date = originalMonthYear.parse(tranDateTime);

Throws the exception

java.text.ParseException: Unparseable date: "2017-08-16T00:00:00Z"

Solutions

  • Change your date 2017-08-16T00:00:00Z into 2017-08-16T00:00:00.000Z (add milliseconds to your date)
  • Change your pattern yyyy-MM-dd'T'HH:mm:ss.SSSXXX into yyyy-MM-dd'T'HH:mm:ssXXX (remove milliseconds from your pattern)

You asked in a comment:

Moreover, the datetime value could be "2017-08-16T00:00:00Z" or "2017-08-16T00:00:15.537Z" retrieved from database. Do we have a general pattern to parse both formats?

Even better, they can both be parsed without an explicit pattern:

    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:00Z"));
    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:15.537Z"));

This prints:

2017-08-16T00:00Z
2017-08-16T00:00:15.537Z

To format, for example:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:00Z").format(formatter));

This prints

2017-08-16 00:00:00

I am using and warmly recommending java.time , the modern Java date and time API. SimpleDateFormat and Date are long outmoded and the former in particular notoriously troublesome. The modern API is so much nicer to work with.

Your strings (in spite of differences) both conform to ISO 8601, the standard for date and time formats. The java.time classes parse these formats without any explicit formatter.

Link: Oracle tutorial: Date Time explaining how to use java.time

2017-08-16T00:00:00Z更改为2017-08-16T00:00:00.000Z ,对我2017-08-16T00:00:00.000Z

Problem source :

The problem come from trying to pars date value 2017-08-16T00:00:00Z with a date format yyyy-MM-dd'T'HH:mm:ss.SSSXXX , in the line :

Date date = originalMonthYear.parse(tranDateTime);

See the difference between the value and format:

 ______________________________
|2017|08|16| T |00|00|00Z      |
|yyyy|MM|dd|'T'|HH|mm|ss.SSSXXX|
|____|__|__|___|__|__|_________|

Solution :

Simple one is :

Date date = originalMonthYear.parse("2017-08-16T00:00:00.000Z")

But, if you will get many differents formats, you can use something like ( never tested ):

List<SimpleDateFormat> myUsedPatterns = new ArrayList<>();

myUsedPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
myUsedPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"));

for (SimpleDateFormat myPattern : myUsedPatterns) {
    try {
        SimpleDateFormat originalMonthYear = new SimpleDateFormat(myPattern );
        Date date = originalMonthYear.parse(tranDateTime);

        SimpleDateFormat formatter = new SimpleDateFormat(toDateFormat);
        return formatter.format(date);

    } catch (ParseException e) {
        // Loop
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM