break;
}
// Handle cutover here.
long fd = getCurrentFixedDate();
BaseCalendar cal;
if (gregorianCutoverYear == gregorianCutoverYearJulian) {
cal = getCutoverCalendarSystem();
} else if (y == gregorianCutoverYear) {
cal = gcal;
} else {
cal = getJulianCalendarSystem();
}
long day1 = fd - (7 * (woy - min));
// Make sure that the min week has the current DAY_OF_WEEK
if (cal.getYearFromFixedDate(day1) != y) {
min++;
}
// Make sure the same thing for the max week
fd += 7 * (max - woy);
cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem();
if (cal.getYearFromFixedDate(fd) != y) {
max--;
}
// value: the new WEEK_OF_YEAR which must be converted
// to month and day of month.
value = getRolledValue(woy, amount, min, max) - 1;
BaseCalendar.Date d = getCalendarDate(day1 + value * 7);
set(MONTH, d.getMonth() - 1);
set(DAY_OF_MONTH, d.getDayOfMonth());
return;
}
case WEEK_OF_MONTH:
{
boolean isCutoverYear = isCutoverYear(cdate.getNormalizedYear());
// dow: relative day of week from first day of week
int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
if (dow < 0) {
dow += 7;
}
long fd = getCurrentFixedDate();
long month1; // fixed date of the first day (usually 1) of the month
int monthLength; // actual month length
if (isCutoverYear) {
month1 = getFixedDateMonth1(cdate, fd);
monthLength = actualMonthLength();
} else {
month1 = fd - internalGet(DAY_OF_MONTH) + 1;
monthLength = calsys.getMonthLength(cdate);
}
// the first day of week of the month.
long monthDay1st = calsys.getDayOfWeekDateOnOrBefore(month1 + 6,
getFirstDayOfWeek());
// if the week has enough days to form a week, the
// week starts from the previous month.
if ((int)(monthDay1st - month1) >= getMinimalDaysInFirstWeek()) {
monthDay1st -= 7;
}
max = getActualMaximum(field);
// value: the new WEEK_OF_MONTH value
int value = getRolledValue(internalGet(field), amount, 1, max) - 1;
// nfd: fixed date of the rolled date
long nfd = monthDay1st + value * 7 + dow;
// Unlike WEEK_OF_YEAR, we need to change day of week if the
// nfd is out of the month.
if (nfd < month1) {
nfd = month1;
} else if (nfd >= (month1 + monthLength)) {
nfd = month1 + monthLength - 1;
}
int dayOfMonth;
if (isCutoverYear) {
// If we are in the cutover year, convert nfd to
// its calendar date and use dayOfMonth.
BaseCalendar.Date d = getCalendarDate(nfd);
dayOfMonth = d.getDayOfMonth();
} else {
dayOfMonth = (int)(nfd - month1) + 1;
}
set(DAY_OF_MONTH, dayOfMonth);
return;
}
case DAY_OF_MONTH:
{
if (!isCutoverYear(cdate.getNormalizedYear())) {
max = calsys.getMonthLength(cdate);
break;
}
// Cutover year handling
long fd = getCurrentFixedDate();
long month1 = getFixedDateMonth1(cdate, fd);
// It may not be a regular month. Convert the date and range to
// the relative values, perform the roll, and
// convert the result back to the rolled date.
int value = getRolledValue((int)(fd - month1), amount, 0, actualMonthLength() - 1);
BaseCalendar.Date d = getCalendarDate(month1 + value);
assert d.getMonth()-1 == internalGet(MONTH);
set(DAY_OF_MONTH, d.getDayOfMonth());
return;
}
case DAY_OF_YEAR:
{
max = getActualMaximum(field);
if (!isCutoverYear(cdate.getNormalizedYear())) {
break;
}
// Handle cutover here.
long fd = getCurrentFixedDate();
long jan1 = fd - internalGet(DAY_OF_YEAR) + 1;
int value = getRolledValue((int)(fd - jan1) + 1, amount, min, max);
BaseCalendar.Date d = getCalendarDate(jan1 + value - 1);
set(MONTH, d.getMonth() - 1);
set(DAY_OF_MONTH, d.getDayOfMonth());
return;
}
case DAY_OF_WEEK:
{
if (!isCutoverYear(cdate.getNormalizedYear())) {
// If the week of year is in the same year, we can
// just change DAY_OF_WEEK.
int weekOfYear = internalGet(WEEK_OF_YEAR);
if (weekOfYear > 1 && weekOfYear < 52) {
set(WEEK_OF_YEAR, weekOfYear); // update stamp[WEEK_OF_YEAR]
max = SATURDAY;
break;
}
}
// We need to handle it in a different way around year
// boundaries and in the cutover year. Note that
// changing era and year values violates the roll
// rule: not changing larger calendar fields...
amount %= 7;
if (amount == 0) {
return;
}
long fd = getCurrentFixedDate();
long dowFirst = calsys.getDayOfWeekDateOnOrBefore(fd, getFirstDayOfWeek());
fd += amount;
if (fd < dowFirst) {
fd += 7;
} else if (fd >= dowFirst + 7) {
fd -= 7;
}
BaseCalendar.Date d = getCalendarDate(fd);
set(ERA, (d.getNormalizedYear() <= 0 ? BCE : CE));
set(d.getYear(), d.getMonth() - 1, d.getDayOfMonth());
return;
}
case DAY_OF_WEEK_IN_MONTH:
{
min = 1; // after normalized, min should be 1.
if (!isCutoverYear(cdate.getNormalizedYear())) {
int dom = internalGet(DAY_OF_MONTH);
int monthLength = calsys.getMonthLength(cdate);
int lastDays = monthLength % 7;
max = monthLength / 7;
int x = (dom - 1) % 7;
if (x < lastDays) {
max++;
}
set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK));
break;
}
// Cutover year handling
long fd = getCurrentFixedDate();
long month1 = getFixedDateMonth1(cdate, fd);
int monthLength = actualMonthLength();
int lastDays = monthLength % 7;
max = monthLength / 7;
int x = (int)(fd - month1) % 7;
if (x < lastDays) {
max++;
}
int value = getRolledValue(internalGet(field), amount, min, max) - 1;
fd = month1 + value * 7 + x;
BaseCalendar cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem();
BaseCalendar.Date d = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
cal.getCalendarDateFromFixedDate(d, fd);
set(DAY_OF_MONTH, d.getDayOfMonth());
return;
}
}