Not able to convert the string to date on Android

2020-05-03 12:13发布

问题:

I have obtained a string from an API in form of 2017-04-23T19:47:39+00:00 How do i convert it into date of format "2017-04-23T19:47:39-0000"?

I tried the following but it gave ParseException

String created_at_string = "2017-04-23T19:47:39+00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date created_at = sdf.parse(created_at_string);

Exception:

06-22 18:18:32.517 10396-10396/com.harit.abs W/System.err: java.text.ParseException: Unparseable date: ""2018-04-29T10:55:37+00:00""
        at java.text.DateFormat.parse(DateFormat.java:358)
        at com.harit.abs.Sync_Activity.bu(Sync_Activity.java:169)
        at com.harit.abs.Sync_Activity$2.onCompleted(Sync_Activity.java:118)
        at com.harit.abs.Sync_Activity$2.onCompleted(Sync_Activity.java:87)
        at com.koushikdutta.async.future.SimpleFuture.handleCallbackUnlocked(SimpleFuture.java:107)
        at com.koushikdutta.async.future.SimpleFuture.setComplete(SimpleFuture.java:141)
        at com.koushikdutta.async.future.SimpleFuture.setComplete(SimpleFuture.java:128)
        at com.koushikdutta.ion.IonRequestBuilder$1.run(IonRequestBuilder.java:246)
        at com.koushikdutta.async.AsyncServer$RunnableWrapper.run(AsyncServer.java:60)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)

Tried what is given in SimpleDateFormat with TimeZone Still getting the same parse Exception

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
String created_at_string = "2017-04-23T19:47:39+00:00";
Date created_at = sdf.parse(created_at_string);

回答1:

You don’t need to

The conversion you are asking about could easily be superfluous. You are asking for a string like 2017-04-23T19:47:39-0000. This string is in ISO 8601 format, the international standard format. So depending on your exact situation I would expect a string in ISO 8601 to be fine for you. The string you already got, 2017-04-23T19:47:39+00:00 is in ISO 8601 too! The standard allows for some variations, and one of them is that the colon in the offset is optional. So the first thing I think that you should do is to pass on the string you get and see if that works. In case it doesn’t, read on.

java.time

Your desired conversion goes so smoothly with java.time the modern Java date and time API:

    DateTimeFormatter formatterWithoutColon 
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssxx");
    String createdAtString = "2017-04-23T19:47:39+00:00";
    OffsetDateTime dateTime = OffsetDateTime.parse(createdAtString);
    String inDesiredFormat = dateTime.format(formatterWithoutColon);
    System.out.println(inDesiredFormat);

This prints the desired:

2017-04-23T19:47:39+0000

Please note that we didn’t even need a formatter for parsing the string. OffsetDateTime and many other classes of java.time parse ISO 8601 as their default. Since our requirements for the result are a bit more precise, we use a formatter here. xx gives us the offset without colon, for example +0000.

The Date class that you used is long outdated. So is SimpleDateFormat, and it’s notoriously troublesome too. I suggest you avoid those classes.

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

The hack

The change you require is very simple, you just want a colon removed. So another, not so nice, but basic and simple solution that doesn’t require ThreeTenABP is a regular expression:

    String inDesiredFormat = createdAtString.replaceFirst("([+-]\\d{2}):(\\d{2})$", "$1$2");

This gives the same result as above.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
  • Wikipedia article: ISO 8601


回答2:

Possibly you could try to set the locale,

SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);