Logo Search packages:      
Sourcecode: icu version File versions  Download package

void Calendar::add ( UCalendarDateFields  field,
int32_t  amount,
UErrorCode status 
) [virtual, inherited]

UDate Arithmetic function. Adds the specified (signed) amount of time to the given time field, based on the calendar's rules. For example, to subtract 5 days from the current time of the calendar, call add(Calendar::DATE, -5). When adding on the month or Calendar::MONTH field, other fields like date might conflict and need to be changed. For instance, adding 1 month on the date 01/31/96 will result in 02/29/96.

Parameters:
field Specifies which date field to modify.
amount The amount of time to be added to the field, in the natural unit for that field (e.g., days for the day fields, hours for the hour field.)
status Output param set to success/failure code on exit. If any value previously set in the time field is invalid or restricted by leniency, this will be set to an error status. ICU 2.6.

Reimplemented in ChineseCalendar, and HebrewCalendar.

Definition at line 1759 of file calendar.cpp.

References FALSE, Calendar::getTimeInMillis(), Calendar::internalGet(), Calendar::internalGetTime(), Calendar::pinField(), Calendar::setTimeInMillis(), TRUE, U_ILLEGAL_ARGUMENT_ERROR, UCAL_AM_PM, UCAL_DAY_OF_MONTH, UCAL_DAY_OF_WEEK, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_YEAR, UCAL_DOW_LOCAL, UCAL_DST_OFFSET, UCAL_ERA, UCAL_EXTENDED_YEAR, UCAL_HOUR, UCAL_HOUR_OF_DAY, UCAL_JULIAN_DAY, UCAL_MILLISECOND, UCAL_MILLISECONDS_IN_DAY, UCAL_MINUTE, UCAL_MONTH, UCAL_SECOND, UCAL_WEEK_OF_MONTH, UCAL_WEEK_OF_YEAR, UCAL_YEAR, and UCAL_YEAR_WOY.

{
    if (amount == 0) {
        return;   // Do nothing!
    }

    // We handle most fields in the same way.  The algorithm is to add
    // a computed amount of millis to the current millis.  The only
    // wrinkle is with DST -- for some fields, like the DAY_OF_MONTH,
    // we don't want the HOUR to shift due to changes in DST.  If the
    // result of the add operation is to move from DST to Standard, or
    // vice versa, we need to adjust by an hour forward or back,
    // respectively.  For such fields we set keepHourInvariant to TRUE.

    // We only adjust the DST for fields larger than an hour.  For
    // fields smaller than an hour, we cannot adjust for DST without
    // causing problems.  for instance, if you add one hour to April 5,
    // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an
    // illegal value), but then the adjustment sees the change and
    // compensates by subtracting an hour.  As a result the time
    // doesn't advance at all.

    // For some fields larger than a day, such as a UCAL_MONTH, we pin the
    // UCAL_DAY_OF_MONTH.  This allows <March 31>.add(UCAL_MONTH, 1) to be
    // <April 30>, rather than <April 31> => <May 1>.

    double delta = amount; // delta in ms
    UBool keepHourInvariant = TRUE;

    switch (field) {
    case UCAL_ERA:
        set(field, get(field, status) + amount);
        pinField(UCAL_ERA, status);
        return;

    case UCAL_YEAR:
    case UCAL_EXTENDED_YEAR:
    case UCAL_YEAR_WOY:
    case UCAL_MONTH:
        set(field, get(field, status) + amount);
        pinField(UCAL_DAY_OF_MONTH, status);
        return;

    case UCAL_WEEK_OF_YEAR:
    case UCAL_WEEK_OF_MONTH:
    case UCAL_DAY_OF_WEEK_IN_MONTH:
        delta *= kOneWeek;
        break;

    case UCAL_AM_PM:
        delta *= 12 * kOneHour;
        break;

    case UCAL_DAY_OF_MONTH:
    case UCAL_DAY_OF_YEAR:
    case UCAL_DAY_OF_WEEK:
    case UCAL_DOW_LOCAL:
    case UCAL_JULIAN_DAY:
        delta *= kOneDay;
        break;

    case UCAL_HOUR_OF_DAY:
    case UCAL_HOUR:
        delta *= kOneHour;
        keepHourInvariant = FALSE;
        break;

    case UCAL_MINUTE:
        delta *= kOneMinute;
        keepHourInvariant = FALSE;
        break;

    case UCAL_SECOND:
        delta *= kOneSecond;
        keepHourInvariant = FALSE;
        break;

    case UCAL_MILLISECOND:
    case UCAL_MILLISECONDS_IN_DAY:
        keepHourInvariant = FALSE;
        break;

    default:
#if defined (U_DEBUG_CAL)
        fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s not addable",
            __FILE__, __LINE__, fldName(field));
#endif
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return;
        //  throw new IllegalArgumentException("Calendar.add(" + fieldName(field) +
        //                                     ") not supported");
    }

    // In order to keep the hour invariant (for fields where this is
    // appropriate), record the DST_OFFSET before and after the add()
    // operation.  If it has changed, then adjust the millis to
    // compensate.
    int32_t dst = 0;
    int32_t hour = 0;
    if (keepHourInvariant) {
        dst = get(UCAL_DST_OFFSET, status);
        hour = internalGet(UCAL_HOUR_OF_DAY);
    }

    setTimeInMillis(getTimeInMillis(status) + delta, status);

    if (keepHourInvariant) {
        dst -= get(UCAL_DST_OFFSET, status);
        if (dst != 0) {
            // We have done an hour-invariant adjustment but the
            // DST offset has altered.  We adjust millis to keep
            // the hour constant.  In cases such as midnight after
            // a DST change which occurs at midnight, there is the
            // danger of adjusting into a different day.  To avoid
            // this we make the adjustment only if it actually
            // maintains the hour.
            double t = internalGetTime();
            setTimeInMillis(t + dst, status);
            if (get(UCAL_HOUR_OF_DAY, status) != hour) {
                setTimeInMillis(t, status);
            }
        }
    } 
}


Generated by  Doxygen 1.6.0   Back to index