限时折扣的执行计划
创建限时折扣活动, 折扣时间: 08:00 ~ 11:00
- 活动时间:2016-12-01 10:00:00 ~ 2016-12-10 10:00:00, 每天重复
生成的执行计划如下: 2016-12-02 08:00:00 ~ 2016-12-02 11:00:00 2016-12-03 08:00:00 ~ 2016-12-03 11:00:00 2016-12-04 08:00:00 ~ 2016-12-04 11:00:00 2016-12-05 08:00:00 ~ 2016-12-05 11:00:00 2016-12-06 08:00:00 ~ 2016-12-06 11:00:00 2016-12-07 08:00:00 ~ 2016-12-07 11:00:00 2016-12-08 08:00:00 ~ 2016-12-08 11:00:00 2016-12-09 08:00:00 ~ 2016-12-09 11:00:00
- 活动时间:2016-12-01 10:00:00 ~ 2016-12-30 10:00:00, 每天重复, 重复日期 1,2,4 代表周一、周二、周四
生成的执行计划如下: 2016-12-05 08:00:00 ~ 2016-12-05 11:00:00 2016-12-06 08:00:00 ~ 2016-12-06 11:00:00 2016-12-08 08:00:00 ~ 2016-12-08 11:00:00 2016-12-12 08:00:00 ~ 2016-12-12 11:00:00 2016-12-13 08:00:00 ~ 2016-12-13 11:00:00 2016-12-15 08:00:00 ~ 2016-12-15 11:00:00 2016-12-19 08:00:00 ~ 2016-12-19 11:00:00 2016-12-20 08:00:00 ~ 2016-12-20 11:00:00 2016-12-22 08:00:00 ~ 2016-12-22 11:00:00 2016-12-26 08:00:00 ~ 2016-12-26 11:00:00 2016-12-27 08:00:00 ~ 2016-12-27 11:00:00 2016-12-29 08:00:00 ~ 2016-12-29 11:00:00
- 活动时间:2016-12-01 10:00:00 ~ 2017-02-10 10:00:00, 每月重复, 重复日期9号
生成的执行计划如下: 2016-12-02 08:00:00 ~ 2016-12-02 11:00:00 2016-12-03 08:00:00 ~ 2016-12-03 11:00:00 2016-12-04 08:00:00 ~ 2016-12-04 11:00:00
/**
* 活动开始时间
*/
private LocalDateTime startTime;
/**
* 活动结束时间
*/
private LocalDateTime endTime;
/**
* 限时折扣优惠规则
*/
private static final Integer EVERY_DAY = 1;
private static final Integer EVERY_MONTH = 2;
private static final Integer EVERY_WEEK = 3;
/**
* 是否重复, 0: 不重复, 1: 重复
*/
private Integer isRepeat;
/**
* 重复周期, 1: 每天, 2: 每月, 3: 每周
*/
private Integer repeatCycle;
/**
* 重复周期数, 几号或者周几, 周类型用","分隔
*/
private String cycleValue;
/**
* 起始时间
*/
private String startTime;
/**
* 结束时间
*/
private String endTime;
private List<DiscountExecutePlan> generateExecutePlan() {
Activity activity = getActivity();
List<DiscountExecutePlan> executePlans = new ArrayList<>();
if (AppConstants.NO.equals(isRepeat)) {
executePlans.add(DiscountExecutePlan.of(activity.getId(), activity.getOwner(),
activity.getStartTime(), activity.getEndTime()));
return executePlans;
}
LocalTime startTime = LocalTime.parse(this.startTime, DateTimeFormatter.ISO_LOCAL_TIME);
LocalTime endTime = LocalTime.parse(this.endTime, DateTimeFormatter.ISO_LOCAL_TIME);
if (EVERY_DAY.equals(repeatCycle)) {
generateDayPlans(startTime, endTime, executePlans);
} else if (EVERY_MONTH.equals(repeatCycle)) {
generateMonthPlans(startTime, endTime, executePlans);
} else if (EVERY_WEEK.equals(repeatCycle)) {
generateWeekPlans(startTime, endTime, executePlans);
}
return executePlans;
}
private void generateDayPlans(LocalTime startTime, LocalTime endTime, List<DiscountExecutePlan> executePlans) {
if (isAllDay()) {
// 合并
}
LocalDateTime start = getActivity().getStartTime();
while (start.isBefore(getActivity().getEndTime())) {
addPlan(start, startTime, endTime, executePlans);
start = start.plusDays(1);
}
}
private void generateMonthPlans(LocalTime startTime, LocalTime endTime, List<DiscountExecutePlan> executePlans) {
LocalDateTime start = getActivity().getStartTime().withDayOfMonth(Integer.parseInt(cycleValue));
if (start.isBefore(getActivity().getStartTime())) {
start.plusMonths(1);
}
while (start.isBefore(getActivity().getEndTime())) {
addPlan(start, startTime, endTime, executePlans);
start = start.plusMonths(1);
}
}
private void generateWeekPlans(LocalTime startTime, LocalTime endTime, List<DiscountExecutePlan> executePlans) {
LocalDateTime start = getActivity().getStartTime().minusDays(7);
int[] weekDays = Stream.of(cycleValue.split(",")).mapToInt(Integer::parseInt).toArray();
while (start.isBefore(getActivity().getEndTime())) {
for (int weekDay : weekDays) {
LocalDateTime base = start.plusDays(weekDay + 7 - start.getDayOfWeek().getValue());
addPlan(base, startTime, endTime, executePlans);
}
start = start.plusDays(7);
}
if (isAllDay()) {
// 合并相邻的
}
}
private void addPlan(LocalDateTime base, LocalTime startTime, LocalTime endTime, List<DiscountExecutePlan> executePlans) {
LocalDateTime start = LocalDateTime.of(base.toLocalDate(), startTime);
LocalDateTime end = LocalDateTime.of(base.toLocalDate(), endTime);
if (start.isBefore(getActivity().getStartTime()) || end.isAfter(getActivity().getEndTime())) {
return;
}
executePlans.add(DiscountExecutePlan.of(getActivity().getId(), getActivity().getOwner(),
start, end));
}
private boolean isAllDay() {
return startTime.equals("00:00") && endTime.equals("24:00");
}
public static void main(String[] args) {
Activity activity = Activity.builder()
.id(IdGenerator.activityId())
.startTime(LocalDateTime.now().plusDays(2))
.endTime(LocalDateTime.now().plusDays(60))
.build();
DiscountRule rule = DiscountRule.builder()
.isRepeat(1)
.repeatCycle(EVERY_DAY)
.startTime("08:00")
.endTime("10:00")
.build();
rule.setActivity(activity);
List<DiscountExecutePlan> dayPlans = rule.generateExecutePlan();
System.out.println(dayPlans);
rule.setRepeatCycle(EVERY_MONTH);
rule.setCycleValue("25");
List<DiscountExecutePlan> monthPlans = rule.generateExecutePlan();
System.out.println(monthPlans);
rule.setRepeatCycle(EVERY_WEEK);
rule.setCycleValue("1,2,4,6");
List<DiscountExecutePlan> weekPlans = rule.generateExecutePlan();
System.out.println(weekPlans);
}