0

I'm getting a ParseException while parsing a date from String to Date object. The date string also contains a timezone. I'm using this code:

final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
System.out.print(sdf.parse("2018-01-16T00:07:00.000+05:30"));

Below is the error I'm getting:

Exception in thread "main" java.text.ParseException: Unparseable date: "2018-01-16T00:07:00.000+05:30"
    at java.text.DateFormat.parse(DateFormat.java:366)
wss
  • 70
  • 4
user2142786
  • 1,484
  • 9
  • 41
  • 74
  • what about the TO that exists between the date string??? you need to cater it too. – Farhan Qasim Jan 30 '18 at 09:36
  • 2
    Well ... Does the parsed string follow the same format as the format specifier? – Seelenvirtuose Jan 30 '18 at 09:38
  • 2
    This exception happened because you are not matching the date you want to parse. – Antoine Dubuis Jan 30 '18 at 09:40
  • Try the answers provided in this link: https://stackoverflow.com/questions/17692863/converting-string-in-t-z-format-to-date – srp321 Jan 30 '18 at 10:06
  • I recommend that in 2018 you stay away from the long outdated and notoriously troublesome `SimpleDateFormat` and friends. [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) is so much nicer to work with. – Ole V.V. Jan 30 '18 at 11:11
  • 1
    @srp321, the answers found in the question you link to use `SimpleDateFormat` too, I recommend you avoid that and use `java.time` instead. See the modern and easy solution in [the answer by Laurent B](https://stackoverflow.com/a/48518250/5772882). – Ole V.V. Jan 30 '18 at 11:58
  • @OleV.V. i wasn't sure if OP was using java 8, so i suggested as per the usage he already had implemented, and thanks for recommending, in scenarios when i have Java 8 available, i use java.time utilities. – srp321 Jan 30 '18 at 12:03
  • Possible duplicate of [Java string to date conversion](https://stackoverflow.com/questions/4216745/java-string-to-date-conversion) – Tom Jan 31 '18 at 13:21

3 Answers3

4

The format you use in SimpleDateFormat must match the input String.

Your input is 2018-01-16T00:07:00.000+05:30, which is ISO8601 compliant:

  • year-month-day (2018-01-16)
  • followed by the letter T
  • followed by hour:minutes:seconds.milliseconds (00:07:00.000)
  • followed by the UTC offset (+05:30)

Note: the offset +05:30 is not a timezone. Read this to know the difference.

Anyway, the pattern you're using ("yyyy-MM-dd HH:mm:ss z") doesn't match the input string:

  • it's missing the T between date and time
  • it's missing the milliseconds
  • there's a space before the offset
  • the correct letter to parse offsets is X (although I think that z might work, depending on the JVM version you're using; in my tests, it didn't)

So your code should be:

// use "XXX" to parse the whole offset (only one "X" will parse just `+05`, missing the `:30` part)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date d = sdf.parse("2018-01-16T00:07:00.000+05:30");

But it's much better to use the new Java 8 classes, if they're available to you:

// parse ISO8601 compliant string directly
OffsetDateTime odt = OffsetDateTime.parse("2018-01-16T00:07:00.000+05:30");

If you still need to use a java.util.Date object, it's easy to convert:

// convert to java.util.Date
Date date = Date.from(odt.toInstant());
wss
  • 70
  • 4
  • Very well explained answer, thanks. Agree to use the Java 8 classes. New? Only four years old. :-) Available in Java 6 and 7 too through the [ThreeTen Backport](http://www.threeten.org/threetenbp/). – Ole V.V. Jan 31 '18 at 15:17
1

Your are using an ISO 8601 date.

Using SimpleDateFormat :

final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'SSSX");
System.out.print(sdf.parse("2018-01-16T00:07:00.000+05:30"));

Alertnatively, you can use the build in ISO 8601 parsing provided :

Using joda time Instant:

Instant.parse("2018-01-16T00:07:00.000+05:30")

JAVA 8 : (prefered see comment below)

https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html#parse-java.lang.CharSequence-

    System.out.println(java.time.OffsetDateTime.parse(s));
Laurent B
  • 2,200
  • 19
  • 29
  • 1
    Instant.parse("2018-01-16T00:07:00.000+05:30") doesn't work, it throws java.time.format.DateTimeParseException – Rahul Jan 30 '18 at 10:01
  • 1
    @Rahul edited as it worked with joda but java 8 Instant does not support timezones, you have to use OffsetDateTime – Laurent B Jan 30 '18 at 10:12
  • 1
    It’s preferred to use the Java 8 solution. Joda-Time is in maintenance mode, and `SimpleDateFormat` long outdated and notoriously troublesome. If using Java 6 or 7, consider adding [ThreeTen Backport](http://www.threeten.org/threetenbp/) to your project so you can use the Java 8 solution. – Ole V.V. Jan 30 '18 at 11:14
1

Change the following:

final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
          System.out.print(sdf.parse("2018-01-16 0:07:00 +0530"));

You are trying to parse z which stands for General time zone eg GMT IST etc but you need Z zone-offset like +0530 for India.Also remove the OT between the string. Your date format should match with the pattern. Refer https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Akshay
  • 1,161
  • 1
  • 12
  • 33
  • 1
    RFC 822 is the ARPA Internet Text Messages specification. The format OP is using is correct according to the ISO 8601 – Laurent B Jan 30 '18 at 09:58
  • @LaurentB see my edit..z time-zone name zone-name Pacific Standard Time; PST while Z zone-offset offset-Z +0000; -0800; -08:00; is what I am trying to say..which is just another approach to solve the problem – Akshay Jan 30 '18 at 10:02