可根据参数类型指定
每隔几天重复
每周周几
每月的某一天
每月的第几个星期的周几
生成指定次数或指定结束日期得到符合规则的日期
参数类
public class RepeatParams {
private Integer repeatType;//重复类型 1 day 2 week 3 month
private Integer repeatEvery;//重复周期间隔type为1或2有此值
private Integer repeatBy;//重复条件当type为2有此值,每周几
private Integer times;//设置次数
private Integer repeatEveryType;//1-以周为单位 2-以day为单位当type为3有此值,每月的第几天为2每月第几个星期几为1
private Integer monthDay;//当repeat_every_type为2需指定每月的几号
private Integer monthWeekTimes;//当repeat_every_type为1需指定每月的第几个星期
private Integer monthWeekDay;//当repeat_every_type为1需指定每月的周几
private String startsOn;//repeat开始时间
private String setEndOn;//设置结束时间时间
private String type;//1次数2设置结束时间
}
具体实现
public class RepeatService {
public Object previewRepeatDay(RepeatParams repeatParams) {
List<LocalDate> dates=null;
switch (repeatParams.getRepeatType()){
case 1:
dates = repeatDays(repeatParams);
break;
case 2:
dates = repeatWeek(repeatParams);
break;
case 3:
dates = repeatMonth(repeatParams);
break;
default:
return false;
}
List<Date> date = new ArrayList<>();
List<String> d = new ArrayList<>();
dates.stream().forEach(e ->{
ZoneId zone = ZoneId.systemDefault();
Instant instant = e.atStartOfDay().atZone(zone).toInstant();
Date from = Date.from(instant);
d.add(e.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
date.add(from);
});
return d;
}
private List<LocalDate> repeatDays(RepeatParams repeatParams){
List<LocalDate> localDates = new ArrayList<>();
LocalDate startsOn = LocalDate.parse(repeatParams.getStartsOn(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
localDates.add(startsOn);
//如果是设置次数
if ("1".equals(repeatParams.getType())){
if (repeatParams.getTimes()>100){
repeatParams.setTimes(100);
}
for (int i = 1 ; i<repeatParams.getTimes();i++){
LocalDate date = startsOn.plusDays(repeatParams.getRepeatEvery());
localDates.add(date);
startsOn = date;
}
//如果是设置结束时间
}else if ("2".equals(repeatParams.getType())){
LocalDate endsOn = LocalDate.parse(repeatParams.getSetEndOn(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate date = startsOn;
while (date.plusDays(repeatParams.getRepeatEvery()).isBefore(endsOn) && localDates.size()<100){
date = date.plusDays(repeatParams.getRepeatEvery());
localDates.add(date);
}
}else {
//todo 使用自定义异常
throw new RuntimeException("type value is error");
}
return localDates;
}
private List<LocalDate> repeatWeek(RepeatParams repeatParams){
List<LocalDate> localDates = new ArrayList<>();
LocalDate startsOn = LocalDate.parse(repeatParams.getStartsOn(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
int repeatBy = repeatParams.getRepeatBy();
int now = startsOn.getDayOfWeek().getValue();
//计算取得第一个repeat日期
int x = repeatBy-now;
if (x<0){
x=x+7;
}
LocalDate repeatStart = startsOn.plusDays(x);
localDates.add(repeatStart);
//如果是设置次数
if ("1".equals(repeatParams.getType())){
if (repeatParams.getTimes()>100){
repeatParams.setTimes(100);
}
for (int i = 1 ; i<repeatParams.getTimes();i++){
LocalDate date = repeatStart.plusWeeks(repeatParams.getRepeatEvery());
localDates.add(date);
repeatStart = date;
}
//如果是设置结束时间
}else if ("2".equals(repeatParams.getType())){
LocalDate endsOn = LocalDate.parse(repeatParams.getSetEndOn(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate date = repeatStart;
while (date.plusWeeks(repeatParams.getRepeatEvery()).isBefore(endsOn) && localDates.size()<100){
date = date.plusWeeks(repeatParams.getRepeatEvery());
localDates.add(date);
}
}else {
//todo 使用自定义异常
throw new RuntimeException("type value is error");
}
return localDates;
}
private List<LocalDate> repeatMonth(RepeatParams repeatParams){
LocalDate start = LocalDate.parse(repeatParams.getStartsOn(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
List<LocalDate> localDates =null;
//以周为单位
if (repeatParams.getRepeatEveryType()==1){
localDates = repeatMonthByWeek(repeatParams.getStartsOn(), repeatParams.getTimes(), repeatParams.getSetEndOn(), repeatParams.getMonthWeekDay(), repeatParams.getMonthWeekTimes(), repeatParams.getType());
//以天为单位
}else if (repeatParams.getRepeatEveryType()==2){
localDates = repeatMonthByDay(repeatParams.getStartsOn(), repeatParams.getSetEndOn(), repeatParams.getTimes(), repeatParams.getMonthDay(), repeatParams.getType());
}else {
//todo 自定义异常
throw new RuntimeException("repeatEveryType is error");
}
//会出现首天不对,做排除
for (int i = 0;i<localDates.size();i++){
if (localDates.get(i).isBefore(start)){
localDates.remove(i);
break;
}
}
return localDates;
}
private List<LocalDate> repeatMonthByDay(String startsOn, String setEndOn, Integer times, Integer monthDay, String type) {
List<LocalDate> localDates= new ArrayList<>();
LocalDate start = LocalDate.parse(startsOn, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
int startDay = start.getDayOfMonth();
int x = monthDay - startDay;
LocalDate date = null;
//获取初始值
if (x>0){
//取本月值
date = start.plusDays(x);
}else if (x==0){
//包含当天
date = start;
}else {
//取下月值
date = start.plusDays(x).plusMonths(1);
}
localDates.add(date);
//如果是设置次数
if ("1".equals(type)){
if (times>100){
times=100;
}
for (int i = 1 ; i<times;i++){
LocalDate next = date.plusMonths(1);
localDates.add(next);
date =next;
}
//如果是设置结束时间
}else if ("2".equals(type)){
LocalDate endsOn = LocalDate.parse(setEndOn, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
while (date.plusMonths(1).isBefore(endsOn) && localDates.size()<100){
date = date.plusMonths(1);
localDates.add(date);
}
}else {
//todo 使用自定义异常
throw new RuntimeException("type value is error");
}
return localDates;
}
private List<LocalDate> repeatMonthByWeek(String startsOn, Integer times, String setEndOn, Integer monthWeekDay, Integer monthWeekTimes, String type) {
List<LocalDate> localDates= new LinkedList<>();
LocalDate start = LocalDate.parse(startsOn, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//如果是设置次数
if ("1".equals(type)){
if (times>100){
times=100;
}
//计算第一天
LocalDate first = findWeekDays(monthWeekDay, monthWeekTimes, localDates, start);
//第一天不符合条件
if (first.isBefore(start)){
times++;
}
//移出数据。重新计算
localDates.remove(first);
for (int i = 0 ; i<times;i++){
findWeekDays(monthWeekDay, monthWeekTimes, localDates, start);
start = start.plusMonths(1);
}
//如果是设置结束时间
}else if ("2".equals(type)){
LocalDate endsOn = LocalDate.parse(setEndOn, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
while (start.isBefore(endsOn) && localDates.size()<100){
LocalDate weekDays = findWeekDays(monthWeekDay, monthWeekTimes, localDates, start);
//如果最后值年份 月份相等 则结束
if (weekDays.getYear()==endsOn.getYear()){
if (weekDays.getMonthValue()==endsOn.getMonthValue()){
//如果最后日期大于结束时间,需移出最后一天
if (weekDays.getDayOfMonth()>endsOn.getDayOfMonth()){
localDates.remove(weekDays);
}
start = endsOn.plusDays(1);
}else {
start = LocalDate.of(weekDays.getYear(),weekDays.getMonth(),1).plusMonths(1);
}
}else {
start = LocalDate.of(weekDays.getYear(),weekDays.getMonth(),1).plusMonths(1);
}
}
}else {
//todo 使用自定义异常
throw new RuntimeException("type value is error");
}
return localDates;
}
private LocalDate findWeekDays(Integer monthWeekDay, Integer monthWeekTimes, List<LocalDate> localDates, LocalDate start) {
//本月的第一天
LocalDate firstday = LocalDate.of(start.getYear(),start.getMonth(),1);
//本月的最后一天
LocalDate lastDay =start.with(TemporalAdjusters.lastDayOfMonth());
//返回符合条件的日期
LocalDate res =start;
//第几个
int x=0;
for (;firstday.isBefore(lastDay);firstday = firstday.plusDays(1)){
int value = firstday.getDayOfWeek().getValue();
if (value==monthWeekDay){
x++;
}
if (x==monthWeekTimes){
localDates.add(firstday);
res = firstday;
break;
}
}
return res;
}
}