Boolean _CFCalendarAddComponentsV(CFCalendarRef calendar, /* inout */ CFAbsoluteTime *atp, CFOptionFlags options, const char *componentDesc, int *vector, int count) { if (!calendar->_cal) __CFCalendarSetupCal(calendar); if (calendar->_cal) { UErrorCode status = U_ZERO_ERROR; ucal_clear(calendar->_cal); UDate udate = floor((*atp + kCFAbsoluteTimeIntervalSince1970) * 1000.0); ucal_setMillis(calendar->_cal, udate, &status); char ch = *componentDesc; while (ch) { UCalendarDateFields field = __CFCalendarGetICUFieldCodeFromChar(ch); int amount = *vector; if (options & kCFCalendarComponentsWrap) { ucal_roll(calendar->_cal, field, amount, &status); } else { ucal_add(calendar->_cal, field, amount, &status); } vector++; componentDesc++; ch = *componentDesc; } udate = ucal_getMillis(calendar->_cal, &status); *atp = (udate / 1000.0) - kCFAbsoluteTimeIntervalSince1970; return U_SUCCESS(status) ? true : false; } return false; }
/** * call-seq: * calendar.roll(field, int_amount) * * Adds a signed amount to the specified calendar field without changing larger fields. * A negative roll amount means to subtract from field without changing larger fields. * If the specified amount is 0, this method performs nothing. * * Example: Consider a GregorianCalendar originally set to August 31, 1999. Calling roll(:month, 8) * sets the calendar to April 30, 1999. Using a Gregorian Calendar, the :day_of_month field cannot * be 31 in the month April. :day_of_month is set to the closest possible value, 30. The :year field * maintains the value of 1999 because it is a larger field than :month. */ VALUE icu4r_cal_roll(VALUE obj, VALUE field, VALUE amount) { UErrorCode status = U_ZERO_ERROR; int date_field; Check_Type(field, T_SYMBOL); Check_Type(amount, T_FIXNUM); date_field = icu4r_get_cal_field_int(field); ucal_roll(UCALENDAR(obj), date_field, FIX2INT(amount) , &status); ICU_RAISE(status); return Qnil; }