Cannot parse date string coming from MongoDB in Android/Java Cannot parse date string coming from MongoDB in Android/Java mongodb mongodb

Cannot parse date string coming from MongoDB in Android/Java


Your pattern accepts only second digits but your string has fractional seconds as well

yyyy-MM-dd'T'HH:mm:ss    'Z'2015-06-25 T 00:00:00.000 Z

You need to use

"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 


Do not ignore the Z

Your formatting pattern has single quote marks around the Z. That means to interpret the "Z" as mere text, to expect it but then ignore it. Very bad, as that Z has meaning: short for Zulu, and means UTC time zone.

By ignoring the Z, parsing will implicitly apply your JVM’s current default time zone. Your input meant the first moment of the day in UTC (stroke of midnight), but in the following code you can see the value is mis-interpreted as midnight in my default zone of America/Los_Angeles -- an error of 7 hours (my zone’s current offset from UTC).

try {    java.text.DateFormat format = new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss'Z'" , Locale.ENGLISH );    java.util.Date date = format.parse ( "2015-06-25T00:00:00Z" );    System.out.println ( "date: " + date );} catch ( ParseException e ) {    e.printStackTrace ();}

In this output, PDT means the Daylight Saving Time (DST) version of Pacific time (more accurately named as America/Los_Angeles). Note the time is 00:00:00 but that is wrong -- should have been seven hours earlier on the previous day as my zone is behind UTC.

date: Thu Jun 25 00:00:00 PDT 2015

java.time

This work would be much easier with the java.time framework built into Java 8 and later. For Java 6 & 7, use the back-port, ThreeTen-Backport. For Android, the adaptation of that back-port, ThreeTenABP.

The java.time classes use ISO 8601 format by default when parsing/generating textual representations of date-time values. Your input happens to comply fully with ISO 8601. So no need to specify a formatting pattern.

An Instant is a moment on the timeline in UTC.

String input = "2015-06-25T00:00:00Z";Instant instant = Instant.parse ( input );

Apply a proper time zone name if desired.

ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );

Dump to console.

System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );

input: 2015-06-25T00:00:00Z | instant: 2015-06-25T00:00:00Z | zdt: 2015-06-24T17:00-07:00[America/Los_Angeles]

Note how in this output, the same input is now correctly adjusted to my America/Los_Angeles time zone by moving back seven hours into the previous date.

Convert to/from java.time

Avoid using java.util.Date. The old date-time classes really are that bad. But if required, you can convert between java.time types and the old types. In this case, by using the count-from-epoch in milliseconds. Be aware that you may lose a bit of data, going from the nanoseconds resolution to milliseconds in java.util.Date (not in this case, but perhaps in other cases).

java.util.Date utilDate = new java.util.Date( instant.toEpochMilli() );