FUNCTION new_add_months (date_in IN DATE, months_shift IN NUMBER) RETURN DATE IS /* Return value of function */ return_value DATE; /* The day in the month */ day_of_month VARCHAR2(2); /* The month and year for the return value */ month_year VARCHAR2(6); /* The calculated end of month date */ end_of_month DATE; BEGIN return_value := ADD_MONTHS (date_in, months_shift); /* Is original date the last day of its month? */ IF date_in = LAST_DAY (date_in) THEN /* Pull out the day number of the original date */ day_of_month := TO_CHAR (date_in, 'DD'); /* Grab the month and year of the new date */ month_year := TO_CHAR (return_value, 'MMYYYY'); /* Combine these components into an actual date */ end_of_month := TO_DATE ( month_year || day_of_month, 'MMYYYYDD'); /* || Return the earliest of (a) the normal result of ADD_MONTHS || and (b) the same day in the new month as in the original month. */ return_value := LEAST (return_value, end_of_month); END IF; /* Return the shifted date */ RETURN return_value; END new_add_months;