public Calendar floor(Calendar cal) {
        Calendar twoYearsAgo = (Calendar) cal.clone();
        twoYearsAgo.add(Calendar.YEAR, -2);

        OUTER:
        while (true) {
            if (cal.compareTo(twoYearsAgo) < 0) {
                // we went too far into the past
                throw new RareOrImpossibleDateException();
            }
            for (CalendarField f : CalendarField.ADJUST_ORDER) {
                int cur = f.valueOf(cal);
                int next = f.floor(this,cur);
                if (cur==next)  continue;   // this field is already in a good shape. move on to next

                // we are modifying this field, so clear all the lower level fields
                for (CalendarField l=f.lowerField; l!=null; l=l.lowerField)
                    l.clear(cal);

                if (next<0) {
                    // we need to borrow from the next field.
                    f.rollUp(cal,-1);
                    // the problem here, in contrast with the ceil method, is that
                    // the maximum value of the field is not always a fixed value (that is, day of month)
                    // so we zero-clear all the lower fields, set the desired value +1,
                    f.setTo(cal,f.last(this));
                    f.addTo(cal,1);
                    // then subtract a minute to achieve maximum values on all the lower fields,
                    // with the desired value in 'f'
                    CalendarField.MINUTE.addTo(cal,-1);
                    // since higher order field is affected by this, we need to restart from all over
                    continue OUTER;
                } else {
                    f.setTo(cal,next);
                    f.addTo(cal,1);
                    CalendarField.MINUTE.addTo(cal,-1);
                    if (f.redoAdjustmentIfModified)
                        continue OUTER; // when we modify DAY_OF_MONTH and DAY_OF_WEEK, do it all over from the top
                }
            }
            return cal; // all fields adjusted
        }
    }
public Calendar floor ( Calendar cal ) { Calendar twoYearsAgo = ( Calendar ) cal . clone ( ) ; twoYearsAgo . add ( Calendar . YEAR , - 2 ) ; OUTER : while ( true ) { if ( cal . compareTo ( twoYearsAgo ) < 0 ) { throw new RareOrImpossibleDateException ( ) ; } for ( CalendarField f : CalendarField . ADJUST_ORDER ) { int cur = f . valueOf ( cal ) ; int next = f . floor ( this , cur ) ; if ( cur == next ) continue ; for ( CalendarField l = f . lowerField ; l != null ; l = l . lowerField ) l . clear ( cal ) ; if ( next < 0 ) { f . rollUp ( cal , - 1 ) ; f . setTo ( cal , f . last ( this ) ) ; f . addTo ( cal , 1 ) ; CalendarField . MINUTE . addTo ( cal , - 1 ) ; continue OUTER ; } else { f . setTo ( cal , next ) ; f . addTo ( cal , 1 ) ; CalendarField . MINUTE . addTo ( cal , - 1 ) ; if ( f . redoAdjustmentIfModified ) continue OUTER ; } } return cal ; } }
See {@link #floor(long)}

This method modifies the given calendar and returns the same object.

@throws RareOrImpossibleDateException if the date isn't hit in the 2 years before it indicates an impossible
(e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49