pepote
pepote

Reputation: 313

Why am i getting the error "Unparseable date" from SimpleDateFormat?

Im trying to parse a Date-String without timezone to a new Date with time-Zone but im getting the error:
java.text.ParseException: Unparseable date: "2017-11-17 10:49:39.772 "

Here´s my code:

 String date = "2017-11-17 10:49:39.772 "
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
 sdf.setTimeZone(TimeZone.getTimeZone("Europe/Amsterdam"));
 sdf.parse(date);  //here´s the error
 return date.getTime();

Any suggestions?

Upvotes: 0

Views: 1363

Answers (3)

Anonymous
Anonymous

Reputation: 86324

Your question has been answered already. I just wanted to contribute the modern version of your code.

java.time

Your are using the long outdated classes SimpleDateFormat and Date. java.time, the modern Java date and time API also known as JSR-310 is generally so much nicer to work with. In your particular case the code is pretty similar:

    String date = "2017-11-17 10:49:39.772 ";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS ");
    ZoneId zid = ZoneId.of("Europe/Amsterdam");
    ZonedDateTime zdt = LocalDateTime.parse(date, dtf).atZone(zid);
    System.out.println(zdt);

This prints

2017-11-17T10:49:39.772+01:00[Europe/Amsterdam]

I need not repeat what @DarrenW already said: when your input string ends in a space and no time offset, then your format pattern string should also end in a space and no Z since Z matches an offset from UTC (now I repeated it anyway).

Contrary to a Date a ZonedDateTime has a time zone in it (as the name says), so I was thinking this might fit your requirements better.

Getting milliseconds from the epoch

It may be speculation: your call date.getTime() gave me the impression that you’re after the number of milliseconds since January 1, 1970, 00:00:00 GMT (the “epoch”). If so, do:

    long millisSinceEpoch = zdt.toInstant().toEpochMilli();

The result is

1510912179772

Parsing with a time zone offest in the string

More speculation, I could not help thinking that what just might have happened was that you received a date-time string that matched your format pattern string, but with an incorrect time zone offset in, which you stripped off, leaving the dangling space in the end of your string. If this was the case, the modern API can handle the situation more easily and elegantly by just ignoring the incorrect offset while parsing:

    String date = "2017-11-17 10:49:39.772 +0000";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS Z");
    ZoneId zid = ZoneId.of("Europe/Amsterdam");
    ZonedDateTime zdt = LocalDateTime.parse(date, dtf).atZone(zid);

The result is 2017-11-17T10:49:39.772+01:00[Europe/Amsterdam] again, exactly the same as from the first snippet above. LocalDateTime is a date and time without any time zone or offset information, so there is no way the incorrect offset from the string could come through. And anyway atZone() still sets the correct time zone.

Another way to obtain the same would be to parse right into a ZonedDateDate and then call its withZoneSameLocal() to get rid of the unwanted offset.

Upvotes: 2

DarrenW
DarrenW

Reputation: 85

If you want the string to be parsed correctly it must match the SimpleDateFormat pattern you supplied in the constructor:

Old line:

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

New line:

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

Upvotes: 1

Piotr Wilkin
Piotr Wilkin

Reputation: 3501

You explicitly said in your SimpleDateFormat that you require a timezone offset at the end (the Z parameter), yet your string is missing the offset. You'd need something like +0000 at the end.

Upvotes: 1

Related Questions