/**
   * Add the specified month to the specified time instant. The amount added may be negative.
   *
   * <p>If the new month has less total days than the specified day of the month, this value is
   * coerced to the nearest sane value. e.g.
   *
   * <p>07-31 - (1 month) = 06-30
   *
   * <p>03-31 - (1 month) = 02-28 or 02-29 depending
   *
   * <p>
   *
   * @see org.joda.time.DateTimeField#add
   * @see org.joda.time.ReadWritableDateTime#addMonths(int)
   * @param instant the time instant in millis to update.
   * @param months the months to add (can be negative).
   * @return the updated time instant.
   */
  public long add(long instant, int months) {
    if (months == 0) {
      return instant; // the easy case
    }
    //
    // Save time part first.
    //
    long timePart = iChronology.getMillisOfDay(instant);
    //
    //
    // Get this year and month.
    //
    int thisYear = iChronology.getYear(instant);
    int thisMonth = iChronology.getMonthOfYear(instant, thisYear);
    // ----------------------------------------------------------
    //
    // Do not refactor without careful consideration.
    // Order of calculation is important.
    //
    int yearToUse;
    // Initially, monthToUse is zero-based
    int monthToUse = thisMonth - 1 + months;
    if (monthToUse >= 0) {
      yearToUse = thisYear + (monthToUse / iMax);
      monthToUse = (monthToUse % iMax) + 1;
    } else {
      yearToUse = thisYear + (monthToUse / iMax) - 1;
      monthToUse = Math.abs(monthToUse);
      int remMonthToUse = monthToUse % iMax;
      // Take care of the boundary condition
      if (remMonthToUse == 0) {
        remMonthToUse = iMax;
      }
      monthToUse = iMax - remMonthToUse + 1;
      // Take care of the boundary condition
      if (monthToUse == 1) {
        yearToUse += 1;
      }
    }
    // End of do not refactor.
    // ----------------------------------------------------------

    //
    // Quietly force DOM to nearest sane value.
    //
    int dayToUse = iChronology.getDayOfMonth(instant, thisYear, thisMonth);
    int maxDay = iChronology.getDaysInYearMonth(yearToUse, monthToUse);
    if (dayToUse > maxDay) {
      dayToUse = maxDay;
    }
    //
    // get proper date part, and return result
    //
    long datePart = iChronology.getYearMonthDayMillis(yearToUse, monthToUse, dayToUse);
    return datePart + timePart;
  }
 /**
  * Set the Month component of the specified time instant.
  *
  * <p>If the new month has less total days than the specified day of the month, this value is
  * coerced to the nearest sane value. e.g.
  *
  * <p>07-31 to month 6 = 06-30
  *
  * <p>03-31 to month 2 = 02-28 or 02-29 depending
  *
  * <p>
  *
  * @param instant the time instant in millis to update.
  * @param month the month (1,12) to update the time to.
  * @return the updated time instant.
  * @throws IllegalArgumentException if month is invalid
  */
 public long set(long instant, int month) {
   FieldUtils.verifyValueBounds(this, month, MIN, iMax);
   //
   int thisYear = iChronology.getYear(instant);
   //
   int thisDom = iChronology.getDayOfMonth(instant, thisYear);
   int maxDom = iChronology.getDaysInYearMonth(thisYear, month);
   if (thisDom > maxDom) {
     // Quietly force DOM to nearest sane value.
     thisDom = maxDom;
   }
   // Return newly calculated millis value
   return iChronology.getYearMonthDayMillis(thisYear, month, thisDom)
       + iChronology.getMillisOfDay(instant);
 }
  // -----------------------------------------------------------------------
  public long add(long instant, long months) {
    int i_months = (int) months;
    if (i_months == months) {
      return add(instant, i_months);
    }

    // Copied from add(long, int) and modified slightly:

    long timePart = iChronology.getMillisOfDay(instant);

    int thisYear = iChronology.getYear(instant);
    int thisMonth = iChronology.getMonthOfYear(instant, thisYear);

    long yearToUse;
    long monthToUse = thisMonth - 1 + months;
    if (monthToUse >= 0) {
      yearToUse = thisYear + (monthToUse / iMax);
      monthToUse = (monthToUse % iMax) + 1;
    } else {
      yearToUse = thisYear + (monthToUse / iMax) - 1;
      monthToUse = Math.abs(monthToUse);
      int remMonthToUse = (int) (monthToUse % iMax);
      if (remMonthToUse == 0) {
        remMonthToUse = iMax;
      }
      monthToUse = iMax - remMonthToUse + 1;
      if (monthToUse == 1) {
        yearToUse += 1;
      }
    }

    if (yearToUse < iChronology.getMinYear() || yearToUse > iChronology.getMaxYear()) {

      throw new IllegalArgumentException("Magnitude of add amount is too large: " + months);
    }

    int i_yearToUse = (int) yearToUse;
    int i_monthToUse = (int) monthToUse;

    int dayToUse = iChronology.getDayOfMonth(instant, thisYear, thisMonth);
    int maxDay = iChronology.getDaysInYearMonth(i_yearToUse, i_monthToUse);
    if (dayToUse > maxDay) {
      dayToUse = maxDay;
    }

    long datePart = iChronology.getYearMonthDayMillis(i_yearToUse, i_monthToUse, dayToUse);
    return datePart + timePart;
  }