Be careful when using java.util.Calendar to get month names
java.util.Calendar operates in ‘lenient’ mode by default.
This means that setting invalid date values will silently yield a reconciled value on retrieval.
The example given in the documentation is that setting January 32 yields February 1.
When working with Calendar instances for the purpose of getting back a month name, this silent lenient mode can bite you. For instance:
Calendar month = Calendar.getInstance(); month.set(Calendar.MONTH, Calendar.NOVEMBER); return String.format(Locale.getDefault(), "%tB", month); // or return month.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault())
The code snippet above tries to get the English name for
When this code is run between October 1 through 30, this returns “November”, as expected.
But on October 31, something spooky happens: it unexpectedly returns “December”. 👻
This is because November 31 is an invalid date, and automatically gets reconciled to December 1. There’s two possible solutions to this:
- Set the day of month to 1 prior to setting the month. Or at the same time using
Calendar.set(year, month, day).
- Avoid making a
Calendarinstance in the first place, by using