7

I am getting ParseException for the following code

    String dateStr = "2011-12-22 10:56:24.389362";
    String formatStr = "yyyy-MM-dd HH:mm:ss.SSSSSS";
    Date testDate = null;
    SimpleDateFormat sdf= new SimpleDateFormat(formatStr);
    sdf.setLenient(false);
    testDate = sdf.parse(dateStr);

    System.out.println("CHECK DATE " + sdf.format(testDate));

Exception in thread "main" java.text.ParseException: Unparseable date: "2011-12-22 10:56:24.389362" at java.text.DateFormat.parse(DateFormat.java:337)

If I comment out the line sdf.setLenient(false), then I see a time difference in the ouput CHECK DATE 2011-12-22 11:02:53.000362

What am I doing wrong??

Praneeth
  • 1,457
  • 5
  • 23
  • 36

5 Answers5

8

'S' is for millisecond. There are 1000 (0 to 999) milliseconds in a second. 389362 is greater than 999. The extra 389000 milliseconds are getting converted to 389 seconds, or 6 minutes 29 seconds and added to the time.

Skip Head
  • 7,580
  • 1
  • 30
  • 34
  • What should be the pattern to allow 389362? – Praneeth Dec 22 '11 at 17:50
  • Milliseconds are the shortest time allowed. You need to change the input so it only goes to three decimal digits '389' in the example, and the format ends in '.SSS' – Skip Head Dec 22 '11 at 17:56
  • Thanks. Either I need to change my input to three decimal digits or I need to write my own parser that allows micro seconds as per @GrailsGuy – Praneeth Dec 22 '11 at 18:01
5

The S format specifier refers to milliseconds. When you allow lenient parsing, the last part is interpreted as 389362 milliseconds. When that's added to the date so far, the last 3 digits (actually, the value % 1000) become the actual milliseconds, and you wind up with a date about 389 seconds (~6 1/2 minutes) later than you're expecting. (With strict parsing, the parser knows that 389362 milliseconds doesn't make sense, so it throws an error.)

The simplest way around that, if you can guarantee the date will always look like that, would be to chop the last 3 digits off. (This will about half the time give you a date that's off by a millisecond. But that's better than having to write a date parser...)

cHao
  • 84,970
  • 20
  • 145
  • 172
3

Your date input for milliseconds is incorrect. It should be:-

String dateStr = "2011-12-22 10:56:24.389";

You also do not need the extra number of "S"s in the pattern. The following should suffice:

String formatStr = "yyyy-MM-dd HH:mm:ss.S";

It is clearly mentioned in the java docs for presentation type of Number:

Number: For formatting, the number of pattern letters is the minimum number of digits, and shorter numbers are zero-padded to this amount. For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.

It works when you set lenient to be true (or comment out the line which defaults it true) since you are asking the parser to be not strict about the parsing. From java docs on setLenient():-

Specify whether or not date/time parsing is to be lenient. With lenient parsing, the parser may use heuristics to interpret inputs that do not precisely match this object's format. With strict parsing, inputs must match this object's format.

CoolBeans
  • 20,654
  • 10
  • 86
  • 101
2

S is only to be used for milliseconds. If you want microseconds, you will have to write your own parser.

Igor
  • 33,276
  • 14
  • 79
  • 112
0

Use toISOString('HH:mm:ss.S') to get milliseconds (3 digits), then complete as you need with 0.

For example:

new Date().toISOString('HH:mm:ss.S')

returns "2012-02-10T12:16:39.124Z"

Milton
  • 928
  • 1
  • 10
  • 22