0

I am trying to parse a date/time json from server side inside bind viewholder. The date string am trying to parse is this:

2018-06-25T08:06:52Z

Here is the code that I am using ( got it from another stack overflow thread)

  try {


           SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
           df.setTimeZone(TimeZone.getTimeZone("Africa/Nairobi"));
           Date date = df.parse(timeToConvert);
           df.setTimeZone(TimeZone.getDefault());
           String formattedDate = df.format(date);
           String trimmed = formattedDate.substring(11,16);
           myViewHolder.date_TV.setText(trimmed);

       }catch (Exception e){

       }

However this does not work, the time set to the text view is the same as before parsing.

Francis Ting
  • 671
  • 6
  • 15
  • 1
    From API level 26 you can use `java.time.Instant` and related classes. – Arnold Schrijver Jul 06 '18 at 08:57
  • 1
    https://developer.android.com/reference/java/time/Instant To fill the comment of Arnold – Itoun Jul 06 '18 at 09:03
  • As the previous comments suggest, 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. The modern `OffsetDateTime` will parse your string without any explicit formatter. Convert to you time zone, then to `LocalTime`, truncate to whole minutes, print and you’re done. – Ole V.V. Jul 06 '18 at 11:08
  • okay. Let me try that out. – Francis Ting Jul 06 '18 at 11:27

2 Answers2

2
    String timeToConvert = "2018-06-25T08:06:52Z";
    Instant inst = Instant.parse(timeToConvert);
    LocalTime time = inst.atZone(ZoneId.of("Africa/Nairobi"))
            .toLocalTime()
            .truncatedTo(ChronoUnit.MINUTES);
    System.out.println("Time in Nairobi: " + time);

This prints:

Time in Nairobi: 11:06

I am using java.time, in this case the backport to Java 6 and 7. This backport is available in an Android edition too, which you may use for low Android API levels. My imports are:

import org.threeten.bp.Instant;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.temporal.ChronoUnit;

If you need the time string for an API that requires this format, you’re fine. If you are after a time string for presentation to a user, consider using Java’s built-in format instead:

    DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
    ZonedDateTime dateTime = inst.atZone(ZoneId.of("Africa/Nairobi"));
    System.out.println("Formatted: " + dateTime.format(timeFormatter));

I tried running this in Swahili (sw_KE) locale and got:

Formatted: 11:06 AM

Apparently this locale uses the English AM/PM way of notating times (I got the same result in Kikuyu and Kalenjin locales). In UK locale I get the same format as before:

Formatted: 11:06

I am using and suggesting java.time, the modern Java date and time API. For anyone reading along and using Java 8 or later or programming for Android API level 26 or higher, you don’t need the backport mentioned. Just import the built-in date-time classes from java.time with subpackages instead of the above mentioned ones.

What went wrong in your code?

Your error comes from hardcoding the Z in the date-time string as a literal. It’s a UTC offset of zero, and when you don’t parse it as such, the date-time string will be parsed in the time zone of your SimpleDateFormat, Africa/Nairobi, which is incorrect for your string.

IMHO you shouldn’t want to use SimpleDateFormat, TimeZone and Date at all, though. Those classes are long outdated and the first in particular has proven troublesome. I always use java.time instead.

Another tip: Don’t swallow exceptions. Don’t leave your catch block empty. Report the exception in some noticeable way. This is your chance to discover when something goes wrong in your code.

Links

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

The time set to the text view is the same as before parsing.

This is because you're not passing in a new SimpleDateFormat.

Try this:

final String serverDate = "2018-06-25T08:06:52Z"
final SimpleDateFormat serverDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
final SimpleDateFormat yourDateFormat = new SimpleDateFormat("yyyy-MM-dd"); // put whatever you want here!

try {
    final Date date = serverDate.parse(serverDateFormat);
    final String formattedDate = yourDateFormat.format(date);
} catch (ParseException e) {
    System.out.println(e.toString());
}

This way you're interpreting the String with the server format into a pure Date object. You're then free to do what you wish with that object and turn it into whichever format you want (by providing your new format).

For more information on building your date format pattern, see this link.

vguzzi
  • 2,420
  • 2
  • 15
  • 19
  • Thanks but the serverDate.parse has an error...cannot resolve method parse(java.text.SimplDateFormat) – Francis Ting Jul 06 '18 at 12:00
  • It should be `final Date date = serverDateFormat.parse(serverDate);`. I suspect it doesn’t work correctly, though. It repeats the error of hardcoding the `Z` in the format pattern string as in the question. – Ole V.V. Jul 06 '18 at 15:56