3

I'm using the Guardian API to get recent news stories about football.

I want to show date and time info to the user, but not in the format the API throws it back to me.

When requesting webPublicationDate after querying http://content.guardianapis.com/search?page-size=10&section=football&show-tags=contributor&api-key=test I get the response in this format:

2017-06-22T16:18:04Z

Now, I want the date and time info in this format: e.g. Jun 21, 2017 and 16:18 or 4:18 pm.

While I basically know to format a Date object properly into this format:

/**
 * Return the formatted date string (i.e. "Mar 3, 1984") from a Date object.
 */
private String formatDate(Date dateObject) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("LLL dd, yyyy");
    return dateFormat.format(dateObject);
}

/**
 * Return the formatted date string (i.e. "4:30 PM") from a Date object.
 */
private String formatTime(Date dateObject) {
    SimpleDateFormat timeFormat = new SimpleDateFormat("h:mm a");
    return timeFormat.format(dateObject);
}

But I can't seem to convert the response I get into a Date object.

2 Answers2

2

You can format the text this way:

package com.mkyong.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestDateExample5 {

public static void main(String[] argv) {

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    String dateInString = "2014-10-05T15:23:01Z";

    try {

        Date date = formatter.parse(dateInString.replaceAll("Z$", "+0000"));
        System.out.println(date);

        System.out.println("time zone : " + TimeZone.getDefault().getID());
        System.out.println(formatter.format(date));

    } catch (ParseException e) {
        e.printStackTrace();
    }

}

}

Z suffix means UTC, java.util.SimpleDateFormat doesn’t parse it correctly, you need to replace the suffix Z with ‘+0000’.

Code from here: https://www.mkyong.com/java/how-to-convert-string-to-date-java/

Karim ElGhandour
  • 337
  • 3
  • 13
1

Instead of directly working with SimpleDateFormat (as this old API has lots of problems and design issues), you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To use it in Android, you'll also need the ThreeTenABP (more on how to use it here).

The main classes to be used are org.threeten.bp.ZonedDateTime (which can parse the date/time input) and org.threeten.bp.format.DateTimeFormatter (to control the output format).

If you are reading this field (2017-06-22T16:18:04Z) as a String, you can create a ZonedDateTime like this:

ZonedDateTime z = ZonedDateTime.parse("2017-06-22T16:18:04Z");

If you already have a java.util.Date object, you can convert it using org.threeten.bp.DateTimeUtils with a org.threeten.bp.ZoneOffset:

Date date = // get java.util.Date
ZonedDateTime z = DateTimeUtils.toInstant(date).atZone(ZoneOffset.UTC);

In the end, the ZonedDateTime object will have the webPublicationDate value.

To get the different output formats, just create one DateTimeFormatter for each format. In the examples below, I also use java.util.Locale class to make sure the month names are in English:

// for Mar 3, 1984
DateTimeFormatter f1 = DateTimeFormatter.ofPattern("MMM d, yyyy", Locale.ENGLISH);
// for 4:40 PM
DateTimeFormatter f2 = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
// for 16:18
DateTimeFormatter f3 = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);

System.out.println(f1.format(z)); // Jun 22, 2017
System.out.println(f2.format(z)); // 4:18 PM
System.out.println(f3.format(z)); // 16:18

The output is:

Jun 22, 2017
4:18 PM
16:18

Note that it uses the UTC timezone (the Z in 2017-06-22T16:18:04Z). If you want to display the date and time in another timezone, just use the org.threeten.bp.ZoneId class:

System.out.println(f3.format(z.withZoneSameInstant(ZoneId.of("Europe/London")))); // 17:18

The output is 17:18 (becase London is in summer time now).

Note that the API uses IANA timezones names (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin). Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard. To find the timezone that better suits each region, use the ZoneId.getAvailableZoneIds() method and check which one fits best for your use cases.


If you don't want to add another dependency to your project and use SimpleDateFormat, you do something similar (create one parser and 3 output formatters, and use English locale). Also don't forget to set the timezone - I'm using UTC below, but you can change it to whatever timezone you want.

// parse date
String dateInString = "2017-06-22T16:18:04Z";
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
Date date = parser.parse(dateInString);

// create output formatters (set timezone to UTC)
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat s1 = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
s1.setTimeZone(utc);
SimpleDateFormat s2 = new SimpleDateFormat("h:mm a", Locale.ENGLISH);
s2.setTimeZone(utc);
SimpleDateFormat s3 = new SimpleDateFormat("HH:mm", Locale.ENGLISH);
s3.setTimeZone(utc);

System.out.println(s1.format(date));
System.out.println(s2.format(date));
System.out.println(s3.format(date));

The output will be the same:

Jun 22, 2017
4:18 PM
16:18