Strange behavior from java.util.Calendar in February

I came across strange behavior from java.util.Calendar:

import static org.junit.Assert.*; import org.junit.Test; import java.util.Calendar; public class Tester1 { @Test public void test_monthOfDate() { assertEquals(1, monthOfDate(2013, 1, 30)); // OK assertEquals(1, monthOfDate(2013, 1, 31)); // OK // Start of February assertEquals(2, monthOfDate(2013, 2, 1)); // FAIL assertEquals(2, monthOfDate(2013, 2, 28)); // FAIL // to the end of it // and after that it is okay also assertEquals(3, monthOfDate(2013, 3, 1)); // OK } public int monthOfDate(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, month - 1); // just a simple get! but seems it is very important cal.get(Calendar.MONTH); // cal.set(Calendar.DAY_OF_MONTH, day); return cal.get(Calendar.MONTH) + 1; } } 

I want to know why this is happening?

+4
source share
1 answer

The problem is that you start with the calendar on January 30, 2013.

Then you set the year to 2013 - this is not a problem.

Then you set the month to 1 (i.e., February). What do you expect from here? What actually happens is that he remembers that he needs to set the month to 1, but not to recalculate the actual time value. The time value will be recounted when you call get , although according to the documentation (empirical mine):

set (f, value) changes the calendar field f to a value. In addition, it sets an internal member variable to indicate that calendar field f has been changed. Although calendar field f changes immediately, the calendar time in milliseconds is not recalculated until the next call to get (), getTime (), getTimeInMillis (), add (), or roll () is made. Thus, multiple calls to set () do not start several unnecessary calculations. As a result of changing the calendar field using set (), other calendar fields can also change depending on the calendar field, the value of the calendar field, and the calendar system. In addition, get (f) will not necessarily return the value specified by calling the set method after recalculating the calendar fields. Specificity is determined by a particular calendar class.

When you try to change “January 30” to “February 30” and force it to calculate what is actually happening, it is that you end March 2 on my inbox, but it may differ in your implementation.

The best fixes:

+15
source

All Articles