/** * If date is not match, will return previous closest match. If date is match, will return this * date. * * @param date - reference DateTime instance - never null; * @return DateTime instance, never null. Value obeys logic specified above. * @throws NoSuchValueException */ DateTime previousClosestMatch(DateTime date) throws NoSuchValueException { List<Integer> year = yearsValueGenerator.generateCandidates(date.getYear(), date.getYear()); TimeNode days = generateDays(cronDefinition, date); int highestMonth = months.getValues().get(months.getValues().size() - 1); int highestDay = days.getValues().get(days.getValues().size() - 1); int highestHour = hours.getValues().get(hours.getValues().size() - 1); int highestMinute = minutes.getValues().get(minutes.getValues().size() - 1); int highestSecond = seconds.getValues().get(seconds.getValues().size() - 1); NearestValue nearestValue; DateTime newDate; if (year.isEmpty()) { int previousYear = yearsValueGenerator.generatePreviousValue(date.getYear()); if (highestDay > 28) { int highestDayOfMonth = new DateTime(previousYear, highestMonth, 1, 0, 0).dayOfMonth().getMaximumValue(); if (highestDay > highestDayOfMonth) { nearestValue = days.getPreviousValue(highestDay, 1); if (nearestValue.getShifts() > 0) { newDate = new DateTime(previousYear, highestMonth, 1, 23, 59, 59, date.getZone()) .minusMonths(nearestValue.getShifts()) .dayOfMonth() .withMaximumValue(); return previousClosestMatch(newDate); } else { highestDay = nearestValue.getValue(); } } } return initDateTime( previousYear, highestMonth, highestDay, highestHour, highestMinute, highestSecond, date.getZone()); } if (!months.getValues().contains(date.getMonthOfYear())) { nearestValue = months.getPreviousValue(date.getMonthOfYear(), 0); int previousMonths = nearestValue.getValue(); if (nearestValue.getShifts() > 0) { newDate = new DateTime(date.getYear(), 12, 31, 23, 59, 59, date.getZone()) .minusYears(nearestValue.getShifts()); return previousClosestMatch(newDate); } return initDateTime( date.getYear(), previousMonths, highestDay, highestHour, highestMinute, highestSecond, date.getZone()); } if (!days.getValues().contains(date.getDayOfMonth())) { nearestValue = days.getPreviousValue(date.getDayOfMonth(), 0); if (nearestValue.getShifts() > 0) { newDate = new DateTime(date.getYear(), date.getMonthOfYear(), 1, 23, 59, 59, date.getZone()) .minusMonths(nearestValue.getShifts()) .dayOfMonth() .withMaximumValue(); return previousClosestMatch(newDate); } return initDateTime( date.getYear(), date.getMonthOfYear(), nearestValue.getValue(), highestHour, highestMinute, highestSecond, date.getZone()); } if (!hours.getValues().contains(date.getHourOfDay())) { nearestValue = hours.getPreviousValue(date.getHourOfDay(), 0); if (nearestValue.getShifts() > 0) { newDate = new DateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), 23, 59, 59, date.getZone()) .minusDays(nearestValue.getShifts()); return previousClosestMatch(newDate); } return initDateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), nearestValue.getValue(), highestMinute, highestSecond, date.getZone()); } if (!minutes.getValues().contains(date.getMinuteOfHour())) { nearestValue = minutes.getPreviousValue(date.getMinuteOfHour(), 0); if (nearestValue.getShifts() > 0) { newDate = new DateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), date.getHourOfDay(), 59, 59, date.getZone()) .minusHours(nearestValue.getShifts()); return previousClosestMatch(newDate); } return initDateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), date.getHourOfDay(), nearestValue.getValue(), highestSecond, date.getZone()); } if (!seconds.getValues().contains(date.getSecondOfMinute())) { nearestValue = seconds.getPreviousValue(date.getSecondOfMinute(), 0); int previousSeconds = nearestValue.getValue(); if (nearestValue.getShifts() > 0) { newDate = new DateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), date.getHourOfDay(), date.getMinuteOfHour(), 59, date.getZone()) .minusMinutes(nearestValue.getShifts()); return previousClosestMatch(newDate); } return initDateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), date.getHourOfDay(), date.getMinuteOfHour(), previousSeconds, date.getZone()); } return date; }