使用java.time将月份添加到特定月份

CAP*_*OCK 5 java date java-time

使用LocalDateTime或将月份添加到指定日期最干净的解决方案是什么LocalDate

很好的答案是在java.time中,如何计算一个月的结果?在JSR-310中查找一周中某天的下一次出现,因此我希望可以使用类似的干净解决方案来解决此问题。

假设用户为某个周期性任务选择一个月中的某一天(从1到31)。选择后,将生成时间戳记,并且每个月都会增加。仅存储当前月份的时间戳(没有上个月的记录,每个月都会更新时间戳)和选定的月份。

如果选择的日期是31日,并且我们从1月31日开始添加一个月,则dateTime.plusMonths(1)方法将在2016年2月29日给出。如果dateTime.plusMonths(1)再次使用method,则结果是3月29日,而预期的是3月31日。但是,它的工作日为1日至28日。

可能正在使用每月31号的变通办法,dateTime.with(TemporalAdjusters.lastDayOfMonth())但这并不涵盖从28号到30号的日子,也可能是一个月的最后几天。

lastDayOfMonth()每月第30天的选定示例:1月30日2月29日(如果前一天的前一天较高,则plusMonth方法行为选择最后一天),3月31日(预期是每月的30号)。此方法不考虑每月的选定日期。


当然,这个问题有很多潜在的解决方案,包括一些检查和计算数月与数天之间的差异,但是我仅在可能的情况下使用java.time功能寻找解决方案。

澄清度

我正在寻找一种将日期移动到选定月份的下个月的方法。喜欢dateTime.plusMonths(1).withDayOfMonth(selectedDayOfMonth)。对于2月31日这样的日期,这将引发一个异常,以withDayOfMonth覆盖plusMonths对最后一个有效日期的调整。

使用plusMonth方法的迭代示例。在上一个迭代值中,采用-想象递归。

+-----------+------------------+---------------+
| iteration | Day-of-month: 31 |   Expected    |
+-----------+------------------+---------------+
|         1 | January 31st     | January 31st  |
|         2 | February 29th    | February 29th |
|         3 | March 29th       | March 31st    |
|         4 | April 29th       | April 30th    |
+-----------+------------------+---------------+
Run Code Online (Sandbox Code Playgroud)

以及每月1日至28日的另一个工作示例。

+-----------+-------------------+--------------+
| iteration | Day-of-month: 4th |   Expected   |
+-----------+-------------------+--------------+
|         1 | January 4th       | January 4th  |
|         2 | February 4th      | February 4th |
|         3 | March 4th         | March 4th    |
|         4 | April 4th         | April 4th    |
+-----------+-------------------+--------------+
Run Code Online (Sandbox Code Playgroud)

对于leap年,可以选择每月的29号,但对于普通年份则不能。

+-----------+--------------------+---------------+
| iteration | Day-of-month: 29th |   Expected    |
+-----------+--------------------+---------------+
|         1 | January 29th       | January 29th  |
|         2 | February 28th      | February 28th |
|         3 | March 28th         | March 29th    |
|         4 | April 28th         | April 29th    |
+-----------+--------------------+---------------+
Run Code Online (Sandbox Code Playgroud)

bin*_*ary 10

将月份的日期设置为 min(selectedDayOfMonth, lastDayOfNextMonth)

public static LocalDate next(LocalDate current, int selectedDayOfMonth) {
    LocalDate next = current.plusMonths(1);
    return next.withDayOfMonth(Math.min(selectedDayOfMonth, next.lengthOfMonth()));
}
Run Code Online (Sandbox Code Playgroud)

用法:

public static void test(int selectedDayOfMonth) {
    LocalDate date = LocalDate.of(2001, Month.JANUARY, selectedDayOfMonth);
    System.out.println(date);
    for (int i = 0; i < 5; i++) {
        date = next(date, selectedDayOfMonth);
        System.out.println(date);
    }
    System.out.println();
}
Run Code Online (Sandbox Code Playgroud)

输出test(4)

2001-01-04
2001-02-04
2001-03-04
2001-04-04
2001-05-04
2001-06-04
Run Code Online (Sandbox Code Playgroud)

输出test(29)

2001-01-29
2001-02-28
2001-03-29
2001-04-29
2001-05-29
2001-06-29
Run Code Online (Sandbox Code Playgroud)

输出test(31)

2001-01-31
2001-02-28
2001-03-31
2001-04-30
2001-05-31
2001-06-30
Run Code Online (Sandbox Code Playgroud)