java - 使用 java.time 将月份添加到每月的特定日期

标签 java date java-time

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

不错的答案是 In java.time, how is the result of adding a month calculated?Find next occurrence of a day-of-week in JSR-310所以我希望这个问题可以用类似的干净解决方案来解决。

假设用户选择一个月中的某一天(从 1 到 31 中的任意一天)执行某个周期性任务。选择时间戳后生成并每月增加。仅存储当前月份的时间戳(没有上个月的轨迹,时间戳每月更新)和选定的月份日期。

如果选择的日期是31 日 并且我们从1 月31 日 开始,使用dateTime.plusMonths(1) 方法添加一个月会得到 2016 年 2 月 29 日。如果再次使用 dateTime.plusMonths(1) 方法,结果为 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    |
+-----------+------------------+---------------+

另一个工作示例是从 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    |
+-----------+-------------------+--------------+

月 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    |
+-----------+--------------------+---------------+

最佳答案

将月中的第几天设置为 min(selectedDayOfMonth, lastDayOfNextMonth)

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

用法:

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();
}

test(4) 的输出:

2001-01-04
2001-02-04
2001-03-04
2001-04-04
2001-05-04
2001-06-04

test(29) 的输出:

2001-01-29
2001-02-28
2001-03-29
2001-04-29
2001-05-29
2001-06-29

test(31) 的输出:

2001-01-31
2001-02-28
2001-03-31
2001-04-30
2001-05-31
2001-06-30

关于java - 使用 java.time 将月份添加到每月的特定日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39046324/

相关文章:

java - Android 假设 "main/UI thread"ID 始终为 1 是否安全?

java - JFormattedTextField 未正确清除

java - eclipse tomcat设置页面中的Tomcat URIEncoding ="UTF-8"

javascript - 如何使用knockout JS 验证日期(年份)?

使用 Date 对象的 Java 执行方法

swift - 比较今天和过去的日期

java - 如何从 Instant 和时间字符串构造 ZonedDateTime?

Java mysql 插入jtable多条数据到mysql数据库

java - 使用 DateTimeFormatter 显示短时区名称

java - 如何将日期截断/跨度为一个时间间隔?