-1

I have a requirement in which I need to render localised datetime on a text view in an Android layout. The date time is returned in an ISO format from a service call. Here is the response JSON

{
   "expiredTime": "2020-01-24T00:59:59.000-05:00",
  . . . Other Keys and Values . . .
}

This is to be rendered in an Android app inside a text view. What I want to do is show the localised time on the app. So If the user were to view in the screen in say New York, the expired time would show 2020-01-24T00:59:59.000-05:00 because the time in the payload belongs to the same time zone as NY. Similarly, if I wanted to display in GMT, the time would be shown as 2020-01-24T05:59:59.000-00:00.

How can I implement this correctly in Android? I have done this as shown below. The returned date is passed to a SimpleDateFormat instance to return a string.

public static final Date parse(String dateTimeAsString) throws ParseException
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME.withLocale(Locale.getDefault()));
            try
            {
                LocalDate localDate = LocalDate.parse(value, formatter);
                if (localDate != null)
                    return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            } catch (DateTimeParseException dtpe)
            {
                // If the format is invalid, then delegate to the other helper function.
            }
        }
        return null;
    }

My questions are as follows:

  1. Is my implementation to get the localised date correct? If not, how would I do it correctly?
  2. How do I localise the date for Android OS version below Oreo? DateTimeFormatter is only available in Android Oreo and up.
Kartik
  • 2,541
  • 2
  • 37
  • 59
  • You are really asking two questions in one: (1) How to parse ISO 8601 format? (2) How to display a date according to the user’s time zone? Each has been asked and answered before, so your search engine is your friend. – Ole V.V. Jan 16 '20 at 18:40
  • When you say localized, do you mean according to the user’s time zone or culture or both? Should the output for a French user in France be `2020-01-24T06:59:59.000+01:00` or something like `24 janvier 2020`? – Ole V.V. Jan 16 '20 at 18:43
  • @OleV.V. Basically Showing the date in Long Date format in the local time zone. – Kartik Jan 18 '20 at 00:07
  • For example, show the date as MM-DD-YY hh:mm:ss Z in US, but show it as DD-MM-YY hh:mm:ss Z in Europe for example. – Kartik Jan 18 '20 at 00:22
  • I think that you can get some of it from this question: [Convert date into AEST using java](https://stackoverflow.com/questions/48412345/convert-date-into-aest-using-java). Only since your UTC offset, `-05:00`, has a colon in it, you don’t need the formatter because your format is the default for `OffsetDateTime`. Parsing with just `OffsetDateTime.parse("2020-01-24T00:59:59.000-05:00")` should work. You may also search fore more helpful questions. – Ole V.V. Jan 18 '20 at 06:51

1 Answers1

1
public static final ZonedDateTime parse(String dateTimeAsString) {
    try {
        return OffsetDateTime.parse(dateTimeAsString).atZoneSameInstant(ZoneId.systemDefault());
    } catch (DateTimeParseException dtpe) {
        return delegateToOtherHelperFunction(dateTimeAsString);
    }
}

Example use:

    String expiredTime = "2020-01-24T00:59:59.000-05:00";
    System.out.println(parse(expiredTime));

Output in my time zone:

2020-01-24T06:59:59+01:00[Europe/Copenhagen]

For your questions:

  1. Is my implementation to get the localised date correct? If not, how would I do it correctly?

No, there are a couple of issues with your implementation. I applaud the use of java.time, the modern Java date and time API, though.

  • Returning a Date won’t give you the time in any particular time zone. A Date hasn’t got a time zone. It’s a point in time only.
  • A LocalDate is a date without time of day, so when using this class you are losing the time part.
  • Unimportant, DateTimeFormatter.ISO_DATE_TIME is the same in all locales, so applying a locale to it makes no difference.
  1. How do I localise the date for Android OS version below Oreo? DateTimeFormatter is only available in Android Oreo and up.

Use the backport. java.time has been backported from Java 8 to Java 6 and 7 and the backport further adapted to early Android API levels. See the links below. If you are writing an app to be supported on several OS versions, I suggest that you simply use the backport throughout (the backport works on high API levels too). I wrote the code above for the backport, so it will work. (I expect it to work on the built-in classes too, not tested).

A note on usage: in computing localized usually means adapted to users’ language (and partially their culture), their so-called locale, rather than to their time zone. Locale and time zone are orthogonal concepts.

Links

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