I am creating a calendar in my Android application. The first day of the calendar is Sunday or Monday. It depends on the locale. Strange behavior of the java.util.GregorianCalendar class in different android versions:
public class CurrentMonth extends AbstractCurrentMonth implements InterfaceCurrentMonth {
public CurrentMonth(GregorianCalendar calendar, int firstDayOfWeek) {
super(calendar, firstDayOfWeek);
}
@Override
public List<ContentAbstract> getListContent() {
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
GregorianCalendar currentCalendar = new GregorianCalendar(year, month, 1);
List<ContentAbstract> list = new ArrayList<>();
int weekDay = getDayOfWeek(currentCalendar);
currentCalendar.add(Calendar.DAY_OF_WEEK, - (weekDay - 1));
while (currentCalendar.get(Calendar.MONTH) != month) {
list.add(getContent(currentCalendar));
currentCalendar.add(Calendar.DAY_OF_MONTH, 1);
}
while (currentCalendar.get(Calendar.MONTH) == month) {
list.add(getContent(currentCalendar));
currentCalendar.add(Calendar.DAY_OF_MONTH, 1);
}
currentCalendar.add(Calendar.DAY_OF_MONTH, - 1);
while (getDayOfWeek(currentCalendar) != 7) {
currentCalendar.add(Calendar.DAY_OF_MONTH, 1);
list.add(getContent(currentCalendar));
}
Log.i("text", "yaer: " + list.get(0).getYear());
Log.i("text", "month: " + list.get(0).getMonth());
Log.i("text", "day of month: " + list.get(0).getDay());
Log.i("text", "day of week: " + list.get(0).getDayOfWeek());
return list;
}
private int getDayOfWeek(GregorianCalendar currentCalendar) {
int weekDay;
if (firstDayOfWeek == Calendar.MONDAY) {
weekDay = 7 - (8 - currentCalendar.get(Calendar.DAY_OF_WEEK)) % 7;
}
else weekDay = currentCalendar.get(Calendar.DAY_OF_WEEK);
return weekDay;
}
private GraphicContent getContent(GregorianCalendar cal) {
GraphicContent content = new GraphicContent();
content.setYear(cal.get(Calendar.YEAR));
content.setMonth(cal.get(Calendar.MONTH));
content.setDay(cal.get(Calendar.DAY_OF_MONTH));
content.setDayOfWeek(cal.get(Calendar.DAY_OF_WEEK));
return content;
}
}
public class GraphicContent extends ContentAbstract {
private int year;
private int month;
private int day;
private int dayOfWeek;
@Override
public int getYear() {
return year;
}
@Override
public void setYear(int year) {
this.year = year;
}
@Override
public int getMonth() {
return month;
}
@Override
public void setMonth(int month) {
this.month = month;
}
@Override
public int getDay() {
return day;
}
@Override
public void setDay(int day) {
this.day = day;
}
@Override
public int getDayOfWeek() {
return dayOfWeek;
}
@Override
public void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
}
Set the class constructor (new GregorianCalendar(1994, 3, 1), Calendar.SUNDAY). In android 4.4, 5.0 Logcat result:
10-12 14:32:28.332 27739-27739/*** I/text: yaer: 1994
10-12 14:32:28.332 27739-27739/*** I/text: month: 2
10-12 14:32:28.332 27739-27739/*** I/text: day of month: 26
10-12 14:32:28.332 27739-27739/*** I/text: day of week: 7
In android 8.0 Logcat result:
2018-10-12 11:50:59.549 6565-6565/*** I/text: yaer: 1994
2018-10-12 11:50:59.549 6565-6565/*** I/text: month: 2
2018-10-12 11:50:59.549 6565-6565/*** I/text: day of month: 27
2018-10-12 11:50:59.549 6565-6565/*** I/text: day of week: 1
As you can see the result - different days (26 and 27), which corresponds to different days of the week. BUT IF YOU CHANGE THE INITIALIZATION of the calendar object:
@Override
public List<ContentAbstract> getListContent() {
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
GregorianCalendar currentCalendar = (GregorianCalendar) Calendar.getInstance();
currentCalendar.set(year, month, 1);
The RESULT WILL BE TRUE on all versions of android:
10-12 15:12:56.400 28914-28914/*** I/text: yaer: 1994
10-12 15:12:56.400 28914-28914/*** I/text: month: 2
10-12 15:12:56.400 28914-28914/*** I/text: day of month: 27
10-12 15:12:56.400 28914-28914/*** I/text: week day: 1
In junit tests the result is correct in all cases (27 and SUNDAY). Delete the logs from the code and check:
public class TestCurrentMonth {
@Test
public void testGetListContent() {
GregorianCalendar calendar = new GregorianCalendar(1994, 3, 1);
int firstDay = Calendar.SUNDAY;
CurrentMonth currentMonth = new CurrentMonth(calendar, firstDay);
List<ContentAbstract> list = currentMonth.getListContent();
Assert.assertEquals(27, list.get(0).getDay());
Assert.assertEquals(Calendar.SUNDAY, list.get(0).getDayOfWeek());
}
}
Also behavior for April 1993, 1992. Why? I already broke my brains.