4

I have a method that gets data from REST server. The method returns the date in this format "2017-08-14T17:45:16.24Z". i also wrote a method that formats date in the order "dd/MM/yyyy". This works perfectly but when i try to format the date from the server and set the that to an Edittext it does not work. This shows shows that my method to format the date in the server response does not work. My method to format the date is below:

private String formatDate(String dateString) {
    try {
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS" );
        Date d = sd.parse(dateString);
        sd = new SimpleDateFormat("dd/MM/yyyy");
        return sd.format(d);
    } catch (ParseException e) {
    }
    return "";
}

This method below that gets the date from the server and formats the date and sets the date to an Edit-text.

public void getProfile() {

    Retrofit retrofit = RetrofitClient.getClient(authUser.getToken());
    APIService mAPIService = retrofit.create(APIService.class);

    mAPIService.getProfile("Bearer " + authUser.getToken()).enqueue(new Callback<Profile>() {
        @Override
        public void onResponse(Response<Profile> response, Retrofit retrofit) {
            if(response.isSuccess()) {
                try {
                    String loginSuccess = response.body().getSuccess();
                    if (loginSuccess.equals("true")) {
                        id_name.setText(response.body().getData().getName());
                        id_email.setText(response.body().getData().getEmail());
                        phone_input_layout.setText(response.body().getData().getPhoneNumber());
                        id_gender.setText(response.body().getData().getGender());
                        String dateOfBirth = response.body().getData().getDateOfBirth();
                        id_date_of_birth.setText(formatDate(dateOfBirth));
                        //updateLabel(dateOfBirth);
                        id_residential_address.setText(response.body().getData().getResidentialAddress());
                        if (response.body().getData().getEmploymentStatus().equals("Student")) {
                            id_nss_number.setVisibility(View.VISIBLE);
                            maximum_layout.setVisibility(View.INVISIBLE);
                            extended_layout.setVisibility(View.INVISIBLE);
                        } else if (response.body().getData().getEmploymentStatus().equals("Employed")) {
                            maximum_layout.setVisibility(View.VISIBLE);
                            extended_layout.setVisibility(View.INVISIBLE);
                            id_nss_number.setVisibility(View.INVISIBLE);
                            id_type.setText(response.body().getData().getIdType());
                            id_number.setText(response.body().getData().getIdNumber());
                            id_expiry_date.setText(response.body().getData().getIdExpiryDate());
                        }


                    } else {
                        String message = response.body().getMessage();
                        Log.e("getProfileError", message);
                        Toast.makeText(UserProfileActivity.this, message, Toast.LENGTH_LONG).show();
                    }
                }catch (Exception e){
                    Toast.makeText(getApplicationContext(), "Some fields are empty", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }

            }


        }

        @Override
        public void onFailure(Throwable throwable) {
            Log.e("getProfileError", throwable.getMessage());
            Toast.makeText(UserProfileActivity.this, "Unable to Login, Please Try Again", Toast.LENGTH_LONG).show();
        }
    });
}

this is the exception i get from the date format

I/dateError:: Unparseable date: "1988-11-09T00:00:00Z"
  • 3
    catch (ParseException e) { } hiding Exceptions is never a good idea, especially if something goes wrong, and you don't know what or why. Also, show your actual code: the code you posted will never compile, since you have a double declaraton of dateOfBirth – Stultuske Feb 15 '18 at 12:22
  • @Stultuske i have updated my question – Roxanne Akorley Feb 15 '18 at 12:40
  • what exception you get? – Zaid Mirza Feb 15 '18 at 12:43
  • I had no exception, but the edit text does not display any data @ZaidMirza – Roxanne Akorley Feb 15 '18 at 12:54
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Feb 15 '18 at 14:07
  • You are still swallowing the exception, so you can’t really know whether you get one. – Ole V.V. Feb 15 '18 at 14:15
  • 1
    @OleV.V. this is the exception i get from the date format I/dateError:: Unparseable date: "1988-11-09T00:00:00Z" (at offset 19) – Roxanne Akorley Feb 15 '18 at 14:27
  • Thanks. Please include this vital information in your question, where we can find it more easily than in the comment. – Ole V.V. Feb 15 '18 at 14:31
  • @OleV.V. sure thing would do that. – Roxanne Akorley Feb 15 '18 at 14:34

2 Answers2

0

Your desired format is

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

The last Z stands for "zero hour offset" also known as "Zulu time" (UTC).

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

With this UTC timezone, converted hour will be 20H.

If you don't add timezone you will have your expected hour 17H.

Cătălin Florescu
  • 5,012
  • 1
  • 25
  • 36
  • i still get the same issue. this doesn't solve my problem but the best way to format my date – Roxanne Akorley Feb 15 '18 at 13:06
  • This will not work as expected, as using the 'S' pattern char will map the value to number of milliseconds. The input example ("16.24") will be parsed as 16 seconds and 24 milliseconds, e.g. 16.024 seconds and not 16.24 seconds as expected. – jarnbjo Feb 15 '18 at 13:07
  • We assume that the expected input will be always the same. Also, if you will try to parse only `16.24` to that format, you will have an exception for sure. – Cătălin Florescu Feb 15 '18 at 13:18
  • @RoxanneAkorley I tried to format your date using my posted pattern and it works. Output: `Mon Aug 14 20:45:16 EEST 2017`. Now depends by your locale timezone or expected timezone. – Cătălin Florescu Feb 15 '18 at 13:19
  • @FlorescuCătălin but for some reason the method for formatting the date is not called in the method that gets the date from the server. The edit text does not display any data. – Roxanne Akorley Feb 15 '18 at 13:35
  • In your `formatDate` method, print your exception `e.printStackTrace()` and post your log. Maybe response is unsuccess or `loginSuccess.equals("true")` is false. – Cătălin Florescu Feb 15 '18 at 14:00
  • @FlorescuCătălin this is the error i get from my formatDate I/dateError:: Unparseable date: "1988-11-09T00:00:00Z" (at offset 19) – Roxanne Akorley Feb 15 '18 at 14:14
  • Well, that's another format. I assume that millis are `000` and server exclude them. In this case format is `yyyy-MM-dd'T'HH:mm:ss'Z'`, without `SSS` for millis. You can try to parse with this new format in first `catch`. – Cătălin Florescu Feb 15 '18 at 14:32
  • @FlorescuCătălin this format works for me..now my date is parsed perfectly. Update your answer so i choose it as the answer. – Roxanne Akorley Feb 15 '18 at 16:29
0

this is the error i get from my formatDate I/dateError:: Unparseable date: "1988-11-09T00:00:00Z" (at offset 19)

That date-time string has got no decimals on the second (and no decimal point). Offset 19 is where the Z is, and where the decimal point is in your format pattern string. This causes your exception.

java.time, the modern Java date and time API, will solve your problem easily:

private static final DateTimeFormatter dateFormatter
        = DateTimeFormatter.ofPattern("dd/MM/yyyy");

private static String formatDate(String dateString) {
    return Instant.parse(dateString)
            .atZone(ZoneId.of("Australia/Queensland"))
            .format(dateFormatter);
}

This will work with and without decimals on the seconds:

    System.out.println(formatDate("2017-08-14T17:45:16.24Z"));
    System.out.println(formatDate("1988-11-09T00:00:00Z"));

This prints

15/08/2017
09/11/1988

You may be surprised that the first line says the 15th of the month when the day-of-month in the string is 14. This is because when it is 17:45 in UTC, it is already the next day in Australia. I suppose you want the day in your user’s time zone. Therefore please substitute your desired time zone if it didn’t happen to be Australia/Queensland. If you do want the date in UTC, use this line instead of the atZone call:

            .atOffset(ZoneOffset.UTC) 

This will make sure you get the same date as in the string.

As a detail, the above code also parses your 0.24 seconds correctly. SimpleDateFormat understood 24 as 24 milliseconds, so you got 0.024 seconds instead, a slight inaccuracy. Another detail, I declared your method static, it’s not necessary, but we might as well.

Question: Can I use java.time on Android?

Yes, you can use java.time on Android. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices 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.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • how do i combine this with my date format method..sorry for asking this novice question – Roxanne Akorley Feb 15 '18 at 16:21
  • You’re very welcome. See my edit: you just substitute the code inside your method with mine. I also moved the formatter outside the method and added a few other details to the answer. – Ole V.V. Feb 15 '18 at 16:49