0

I am trying to parse the date-time string 2017-12-01 00:00:00+01. My pattern is as follows:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");

The exception “Unparseable date: "2017-12-01 00:00:00+01"” is thrown with Android 7 and above.

I found another pattern: "yyyy-MM-dd HH:mm:ssX" but it works only with Android 7 and above.

I tried this workaround "yyyy-MM-dd HH:mm:ssZZZZZ" that I found here, but it doesn't work.

Is there a solution that will also work with Android below Android 7?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
FakeLion
  • 147
  • 1
  • 1
  • 9
  • 1
    Try using a different library. http://www.threeten.org/threetenbp/ – OneCricketeer Jan 16 '18 at 19:48
  • That is not a valid format supported by [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat.html) on API < 24. Do take a look at [RFC 822 time zone format](https://developer.android.com/reference/java/text/SimpleDateFormat.html#rfc822timezone) and [ISO 8601 time zone format](https://developer.android.com/reference/java/text/SimpleDateFormat.html#iso8601timezone). – Srikar Reddy Jan 17 '18 at 06:19

2 Answers2

1

I will give you the good solution and the hack.

java.time

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ssX");
    OffsetDateTime dateTime = OffsetDateTime.parse(dateTimeString, formatter);
    System.out.println(dateTime);

This prints

2017-12-01T00:00+01:00

This is the good solution: java.time, the modern Java date and time API. There are at least two reasons why you would want to do this on Android.

  1. The SimpleDateFormat class that you have been using is not only long outdated, it is also notoriously troublesome, so I would recommend you don’t use it anyway, and the modern API is so much nicer to work with.
  2. Your time zone offset of +01 is an ISO 8601 offset. While only later vertsions of SimpleDateFormat can parse this, java.time has excelled at the ISO 8601 standard from when it came out, so this is a safe bet.

I should say you have a nice opportunity for going future-proof.

Your time of day of 00:00:00 seems to suggest you’re only interested in the date? If so, java.time has one more good offer for you, the LocalDate class represents a date without time of day:

    LocalDate date = dateTime.toLocalDate();

This gives a LocalDate of 2017-12-01.

The hack

You may just append minutes of offset of 00 to your string, and the formatter in your question will parse it:

    dateTimeString += "00";

Question: how do I use java.time on older Android?

If java.time is not built-in on your Android device, you get ThreeTenABP and add it to your project, and then import org.threeten.bp.OffsetDateTime, org.threeten.bp.LocalDate and org.threeten.bp.format.DateTimeFormatter. See the links below. The code is unchanged from above.

Links

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

The problem lies in the "+01" time zone suffix. This is not a valid representation of a time zone under either the "General time zone" rules or the "RFC 822 time zone" rules.

You can change your SimpleDateFormat to "yyyy-MM-dd HH:mm:ss", which will allow the date to be parsed but will ignore the time zone suffix. Then you can manually parse the time zone suffix and modify your Date accordingly.

Alternatively, if you can somehow change your input to include offset minutes in addition to hours (i.e. change the time zone suffix to "+0100"), then your existing date format will work just fine. Including minutes in addition to hours makes the time zone suffix parseable according to RFC 822.

Ben P.
  • 52,661
  • 6
  • 95
  • 123