Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing string to date: Illegal pattern character 'T'.

I need to parse a string to date in java. My string has the following format:

2014-09-17T12:00:44.0000000Z

but java throws the following exception when trying to parse such format... java.lang.IllegalArgumentException: Illegal pattern character 'T'.

Any ideas on how to parse that?

Thank you!

like image 992
mbezunartea Avatar asked Oct 16 '14 07:10

mbezunartea


3 Answers

Given your input of 2014-09-17T12:00:44.0000000Z, it is not sufficient to escape the letter T only. You also have to handle the trailing Z. But be aware, this Z is NOT a literal, but has the meaning of UTC+00:00 timezone offset according to ISO-8601-standard. So escaping Z is NOT correct.

SimpleDateFormat handles this special char Z by pattern symbol X. So the final solution looks like:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSX");
 Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
 System.out.println(d); // output: Wed Sep 17 14:00:44 CEST 2014

Note that the different clock time is right for timezone CEST (toString() uses system timezone), and that the result is equivalent to UTC-time 12:00:44. Furthermore, I had to insert seven symbols S in order to correctly process your input which pretends to have precision down to 100ns (although Java pre 8 can only process milliseconds).

like image 132
Meno Hochschild Avatar answered Sep 17 '22 13:09

Meno Hochschild


You have to escape the 'T' character:

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    format.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date parse = format.parse("2014-09-17T12:00:44.0000000Z");

Using Answer to: What is this date format? 2011-08-12T20:17:46.384Z

like image 22
Xavier Delamotte Avatar answered Sep 16 '22 13:09

Xavier Delamotte


java.time

It is time for the modern answer: always use java.time, the modern Java date and time API, for your date and time work. When this question was asked, java.time had been out with Java 8 for 7 months. Today (2020) no one should use the SimpleDateFormat class that appears to have been the trouble in the question. It is notoriously troublesome and long outdated.

Using java.time we need no explicit formatter:

    String str = "2014-09-17T12:00:44.0000000Z";
    Instant i = Instant.parse(str);
    System.out.println("As Instant: " + i);

Output is:

As Instant: 2014-09-17T12:00:44Z

Your format is ISO 8601 (link at the bottom). The classes of java.time generally parse ISO 8601 as their default and print ISO 8601 back from their toString methods. In ISO 8601 the fraction of second is optional.

If you need a Date object for a legacy API not yet upgraded to java.time:

    Date oldfashionedDate = Date.from(i);
    System.out.println("As old-fashioned Date: " + oldfashionedDate);

Output in my time zone:

As old-fashioned Date: Wed Sep 17 14:00:44 CEST 2014

Output will vary by time zone because Date.toString() confusingly takes the JVM’s default time zone and uses it for rendering the string.

What went wrong for you?

You haven’t shown us your code, but we can already tell that a couple of things are wrong:

  1. SimpleDateFormat cannot parse a string with 7 fractional digits on the seconds correctly. It supports only milliseconds, exactly three decimals.
  2. In your format pattern string you need to escape the literal T by enclosing it in single quotes, 'T', or SimpleDateFormat will understand it as a pattern letter, and there is no format pattern letter T. This is what your exception message meant.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Wikipedia article: ISO 8601.
  • Related question: Date object SimpleDateFormat not parsing timestamp string correctly in Java (Android) environment about parsing more than three decimals on the seconds.
  • Related question: ISO 8601 String to Date/Time object in Android.
like image 37
Ole V.V. Avatar answered Sep 18 '22 13:09

Ole V.V.