16

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!

Raedwald
  • 46,613
  • 43
  • 151
  • 237
mbezunartea
  • 195
  • 1
  • 1
  • 7

4 Answers4

36

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

Rockstar
  • 2,228
  • 3
  • 20
  • 39
Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
  • but one comment, you need to replace last X character with 'Z' in constructor SimpleDateFormat. Good solution, worked for me – Victor Ponomarenko Nov 12 '15 at 10:09
  • @VictorPonomarenko The symbol letter X was introduced with Java 7. For Java 6, I am not sure if Z works as replacement meaning if parsed literal "Z" will be recognized as UTC+00! Maybe it is better to use the workaround for Java 6 to escape Z (interpreting it only as literal) AND to set the zone to "GMT" on the `SimpleDateFormat`-object. – Meno Hochschild Nov 12 '15 at 13:16
  • on android I get runtime exception, when leave X character, but after replacement to 'Z' works good(android now works on java 7) – Victor Ponomarenko Nov 12 '15 at 16:58
  • @VictorPonomarenko Z seems to be the right symbol for [Android](http://developer.android.com/reference/java/text/SimpleDateFormat.html) although the doc is not very detailed, but keep also in mind: Android != Java (and the `SimpleDateFormat`-APIs are really different in both worlds). – Meno Hochschild Nov 12 '15 at 19:57
15

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

Community
  • 1
  • 1
Xavier Delamotte
  • 3,519
  • 19
  • 30
  • Thanks for your answer, now I don't get the same exception, but this one: "java.text.ParseException: Unparseable date: "Date"". I think the Date Format is not yet well defined... – mbezunartea Oct 16 '14 at 07:46
3

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

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
2

Try this.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateClass {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
        System.out.println(d); //output Wed Sep 17 12:00:44 IST 2014
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122