0

I'm trying to parse a String to a Date Object, as part of a loading functionality for my program, as seen below:

    String dateString = "Wed Jan 18 23:22:18 EST 2017";
    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd hh:mm:ss zzz YYYY");
    try {
        Date scheduleItemDate = sdf.parse(dateString);
        System.out.println(scheduleItemDate.toString());
    }
    catch (ParseException e) {
        System.out.println("Exception");
    }

Although the date should be the same as in dateString above, the program prints out the following date:

    Wed Jan 04 23:22:18 EST 2017

The above date is basically two full weeks behind the original date, I'm not sure as to how I am getting this, anything I am doing wrong?

5
  • 1
    The hour should be HH, not hh - "h Hour in am/pm (1-12)" Commented May 7, 2017 at 3:49
  • And year should be yyyy not YYYY - "Y Week year" Commented May 7, 2017 at 3:51
  • the y thing fixes it. Commented May 7, 2017 at 3:52
  • 1
    Yeah, you guys were right, thanks so much! Commented May 7, 2017 at 3:52
  • 1
    What research did you do prior to asking? For example, it seems that this question: Java : Parsing Date String using SimpleDateFormat could have helped you. Commented May 7, 2017 at 9:00

2 Answers 2

7

The hour should be HH, not hh

h Hour in am/pm (1-12)

And year should be yyyy not YYYY

Y Week year

ALWAYS consult the JavaDocs first

String dateString = "Wed Jan 18 23:22:18 EST 2017";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
try {
    Date scheduleItemDate = sdf.parse(dateString);
    System.out.println(dateString);
    System.out.println(scheduleItemDate.toString());
    System.out.println(sdf.format(scheduleItemDate));
} catch (ParseException e) {
    System.out.println("Exception");
}

Which now prints...

Wed Jan 18 23:22:18 EST 2017
Wed Jan 18 23:22:18 EST 2017
Wed Jan 18 23:22:18 EST 2017
Sign up to request clarification or add additional context in comments.

3 Comments

Great explanation and reference link!
And for something like this, a good place to start is the examples in the javadoc page because reading these definitions one by one will make you become a hermit.
Thanks for the javadoc link! :)
1

TL;DR: the newer DateTimeFormatter and friends are somewhat more helpful in debugging issues like yours compared to the outdated SimpleDateFormat.

This is not the answer you were asking for, but it may be the answer you want. If there is any way you can (which there is), drop the outdated classes SimpleDateFormat and Date in favour of the modern ones in the java.time package. The way to do in your case isn’t much different from your code. PLEASE NOTE: I am deliberately including your error.

    String dateString = "Wed Jan 18 23:22:18 EST 2017";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss zzz YYYY"); // wrong
    try {
        ZonedDateTime scheduleItemDate = ZonedDateTime.parse(dateString, dtf);
        System.out.println(scheduleItemDate.toString());
    }
    catch (DateTimeParseException e) {
        System.out.println("Exception");
    }

The output is different, though: the above snippet prints

Exception

I am serious when I say I consider this an improvement. There was a bug in your program all the time, and now the program tells you there is bug. On my computer, the exception message I get is

Text 'Wed Jan 18 23:22:18 EST 2017' could not be parsed at index 0

Index 0, that’s where it says Wed. What’s wrong with that? The problem is my computer runs Danish locale. If you want to parse a date-time string in English on computers of different locales, you need to specify an English-speaking locale, for example:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss zzz YYYY",
                                                        Locale.ENGLISH);

The same holds true if you are using SimpleDateFormat. With this correction I get a different exception message:

Text 'Wed Jan 18 23:22:18 EST 2017' could not be parsed: Invalid value for ClockHourOfAmPm (valid values 1 - 12): 23

Isn’t this message wonderfully precise? The format had expected a value between 1 and 12 (inclusive) where you put 23. As menitoned in the comments, this is because you were using lowercase hh where you intended uppercase HH. After fixing this, we get

Text 'Wed Jan 18 23:22:18 EST 2017' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {DayOfMonth=18, DayOfWeek=3, MonthOfYear=1, WeekBasedYear[WeekFields[SUNDAY,1]]=2017},ISO,America/New_York resolved to 23:22:18 of type java.time.format.Parsed

It’s more cryptic, but it does mention the problem that MadProgrammer also points out: the week-based year. This is what uppercase YYYY gives you (and it’s a very common mistake, judging from the many questions on Stack Overflow with this exact problem). Let’s fix that too:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy",
                                                        Locale.ENGLISH);

Now we get the expected:

2017-01-18T23:22:18-05:00[America/New_York]

One final word of caution: the three and four letter time zone abbreviations like EST come with some negative surprises too. DateTimeFormatter understands EST as UTC-5, which I suppose is what you want with a date in January (winter). For a date in the summer, would you still be expecting UTC-5, or would you expect EDT, that is, UTC-4? In your case you may be able to solve the ambiguity by supplying EDT for Eastern Daylight Time, but generally it’s better to avoid those abbreviation and use the longer time zone IDs like America/New_York and/or offsets like -05:00.

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.