Recently, I work with the Calendar and GregorianCalendar classes of Java (JDK 1.4.2). I used the Calendar.add(int field, int amount) method. But I found that there is an incoherent between the Javadoc and the behavior of the method.

Here is the extract of Javadoc for the Calendar class:

Usage model. To motivate the behavior of add() and roll(), consider a user interface component with increment and decrement buttons for the month, day, and year, and an underlying GregorianCalendar. If the interface reads January 31, 1999 and the user presses the month increment button, what should it read? If the underlying implementation uses set(), it might read March 3, 1999. A better result would be February 28, 1999. Furthermore, if the user presses the month increment button again, it should read March 31, 1999, not March 28, 1999. By saving the original date and using either add() or roll(), depending on whether larger fields should be affected, the user interface can behave as most users will intuitively expect.

I interpreted this as following:
If I have the date “31 January 2007” and I use add(Calendar.MONTH, 1), I should obtain the date “28 February 2007”. — This is exactly what the method did. OK
If I have the date “28 February 2007” and I use add(Calendar.MONTH, 1), I should obtain the date “31 March 2007”. — This is unfortunately NOT what the method did. I obtained “28 March 2007”

Here is the code I used:

package test;

import java.util.Calendar;
import java.util.GregorianCalendar;

import junit.framework.TestCase;

 * @author Hong Nam NGUYEN -- Created: 4 oct. 07 - 10:38:28
public class CalendarTest extends TestCase
    final int MONTH = Calendar.MONTH;
    final int DAY_OF_MONTH = Calendar.DAY_OF_MONTH;
    static Calendar calendar = new GregorianCalendar();
    static {
	calendar.set(2007, Calendar.JANUARY, 31);
    public void testAdd1()
	calendar.roll(MONTH, 1);
            "Should be February", Calendar.FEBRUARY, calendar.get(MONTH));
	assertEquals("Should be 28", 28, calendar.get(DAY_OF_MONTH));
    public void testAdd2()
	calendar.roll(MONTH, 1);
            "Should be March", Calendar.MARCH, calendar.get(MONTH));
	assertEquals("Should be 31", 31, calendar.get(DAY_OF_MONTH));

the second test is down.

I have reported this bug to Sun, so wait for the response.

[Add 10-oct-2007] I had the response from Sun, so this is really a bug. Sun had added this bug to their internal bug tracking system under Bug Id: 6615044.
We can see the bug on the Java Bug Database at: