DefaultTimepointLimiter implements TimepointLimiter { @Override public @NonNull Timepoint roundToNearest(@NonNull Timepoint time,@Nullable Timepoint.TYPE type, @NonNull Timepoint.TYPE resolution) { if (mMinTime != null && mMinTime.compareTo(time) > 0) return mMinTime; if (mMaxTime != null && mMaxTime.compareTo(time) < 0) return mMaxTime; if (type == Timepoint.TYPE.SECOND) return time; if (!exclusiveSelectableTimes.isEmpty()) { Timepoint floor = exclusiveSelectableTimes.floor(time); Timepoint ceil = exclusiveSelectableTimes.ceiling(time); if (floor == null || ceil == null) { Timepoint t = floor == null ? ceil : floor; if (type == null) return t; if (t.getHour() != time.getHour()) return time; if (type == Timepoint.TYPE.MINUTE && t.getMinute() != time.getMinute()) return time; return t; } if (type == Timepoint.TYPE.HOUR) { if (floor.getHour() != time.getHour() && ceil.getHour() == time.getHour()) return ceil; if (floor.getHour() == time.getHour() && ceil.getHour() != time.getHour()) return floor; if (floor.getHour() != time.getHour() && ceil.getHour() != time.getHour()) return time; } if (type == Timepoint.TYPE.MINUTE) { if (floor.getHour() != time.getHour() && ceil.getHour() != time.getHour()) return time; if (floor.getHour() != time.getHour() && ceil.getHour() == time.getHour()) { return ceil.getMinute() == time.getMinute() ? ceil : time; } if (floor.getHour() == time.getHour() && ceil.getHour() != time.getHour()) { return floor.getMinute() == time.getMinute() ? floor : time; } if (floor.getMinute() != time.getMinute() && ceil.getMinute() == time.getMinute()) return ceil; if (floor.getMinute() == time.getMinute() && ceil.getMinute() != time.getMinute()) return floor; if (floor.getMinute() != time.getMinute() && ceil.getMinute() != time.getMinute()) return time; } int floorDist = Math.abs(time.compareTo(floor)); int ceilDist = Math.abs(time.compareTo(ceil)); return floorDist < ceilDist ? floor : ceil; } if (!mDisabledTimes.isEmpty()) { if (type != null && type == resolution) return time; if (resolution == Timepoint.TYPE.SECOND) { if (!mDisabledTimes.contains(time)) return time; return searchValidTimePoint(time, type, resolution); } if (resolution == Timepoint.TYPE.MINUTE) { Timepoint ceil = mDisabledTimes.ceiling(time); Timepoint floor = mDisabledTimes.floor(time); boolean ceilDisabled = time.equals(ceil, Timepoint.TYPE.MINUTE); boolean floorDisabled = time.equals(floor, Timepoint.TYPE.MINUTE); if (ceilDisabled || floorDisabled) return searchValidTimePoint(time, type, resolution); return time; } if (resolution == Timepoint.TYPE.HOUR) { Timepoint ceil = mDisabledTimes.ceiling(time); Timepoint floor = mDisabledTimes.floor(time); boolean ceilDisabled = time.equals(ceil, Timepoint.TYPE.HOUR); boolean floorDisabled = time.equals(floor, Timepoint.TYPE.HOUR); if (ceilDisabled || floorDisabled) return searchValidTimePoint(time, type, resolution); return time; } } return time; } DefaultTimepointLimiter(); @SuppressWarnings("WeakerAccess")  DefaultTimepointLimiter(Parcel in); @Override void writeToParcel(Parcel out, int flags); @Override int describeContents(); @Override boolean isOutOfRange(@Nullable Timepoint current, int index, @NonNull Timepoint.TYPE resolution); boolean isOutOfRange(@NonNull Timepoint current); @SuppressWarnings("SimplifiableIfStatement") @Override boolean isAmDisabled(); @SuppressWarnings("SimplifiableIfStatement") @Override boolean isPmDisabled(); @Override @NonNull Timepoint roundToNearest(@NonNull Timepoint time,@Nullable Timepoint.TYPE type, @NonNull Timepoint.TYPE resolution); @SuppressWarnings("WeakerAccess")
    static final Parcelable.Creator<DefaultTimepointLimiter> CREATOR; }
@Test public void roundToNearestShouldReturnInputIfNotOutOfRange() { Timepoint input = new Timepoint(12, 13, 14); DefaultTimepointLimiter limiter = new DefaultTimepointLimiter(); Assert.assertEquals(limiter.roundToNearest(input, null, Timepoint.TYPE.SECOND), input); }