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
.