Java每月重复次数

问题描述

我正在尝试获取特定期间的每月重复日期。除了我指定的重复日期为30以外,下面的代码有效,然后生成以下错误,这是正常的:

线程“ main”中的异常java.time.DateTimeException:无效的日期“ FEBRUARY 30”

我的问题是:如果指定的重复日期(天)高于该月的最后一天,是否可以将重复周期设置为该月的最后一天?

谢谢!

public class MonthlyRecurrence {
    public static void main(String[] args) {

        LocalDate startDate = LocalDate.of(2020,10,6);
        LocalDate endDate = LocalDate.of(2021,12,31);
        int dayOfMonth = 30;

        List<LocalDate> reportDates = getReportDates(startDate,endDate,dayOfMonth);
        System.out.println(reportDates);
    }

    private static List<LocalDate> getReportDates(LocalDate startDate,LocalDate endDate,int dayOfMonth) {
        List<LocalDate> dates = new ArrayList<>();
        LocalDate reportDate = startDate;
        
        while (reportDate.isBefore(endDate)) {
            reportDate = reportDate.plusMonths(1).withDayOfMonth(dayOfMonth);
            dates.add(reportDate);
        }
        return dates;
    }
    }

解决方法

您需要指定TemporalAdjuster来获取每月的特定日期,而与月份的长度无关。它作为第三个参数传递给您的方法。

因为我不确定您想要什么,所以我包括了两个调节器。一个月的特定日期,一个月的最后一天。它们可以互换使用。但是,后者不会到达Dec 31,2021,因为before排除了==

LocalDate startDate = LocalDate.of(2020,10,6);
LocalDate endDate = LocalDate.of(2021,12,31);

// Adjuster for a specific day
int dayOfMonth = 30;  // must be final or effectively final
                      // as it is used in the following lambda.
TemporalAdjuster specificDay = 
        date-> {
            LocalDate ld = (LocalDate)date;
            int max = ld.getMonth().length(ld.isLeapYear());
            int day = dayOfMonth > max ? max : dayOfMonth;
            return date.with(ChronoField.DAY_OF_MONTH,day);
};
        
        
// Adjuster for the lastDay of the month.
TemporalAdjuster lastDay = TemporalAdjusters.lastDayOfMonth();
    
List<LocalDate> reportDates =
        getReportDates(startDate,endDate,specificDay);

reportDates.forEach(System.out::println);
    
private static List<LocalDate> getReportDates(LocalDate startDate,LocalDate endDate,TemporalAdjuster specificDay) {
    List<LocalDate> dates = new ArrayList<>();
    
    // round up start day to specificDay
    LocalDate reportDate = startDate.with(specificDay);
    
    while (reportDate.isBefore(endDate)) {
        dates.add(reportDate);
        reportDate = reportDate.plusMonths(1).with(specificDay);
    }
    return dates;
}

根据TemporalAdjuster的选择打印以下内容


SpecificDay (30th)  LastDayOfMonth
    2020-10-30        2020-10-31
    2020-11-30        2020-11-30
    2020-12-30        2020-12-31
    2021-01-30        2021-01-31
    2021-02-28        2021-02-28
    2021-03-30        2021-03-31
    2021-04-30        2021-04-30
    2021-05-30        2021-05-31
    2021-06-30        2021-06-30
    2021-07-30        2021-07-31
    2021-08-30        2021-08-31
    2021-09-30        2021-09-30
    2021-10-30        2021-10-31
    2021-11-30        2021-11-30
    2021-12-30