2

I am trying to convert a String in the format of "Wed Jun 01 00:00:00 GMT-400 2016" to ISO8601 "2016-06-01T00:00:00.000Z". I am getting an error "Unparseable date". I am not sure what am I doing wrong.

    DateFormat startDate = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'GMT'Z yyyy", Locale.US);
    startDate.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));

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

    Date aParsedDate = null;
    try {
        // give the date in that format
        aParsedDate = (Date) startDate.parse(inputDateAsString);
        System.out.println(aParsedDate.toString());

        // convert Date to ISO8601
        String nowAsISO = formatter.format(aParsedDate);
        System.out.println("ISO date = " + nowAsISO);
        return nowAsISO;

    } catch (ParseException e) {
        e.printStackTrace();
    }
2
  • The problem is the offset - Z expects something like -0400 and you pass -400. I don't think there is an easy way to parse it without first modifying the input string. z (lower case) accepts the general time zone format which does not require the leading 0 but requires a : between the hours and the minutes... Commented Jul 4, 2016 at 13:09
  • Please do not use Date, Calendar and SimpleDateFormat, they're obsolete and troublesome. Here is why. Use classes from java.time. See the posted answer for more details. Commented May 16, 2021 at 15:28

1 Answer 1

2

java.time

The ISO 8601 standard for timezone offset is to represent the HOUR with two digits. The separator for the HOUR and the MINUTE is optional. The MINUTE is also optional when it is zero. However, in your date-time string, Wed Jun 01 00:00:00 GMT-400 2016, the HOUR is of only one digit.

There is no OOTB (Out-Of-The-Box) DateTimeFormatter defined for the pattern in which your date-time string, Wed Jun 01 00:00:00 GMT-400 2016 is. Luckily, java.time, the modern date-time API provides you with a way to define/build parsing/formatting types with complex patterns.

Demo:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .appendPattern("E MMM d H:m:s")
                                .appendLiteral(' ')
                                .appendZoneId()
                                .appendOffset("+Hmm", "")
                                .appendLiteral(' ')
                                .appendPattern("u")
                                .toFormatter(Locale.ENGLISH);
                                
        String strDateTime = "Wed Jun 01 00:00:00 GMT-400 2016";
        
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime, dtf);
        System.out.println(odt);
    }
}

Output:

2016-06-01T00:00-04:00

As you can see, for timezone offset, I have used the pattern, +Hmm (one digit for HOUR and two for MINUTE).

Learn more about the modern date-time API from Trail: Date Time.

Note that the legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

For any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:

Date date = Date.from(odt.toInstant());

* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.