Java calendar - date is unpredictable after setting day_of_week

I have the following code in a JUnit test that seemed to work last week, not working this week:

Calendar cal = Calendar.getInstance(); cal.set(2011, Calendar.JULY, 12); cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY); // push the date to 15 System.out.println(cal.get(Calendar.DATE)); 

As you can probably conclude from my comment since the 12th of Tuesday, I expect Date to be 15 after setting DAY_OF_WEEK on Friday. However, the printed value is 22 and the test fails.

If, however, I change the code as follows and add an extra call to get:

 Calendar cal = Calendar.getInstance(); cal.set(2011, Calendar.JULY, 12); System.out.println(cal.get(Calendar.DATE)); cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY); // push the date to 15 System.out.println(cal.get(Calendar.DATE)); 

I get the result that I expect 12 and 15.

Can someone explain what is happening and why this test worked last week?

+12
java
Jul 17 2018-11-11T00:
source share
3 answers

The first thing to understand is that Month + Day + DayOfWeek means nothing to the Calendar. The calendar will calculate the true date value based on

YEAR + MONTH + DATE

or

YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK

(Or some other combos, such as year + day of the year, etc.). So Date + DayOfWeek doesn't really matter to him.

The second thing you need to understand is when you install the Java calendar, it does not actually recalculate the absolute time or the fields associated with the update until an operation occurs that forces the calculation.

After your first set, the calendar is in a conflicting state. The month and day say it is July 12th, but the "week of the month" and "day of the week" still say that today, regardless of today. Then you call the set day of the week on Friday. So now the year month and day say July 12th, but the "week of the month" and "day of the week" fields talk about Friday of the week 'this'.

The rules of the calendar say that the last specified field โ€œwinsโ€ when there is a conflict, so the week of the month and day of the week, combined with the expression on Friday this week, is used to calculate other fields.

Inserting get in the middle โ€œcorrectsโ€ it, because it causes the entire internal state of the calendar to be redistributed on Tuesday July 12th before installation on Friday, so there are no internal conflicts. "Week of the month" was set to week, which contains July 12 by recounting before you set the day of the week to Friday.

Edit: sorry for making the changes in two days, noticing that it is open on the old browser tab, and I thought that I would expand for reliable help of future googlers:

The reason she worked for John in the comments is because he lives in London. His computer thinks weeks start on Mondays. Therefore, when asked on Friday the week of 'this', he still answered on July 15 when he was asked on Sunday, July 17. I talk about this because the excellent first days of the week in different locales are another way that trying to use the WEEK_OF fields in a calendar converges.

+19
Jul 17 '11 at 8:00
source share

There is Error 4655637 (similar to your problem). I checked this code under the latest JDK6 (Windows), and I have 15 in both cases. BTW: I suggest that you always use the GregorianCalendar class unless you want something else (depending on your locale).

+3
Jul 17 '11 at 8:00
source share

EDIT: white papers :

The following are the default calendar field combinations. the most recent combination determined by the most recently set single field.

For date fields:

  YEAR + MONTH + DAY_OF_MONTH YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK YEAR + DAY_OF_YEAR YEAR + DAY_OF_WEEK + WEEK_OF_YEAR 

For daytime fields:

  HOUR_OF_DAY AM_PM + HOUR 



In addition to @Affe's clear answer, the following combinations seem to work (via the link to the @GrzegorzSzpetkowski error message)

The calendar expects the following combinations of fields to determine the date.

  MONTH + DAY_OF_MONTH MONTH + WEEK_OF_MONTH + DAY_OF_WEEK MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK DAY_OF_YEAR DAY_OF_WEEK + WEEK_OF_YEAR 

When you set DAY_OF_WEEK, the calendar expects the week field (WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH or WEEK_OF_YEAR) also set. Therefore, do not set DAY_OF_WEEK without setting one of the weeks of the field.

+1
Jul 04 '15 at 11:23
source share



All Articles