How to convert UTC Date String and remove the T and Z in Java?

PacificNW_Lover picture PacificNW_Lover · May 24, 2018 · Viewed 29.2k times · Source

Am using Java 1.7.

Trying to convert:

2018-05-23T23:18:31.000Z 

into

2018-05-23 23:18:31

DateUtils class:

public class DateUtils {

    public static String convertToNewFormat(String dateStr) throws ParseException {
        TimeZone utc = TimeZone.getTimeZone("UTC");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        sdf.setTimeZone(utc);
        Date convertedDate = sdf.parse(dateStr);
        return convertedDate.toString();
    }
}

When trying to use it:

String convertedDate = DateUtils.convertToNewFormat("2018-05-23T23:18:31.000Z");
System.out.println(convertedDate);

Get the following exception:

Exception in thread "main" java.text.ParseException: Unparseable date: "2018-05-23T23:22:16.000Z"
   at java.text.DateFormat.parse(DateFormat.java:366)
   at com.myapp.utils.DateUtils.convertToNewFormat(DateUtils.java:7)

What am I possibly doing wrong?

Is there an easier way to do is (e.g. Apache Commons lib)?

Answer

Basil Bourque picture Basil Bourque · May 24, 2018

tl;dr

Instant.parse( "2018-05-23T23:18:31.000Z" )                // Parse this String in standard ISO 8601 format as a `Instant`, a point on the timeline in UTC. The `Z` means UTC.
.atOffset( ZoneOffset.UTC )                                // Change from `Instant` to the more flexible `OffsetDateTime`.
.format(                                                   // Generate a String representing the value of this `OffsetDateTime` object.
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )   // Specify a formatting pattern as desired.
)                                                          // Returns a `String` object.

2018-05-23 23:18:31

ISO 8601

Your input string is in standard ISO 8601 format.

The java.time classes use these standard formats by default when parsing/generating strings.

The T separates the year-month-day portion from the hour-minute-second. The Z is pronounced Zulu and means UTC.

java.time

You are using troublesome old date-time classes that were supplanted years ago by the java.time classes. The Apache DateUtils is also no longer needed, as you will find its functionality in java.time as well.

Parse that input string as a Instant object. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

String input = "2018-05-23T23:18:31.000Z" ;
Instant instant = Instant.parse( input ) ;

To generate a string in another format, we need a more flexible object. The Instant class is meant to be a basic building block. Lets convert it to a OffsetDateTime`, using UTC itself as the specified offset-from-UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 

Define a formatting pattern to match your desired output.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) ;
String output = odt.format( f ) ;

Tip: Consider using DateTimeFormatter::ofLocalized… methods to automatically localize the String generation per some Locale rather than hard-coding a formatting pattern.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?