I got this code
public String calculateShippingEstimateDate(LocalDateTime initialDate, Integer totalDaysToAdd, SaveOrderSourceData saveOrderSourceData) {
int workDays = totalDaysToAdd;
LocalDateTime finalDate = LocalDateTime.of(initialDate.getYear(),
initialDate.getMonth(),
initialDate.getDayOfMonth(),
initialDate.getHour(),
initialDate.getMinute(),
initialDate.getSecond());
while (workDays > 0) {
finalDate = finalDate.plusDays(1);
if (!(
DateUtility.isWeekend(finalDate.getDayOfWeek())
|| checkHolidays(saveOrderSourceData, finalDate)
)) {
workDays--;
}
}
return finalDate.toString();
}
private boolean checkHolidays(SaveOrderSourceData saveOrderSourceData, LocalDateTime finalDate) {
return saveOrderSourceData.getHolidays()
.stream().anyMatch(holiday -> getHoliday(holiday).isEqual(finalDate.toLocalDate()));
}
private LocalDate getHoliday(Holiday holiday){
return LocalDate.of(holiday.getYear(),holiday.getMonth(), holiday.getDay());
}
i'm going to explain this code.
It's important to know that the estimateDate for this example is equals to five days after the initialDate.
We have an initialDate(15/02/2022) that is equals to the finalDate.
We enter into the while loop, it validates if workdays (in this iteration is 5) is mayor to 0, it's false, so finalDate increases its value, and it validates if the date(16/02/2022) is a weekend or a holiday, and so on, when finalDate is equals to (19/02/2022) it doens't decrease the value of workDays. Finally when the finalDate is (21/02/2022) workDays is equals to 0, and finalDate is a Monday, so the while loop ends.
Holiday Class
import lombok.Builder;
import lombok.Data;
@Data
@Builder(toBuilder = true)
public class Holiday {
private final String id;
private final int year;
private final int month;
private final int day;
}
DateUtility Class
import java.time.DayOfWeek;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;
public class DateUtility {
private DateUtility() {
}
public static boolean isWeekend(DayOfWeek dayOfWeek) {
return SATURDAY.equals(dayOfWeek)
|| SUNDAY.equals(dayOfWeek);
}
}
SaveOrderSourceData class
@Data
@Builder(toBuilder = true)
public class SaveOrderSourceData {
private final List<Holiday> holidays;
}
CodePudding user response:
That will be an equivalent of your while
loop.
iterate()
takesinitialDate.plusDays(1)
as a seed, and spawns new element accordingly to the UnaryOperatordate -> date.plusDays(1)
;filter()
- lives only working days in the stream (with assumption thatDateUtility
andcheckHolidays()
do there job correctly);limit()
- as it's name suggests limit the number of elements in the stream to a given value (note,limit()
is applied when weekends or holidays are filtered out);max()
- produces the optional result, optional might be emptyinitialDate
and all other days the given range are weekends or holidays and the stream will be empty in this case;map()
- is applied on the optional if the value is present;orElse()
- provides an alternative value (as well as in your implementation it'll return theinitialDate
if no further date was found).
public String calculateShippingEstimateDate(LocalDateTime initialDate,
Integer totalDaysToAdd,
SaveOrderSourceData saveOrderSourceData) {
return Stream.iterate(initialDate.plusDays(1), date -> date.plusDays(1))
.filter(date -> !(DateUtility.isWeekend(date.getDayOfWeek())
|| checkHolidays(saveOrderSourceData, date)))
.limit(totalDaysToAdd)
.max(Comparator.naturalOrder())
.map(LocalDateTime::toString)
.orElse(initialDate.toString());
}
I've tested this solution with your utility classes it yields the same result as your imperative implementation
public static void main(String[] args) {
System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 5, SaveOrderSourceData.builder().holidays(List.<Holiday>of()).build()));
System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 5, SaveOrderSourceData.builder().holidays(List.<Holiday>of()).build()) "\n");
System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 27, SaveOrderSourceData.builder().holidays(List.of(Holiday.builder().id("id1").year(2022).month(3).day(3).build())).build()));
System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 27, SaveOrderSourceData.builder().holidays(List.of(Holiday.builder().id("id1").year(2022).month(3).day(3).build())).build()));
}
output
2022-02-22T21:43:25
2022-02-22T21:43:25
2022-03-25T21:43:25
2022-03-25T21:43:25