Parsing a string to date format in java defaults date to 1 and month to January

Solution 1:

Because you used YYYY when you needed yyyy and July 20, 2015 was a Monday. You wanted something like

String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, yyyy";
SimpleDateFormat userDateFormatter = new SimpleDateFormat(
        userDateFormat);
String reference_date = "2000 hrs, Monday, July 20, 2015";

which then outputs

2000 hrs, Monday, July 20, 2015

Then SimpleDateFormat Javadoc says (in part)

Letter    Date or Time Component  Presentation    Examples
G         Era designator          Text            AD
y         Year                    Year            1996; 96
Y         Week year               Year            2009; 09

Solution 2:

java.time

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Monday, July 20, 2015";
    LocalDateTime dateTime = LocalDateTime.parse(referenceDate, userDateTimeFormatter);
    System.out.println(dateTime.format(userDateTimeFormatter));

Output is:

2000 hrs, Monday, July 20, 2015

The answer by Elliott Frisch is correct. I am contributing the modern answer using java.time, the modern Java date and time API. When this question was asked, it had been out for one and a half years. Now it’s four years old and widespread. I am furthermore giving an explicit locale. Your date-time is in English, and while your default locale probably is too, code that relies on that will break if one day you run it on a computer in a different locale or you just change your own locale setting.

You’re far from the only one making the mistake of using incorrect case in a format pattern string. Questions about this are being asked on Stack Overflow all the time. SimpleDateFormat is renowned for acting up: it gives you an incorrect result and pretends all is fine, where you would really have expected it to notify you that something was wrong, for example by throwing an exception.

The modern API does throw an exception when you give it incorrect input that it can detect. For example:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, YYYY", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Thursday, July 20, 2015";

Result:

java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=7, DayOfWeek=4, WeekBasedYear[WeekFields[SUNDAY,1]]=2015, DayOfMonth=20},ISO resolved to 20:00 of type java.time.format.Parsed

It’s not very readable. The thing to notice is “WeekBasedYear”. A week-based year is only useful with a week number, so it’s wrong here. And the docs will tell you that it was uppercase YYYY that gave you this. Let’s fix:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);

With DateTimeFormatter it’s customary to use uuuu for year. yyyy works too for years after year 0. We’re not done, though:

java.time.DateTimeException: Conflict found: Field DayOfWeek 1 differs from DayOfWeek 4 derived from 2015-07-20

The modern API also refuses to accept an incorrect day of week, so you get full validation of your date (there’s a trick to persuade it, though, if you don’t want this validation). As Elliott Frisch already said, July 20, 2015, was a Monday (day 1 of the week), not a Thursday. In my first snippet above I have also fixed this error, so that works.

Link: Oracle tutorial: Date Time explaining how to use java.time.