Wrong Output for java.text.SimpleDateFormat while Reading "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ"

StackOverflow https://stackoverflow.com/questions/21235279

Frage

I was trying to convert the date in String format into java.util.Date by using java.text.SimpleDateFormat, however it's not giving me the right output. Please help!

My input is generated by Django date: ex. "2014-01-20T07:17:06.150995+00:00"

But, I got "Mon Jan 20 15:19:36 GMT+08:00 2014" instead of "Mon Jan 20 15:17:06 GMT+08:00 2014"

Here's my testing code:

String s = "2014-01-20T07:17:06.150995+00:00";

SimpleDateFormat sdf;
String fmt = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ";
sdf = new SimpleDateFormat(fmt, Locale.US);

String result = "";
try {
    Date date = sdf.parse(s);
    Log.d(Constants.LOG_TAG, date.toString());
    result = date.toString();
} catch (Exception e) {
    Log.d(Constants.LOG_TAG, "date formatting error" + e.getMessage());
}
Log.d(Constants.LOG_TAG, "date test >> " + result);
War es hilfreich?

Lösung

As you can see your two dates differ by 2.5 minutes.

This happens because you are parsing microseconds as milliseconds. This will add 150000 milliseconds to your result, or 2.5 minutes.

There is no standard way to parse a date string with microseconds using SimpleDateFormat, you will have to do it yourself if you can't get the source string in a different format.

If the date is always in exactly this format you could do something like:

String dateWithoutMicros = s.substring(0, s.length() - 9) + s.substring(s.length() - 6);
Date date = sdf.parse(dateWithoutMicros);

Andere Tipps

As I first tried to run your Code (replaced Log.d with System.out.println()) i got a ParseException: Unparseable date.

Next I tried several parts of the date with their respective format string parts. Lastly the problem was the timezone part "+00:00" respectively "ZZZZZ".

I read about the pattern letters in the documentation (http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) and found:
Z -> -0800
X -> 08; -0800; -08:00
So swapped your ZZZZZ with X and then it worked fine for me. Final format string:
String fmt = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSX";

Avoid using the java.util.Date & .Calendar and java.text.SimpleTextFormat classes. They are notoriously troublesome.

Joda-Time

Using the third-party open-source Joda-Time 2.3 library, you can pass that ISO 8601 formatted string directly to a constructor. No need for formatters and parsers.

However, like java.util.Date, Joda-Time has a resolution of milliseconds. So it can handle only the first 3 digits of your fraction of a second. Fortunately though, rather than through an exception, Joda-Time simply truncates (ignores) the latter extra fractional digits.

String s = "2014-01-20T07:17:06.150995+00:00";
DateTime dateTime = new DateTime( s );
System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime in UTC/GMT: " + dateTime.toDateTime( DateTimeZone.UTC ) );

When run…

dateTime: 2014-01-19T23:17:06.150-08:00
dateTime in UTC/GMT: 2014-01-20T07:17:06.150Z

java.time.* Classes

The new classes bundled with Java 8, in the java.time.* package, supplant the java.util.Date & .Calendar classes. They are inspired by Joda-Time but are entirely re-architected. JSR 310 defines these classes.

These new classes have a resolution of nanoseconds rather than milliseconds, so they can handle all six of your fractional digits. Like Joda-Time, they take an ISO 8601 string directly.

String s = "2014-01-20T07:17:06.150995+00:00";
ZonedDateTime zdt = ZonedDateTime.parse( s );

System.out.println( "zdt: " + zdt );

When run…

zdt: 2014-01-20T07:17:06.150995Z
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top