code: private void offsetMonth(int newMoon, int dom, int delta) {
          // Move to the middle of the month before our target month.
          newMoon += (int) (CalendarAstronomer.SYNODIC_MONTH * (delta - 0.5));
  
          // Search forward to the target month's new moon
          newMoon = newMoonNear(newMoon, true);
  
          // Find the target dom
          int jd = newMoon + EPOCH_JULIAN_DAY - 1 + dom;
  
          // Pin the dom.  In this calendar all months are 29 or 30 days
          // so pinning just means handling dom 30.
          if (dom > 29) {
              set(JULIAN_DAY, jd-1);
              // TODO Fix this.  We really shouldn't ever have to
              // explicitly call complete().  This is either a bug in
              // this method, in ChineseCalendar, or in
              // Calendar.getActualMaximum().  I suspect the last.
              complete();
              if (getActualMaximum(DAY_OF_MONTH) >= dom) {
                  set(JULIAN_DAY, jd);
              }
          } else {
              set(JULIAN_DAY, jd);
          }
      }
docs: Adjust this calendar to be delta months before or after a given
  start position, pinning the day of month if necessary.  The start
  position is given as a local days number for the start of the month
  and a day-of-month.  Used by add() and roll().
  @param newMoon the local days of the first day of the month of the
  start position (days after January 1, 1970 0:00 Asia/Shanghai)
  @param dom the 1-based day-of-month of the start position
  @param delta the number of months to move forward or backward from
  the start position