package com.intrbiz.bergamot.model.timeperiod; import java.time.Clock; import java.time.LocalDateTime; import java.util.Calendar; import com.intrbiz.bergamot.model.timeperiod.util.DayOfWeek; import com.intrbiz.bergamot.model.timeperiod.util.Month; public class DayOfWeekInMonthQualifier extends MonthQualifier { private static final long serialVersionUID = 1L; private int dayOfWeekInMonth; private DayOfWeek dayOfWeek; public DayOfWeekInMonthQualifier() { super(); } public DayOfWeekInMonthQualifier(Month month, DayOfWeek dayOfWeek, int dayOfWeekInMonth) { super(month); this.dayOfWeek = dayOfWeek; this.dayOfWeekInMonth = dayOfWeekInMonth; } public DayOfWeekInMonthQualifier(Month month, DayOfWeek dayOfWeek, int dayOfWeekInMonth, TimeRange... ranges) { super(month, ranges); this.dayOfWeek = dayOfWeek; this.dayOfWeekInMonth = dayOfWeekInMonth; } public int getDayOfWeekInMonth() { return dayOfWeekInMonth; } public void setDayOfWeekInMonth(int dayOfWeekInMonth) { this.dayOfWeekInMonth = dayOfWeekInMonth; } public DayOfWeek getDayOfWeek() { return dayOfWeek; } public void setDayOfWeek(DayOfWeek dayOfWeek) { this.dayOfWeek = dayOfWeek; } @Override public boolean isInTimeRange(Calendar calendar) { // TODO: we need better tests for this int dowim = this.dayOfWeekInMonth > 0 ? this.dayOfWeekInMonth : (calendar.getActualMaximum(Calendar.DAY_OF_WEEK_IN_MONTH) + this.dayOfWeekInMonth + 1); return calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH) == dowim && super.isInTimeRange(calendar); } @Override public LocalDateTime computeNextStartTime(Clock clock) { LocalDateTime next = super.computeNextStartTime(clock); if (next == null) return null; // compute the first x day of the week in the month if (this.dayOfWeekInMonth > 0) { next = next.withDayOfMonth(1); int addDays = this.dayOfWeek.toJavaTime().getValue() - next.getDayOfWeek().getValue(); if (addDays < 0) addDays = addDays + 7; if (addDays > 0) next = next.plusDays(addDays); // increment the weeks for (int i = (this.dayOfWeekInMonth - 1); i > 0 ; i--) { next = next.plusDays(7); } } else { next = next.withDayOfMonth(next.getMonth().maxLength()); int subDays = next.getDayOfWeek().getValue() - this.dayOfWeek.toJavaTime().getValue(); if (subDays < 0) subDays = subDays + 7; if (subDays > 0) next = next.minusDays(subDays); // decrement the weeks for (int i = (this.dayOfWeekInMonth + 1); i < 0; i++) { next = next.minusDays(7); } } // check the date is valid return (next.isAfter(LocalDateTime.now(clock))) ? next : null; } public String toString() { return this.dayOfWeek.toString().toLowerCase() + " " + this.dayOfWeekInMonth + " " + super.toString(); } }