2

I've got a silly problem, here's my code:

SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ",Locale.US);
System.out.println(dateFormat.format(new Date()));
try {
    wou.setDateStart(dateFormat.parse(date));
    wou.setDateEnd(dateFormat.parse(date));
} catch (ParseException e) {
    System.out.println(e.getCause() + " " + e.getMessage());
    e.printStackTrace();
}

the result is following:

Fri Jun 05 2015 15:34:29 GMT+0000

null Unparseable date: "Fri Jun 05 2015 17:30:00 GMT+0000"

What's wrong with my format? It outputs the current date in the same format as the date I want to parse, but keeps telling me that the date is unparseable...

I'm struggling that for over an hour and I'm completely lost...

EDIT:

I have no control over the date I need to parse (if I did, I would change it in a source to a format that I could consume)

Following code:

String date = request.getParameter("absencyDate");
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss z",Locale.US);
try {
    System.out.println(dateFormat.format(new Date()));
    System.out.println(date);
    System.out.println(dateFormat.parse(date));
} catch (ParseException e1) {

Produces same error:

Fri Jun 05 2015 16:09:15 GMT

Fri Jun 05 2015 12:30:00 GMT+0000

java.text.ParseException: Unparseable date: "Fri Jun 05 2015 12:30:00 GMT+0000"

khartvin
  • 551
  • 1
  • 7
  • 20
  • 1
    Works for me, assuming `date` is the result of `dateFormat.format(new Date())`. – Sotirios Delimanolis Jun 05 '15 at 15:48
  • 1
    Try trimming the double quotes. – DSF Jun 05 '15 at 15:49
  • Your code works if I assign the result of `dateFormat.format(new Date())` to `date`, but it doesn't work I directly use `"Fri Jun 05 2015 17:30:00 GMT+0000"` instead of `date`. I guess this happens due to the (in my point) wrong format of the time zone. Try to use `"EEE MMM dd yyyy HH:mm:ss z"` (without the uppercase *Z*). But it is interesting, the same `SimpleDateFormat ` can't read the stuff it formatted itself. – Tom Jun 05 '15 at 16:03
  • DSF - the quotes aren't part of the date, they appear only in the error message – khartvin Jun 05 '15 at 16:06
  • Tom - I've tried that. Actually I started from that syntax, but it didn't work, so I've added the uppercase `Z` – khartvin Jun 05 '15 at 16:07
  • Ah, the date that you get in your parameter is built incorrectly, with two time zones... – RealSkeptic Jun 05 '15 at 16:24
  • RealSkeptic - you suggest to trim the last 5 characters from it? – khartvin Jun 05 '15 at 16:29
  • If it ends with *"+0000"*, then you could do that, but the "real" solution should be the fix of that program, which creates these date strings. – Tom Jun 05 '15 at 16:32

2 Answers2

4

The problem is your use of zZ in the date format. It expects a simple name-based zone (z), followed by an RFC-822 zone (Z).

It works well if the default zone (or the zone set in the format) is not GMT, because then it just parses up to that point (matches the z), and then it parses the +0000 as the Z.

But when the zone is GMT, it actually tries to parse the part that follows it (+0000) as part of the z, because "GMT+hh:mm" is a valid zone for z, and that fails.

The date format appears deceivingly correct. But combining two timezone formats is not. It should either be a named time zone (which includes "GMT+00:00"), or an RFC 822 offset (which doesn't include the "GMT" designation).

Edit following OP edit

So you get your date parameter from somewhere, and they are sending it to you with a non-standard zone designation. GMT+0000 matches neither general time zone (should be GMT or GMT+00:00), RFC 822 time zone (should be +0000 without GMT), nor ISO 8601 time zone (should be +00 or +0000 or +00:00).

If you know that they will always be using GMT in their dates, I think the best you can do is:

"EEE MMM dd yyyy HH:mm:ss 'GMT'Z"

Which will take the GMT part as a literal string rather than a time zone designator, then interpret the time zone from whatever follows it.

Or if the source that generates that parameter is under your control, fix its format to use a proper time zone matching one of the standards.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • I've udated my question. I have already tried various combinations of `z` and `Z`'s, but none of them worked. – khartvin Jun 05 '15 at 16:20
  • Correct answer. Alternatively you could just delete the SPACE and "GMT" before parsing. `inputString.replace( " GMT" , "" ) ;` – Basil Bourque Jun 05 '15 at 16:58
  • thanks for explaining couple of things about thode date formats RealSkeptic. That helped me a lot. I've decided to trim last 5 chars from the input string, as i cannot be sure, that the timezone won't change someday. Funny fact - the date comes from a jQuery plugin called fullcalendar. It I'm not sure if there's been applied some weird formatting on default Date, or that's just some object of other type (I've heard it uses "Moment" objects)... – khartvin Jun 06 '15 at 20:07
0

java.time

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

Demo using modern date-time API:

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

public class Main {
    public static void main(String args[]) {
        String dateStr = "Fri Jun 05 2015 17:30:00 GMT+0000";
        
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .parseCaseInsensitive()
                                .appendPattern("EEE MMM d u H:m:s")
                                .appendLiteral(' ')
                                .appendZoneId()
                                .appendPattern("X")
                                .toFormatter(Locale.ENGLISH);
        
        ZonedDateTime zdt = ZonedDateTime.parse(dateStr, dtf);
        
        System.out.println(zdt);
    }
}

Output:

2015-06-05T17:30Z[GMT]

For any reason, if you need an object of java.util.Date from this object of ZonedDateTime, you can so as follows:

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

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


* 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110