|
6 | 6 | import de.focus_shift.jollyday.core.parser.functions.FindWeekDayInMonth; |
7 | 7 | import de.focus_shift.jollyday.core.parser.predicates.ValidLimitation; |
8 | 8 | import de.focus_shift.jollyday.core.spi.Holidays; |
9 | | -import de.focus_shift.jollyday.core.spi.Relation; |
| 9 | +import de.focus_shift.jollyday.core.spi.RelativeToWeekdayInMonth; |
10 | 10 |
|
11 | 11 | import java.time.LocalDate; |
12 | 12 | import java.time.Year; |
13 | 13 | import java.util.List; |
14 | 14 |
|
| 15 | +import static de.focus_shift.jollyday.core.spi.Relation.BEFORE; |
15 | 16 | import static java.util.stream.Collectors.toList; |
16 | 17 |
|
17 | 18 | /** |
18 | | - * <p> |
19 | 19 | * RelativeToWeekdayInMonthParser class. |
20 | | - * </p> |
| 20 | + * <p> |
| 21 | + * Resolves the holiday date for a given relative-to-weekday-in-month configuration. |
| 22 | + * <p> |
| 23 | + * This method works as follows: |
| 24 | + * <ul> |
| 25 | + * <li>Finds the base date in the month using the weekdayInMonth configuration.</li> |
| 26 | + * <li>Calculates the difference in days to the target weekday, considering the direction (BEFORE or AFTER).</li> |
| 27 | + * <li>Returns a Holiday for the resulting date.</li> |
| 28 | + * </ul> |
21 | 29 | */ |
22 | 30 | public class RelativeToWeekdayInMonthParser implements HolidayParser { |
23 | 31 |
|
24 | 32 | @Override |
25 | 33 | public List<Holiday> parse(final Year year, final Holidays holidays) { |
26 | 34 | return holidays.relativeToWeekdayInMonth().stream() |
27 | 35 | .filter(new ValidLimitation(year)) |
28 | | - .map(rwm -> { |
29 | | - LocalDate date = new FindWeekDayInMonth(year).apply(rwm.weekdayInMonth()).plusDays(1); |
30 | | - int direction = rwm.when() == Relation.BEFORE ? -1 : 1; |
31 | | - while (date.getDayOfWeek() != rwm.weekday()) { |
32 | | - date = date.plusDays(direction); |
33 | | - } |
34 | | - return new CreateHoliday(date).apply(rwm); |
35 | | - }) |
| 36 | + .map(relativeToWeekdayInMonth -> resolveHolidayForRelativeToWeekdayInMonth(year, relativeToWeekdayInMonth)) |
36 | 37 | .collect(toList()); |
37 | 38 | } |
| 39 | + |
| 40 | + private Holiday resolveHolidayForRelativeToWeekdayInMonth(final Year year, final RelativeToWeekdayInMonth rwm) { |
| 41 | + final LocalDate baseDate = new FindWeekDayInMonth(year).apply(rwm.weekdayInMonth()); |
| 42 | + |
| 43 | + final int currentDayValue = baseDate.getDayOfWeek().getValue(); |
| 44 | + final int targetDayValue = rwm.weekday().getValue(); |
| 45 | + final int direction = (rwm.when() == BEFORE ? -1 : 1); |
| 46 | + |
| 47 | + int daysDifference = targetDayValue - currentDayValue; |
| 48 | + if (direction < 0 && daysDifference >= 0) { |
| 49 | + daysDifference -= 7; |
| 50 | + } else if (direction > 0 && daysDifference <= 0) { |
| 51 | + daysDifference += 7; |
| 52 | + } |
| 53 | + |
| 54 | + final LocalDate resultDate = baseDate.plusDays(daysDifference); |
| 55 | + return new CreateHoliday(resultDate).apply(rwm); |
| 56 | + } |
38 | 57 | } |
0 commit comments