5

I'm trying to convert this to a readable format however, keep getting java.text.ParseException: Unparseable date: "2016-11-18T11:13:43.838Z" (at offset 23)

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
try {
    Date date1 = df.parse("2016-11-18T11:13:43.838Z");

    DateFormat outputFormatter1 = new SimpleDateFormat("dd-MMM-yyyy");
    String output1 = outputFormatter1.format(date1); //
} catch (ParseException e) {
    e.printStackTrace();
}

I read about adding locale as other SO answers suggested but it is still not working.

6
  • Put the Z in single quotes in your SimpleDateFormat. Like this: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); Commented May 2, 2017 at 11:56
  • you are missing the timezone.... Commented May 2, 2017 at 11:58
  • 2
    @ΦXocę웃Пepeúpaツ He does have a timezone. Z is the zero timezone, equivalent to +0000. Commented May 2, 2017 at 12:17
  • Possible duplicate of ISO 8601 String to Date/Time object in Android Commented Jan 14, 2019 at 11:34
  • I recommend that you use java.time, the modern Java date and time API, for your date and time work. See the good answer by Arvind Kumar Avinash. SimpleDateFormat and DateFormat had tons of problems, and Date was poorly designed too. Fortunately they are all long outdated. Commented Dec 20, 2024 at 9:49

5 Answers 5

6

you are parsing a string that is not a correct representation of that pattern, you are missing the TimeZone... something like: -0600

example:

Date date1 = df.parse("2016-11-18T11:13:43.838-0600Z");

here is the doc for more info....

your code should look like:

    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    try {
        Date date1 = df.parse("2016-11-18T11:13:43.838-0600Z");
        DateFormat outputFormatter1 = new SimpleDateFormat("dd-MMM-yyyy");
        String output1 = outputFormatter1.format(date1); //
    } catch (ParseException e) {
        e.printStackTrace();
    }
Sign up to request clarification or add additional context in comments.

2 Comments

This is the only thing that worked. The solution was to change how the back-end is saving date so I can format it on allowable patterns by SimpleDateFormat. Unless someone can provide a solution without changing the value of date returned by the api call, I think this is the best answer.
@Woppi -0600 is not the same as Z (=+0000). So if you change the input like that via string preprocessing you will get another result. If your JVM is too old (before Java-7 no support for X-pattern) then you should rather replace "Z" by "+0000" (or even "+00:00").
6

According to the docs the Z in your format string indicates an RFC 822 time zone e.g. +01:00. You need to parse a ISO 8601 Time zone (the Z in your input string indicating UTC timezone). You configure that with X:

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

1 Comment

Hello, I tried X but getting "java.lang.IllegalArgumentException: Unknown pattern character 'X' at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:314)". BTW, I am using this in Android app and I just realize the pattern saved on our mongodb is not supported in android developer.android.com/reference/java/text/SimpleDateFormat.html
2

Reading the Javadoc for SimpleDateFormat, I found that using Z for timezone is very strict. It will not recognize "Z" as zulu, it only accepts numeric timezone offsets. You might want to try X instead, which accept "Z" according to the documentation.

Comments

1

java.time

In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy java.util date-time API. Any new code should use the java.time API. Given below is a solution using modern date-time API:

You do not need a DateTimeFormatter

Your date-time string is in ISO 8601 format, which is also the format that java.time types use by default. So, you do not need to use a DateTimeFormatter explicitly e.g.

Instant instant = Instant.parse("2016-11-18T11:13:43.838Z");
ZonedDateTime zdt = ZonedDateTime.parse("2016-11-18T11:13:43.838Z");
OffsetDateTime odt = OffsetDateTime.parse("2016-11-18T11:13:43.838Z");

Demo:

class Main {
    public static void main(String args[]) {
        ZonedDateTime zdt = ZonedDateTime.parse("2016-11-18T11:13:43.838Z");
        System.out.println(zdt);

        // String representation in a custom format
        String formatted = zdt.format(
                DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.ENGLISH));
        System.out.println(formatted);
    }
}    

Output:

2016-11-18T11:13:43.838Z
18-Nov-2016

Online Demo

Some important points:

  1. If for some reason, you need an instance of java.util.Date, let java.time API do the heavy lifting of parsing your date-time string and convert zdt from the above code into a java.util.Date instance using Date.from(zdt.toInstant()).
  2. Z denotes zero time zone offset i.e. a time zone offset of +00:00 hours.

What symbol should I use to parse a zone offset string?

You should use X to parse the zone offset in an offset-date-time string that is not in the default format.

Example of zone offset format Pattern
-08 X
-0830 XX
-08:30 XXX
-08:30:15 XXXXX

So, to parse the time zone offset of Z (or +00:00) in an offset date-time string, which is not in the default format of OffsetDateTime, you should use the symbol X. Check the documentation to learn more about it.

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

Some useful links:

  1. Check the answers mentioned in this comment.
  2. Always specify a Locale with a date-time formatter for custom formats.
  3. Check this answer and this answer to learn how to use java.time API with JDBC.

Comments

0

Please try this format

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

2 Comments

Incorrect answer. The Z in the string to parse is a UTC offset of 0. When you ignore it, you aren’t getting the correct time.
Yes, correct solutions here and here.

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.