一尘不染

如何在Java 8中向LocalDate添加日期的同时跳过周末?

algorithm

其他答案请参考Joda API。我想用做java.time

假设今天的日期是2015年11月26日至星期四,当我向其添加2个工作日时,我希望结果为2015年11月30日,星期一。

我正在我自己的实现上工作,但是如果已经存在的话那将是很棒的!

编辑:

除了循环之外,还有其他方法吗?

我试图派生一个像这样的函数:

Y = f(X1,X2) where
Y is actual number of days to add,
X1 is number of business days to add, 
X2 is day of the week (1-Monday to 7-Sunday)

然后给定X1X2(从日期的星期几得出),我们可以找到Y,然后使用的plusDays()方法LocalDate

到目前为止,我还无法得出它,这是不一致的。任何人都可以确认循环直到添加所需的工作日是唯一的方法吗?


阅读 654

收藏
2020-07-28

共1个答案

一尘不染

以下方法将正值逐个增加,但不包括周末workdays

public LocalDate add(LocalDate date, int workdays) {
    if (workdays < 1) {
        return date;
    }

    LocalDate result = date;
    int addedDays = 0;
    while (addedDays < workdays) {
        result = result.plusDays(1);
        if (!(result.getDayOfWeek() == DayOfWeek.SATURDAY ||
              result.getDayOfWeek() == DayOfWeek.SUNDAY)) {
            ++addedDays;
        }
    }

    return result;
}

经过一番摆弄之后,我想出了一种算法来 计算 要增加或减少的工作日数。

/**
 * @param dayOfWeek
 *            The day of week of the start day. The values are numbered
 *            following the ISO-8601 standard, from 1 (Monday) to 7
 *            (Sunday).
 * @param businessDays
 *            The number of business days to count from the day of week. A
 *            negative number will count days in the past.
 * 
 * @return The absolute (positive) number of days including weekends.
 */
public long getAllDays(int dayOfWeek, long businessDays) {
    long result = 0;
    if (businessDays != 0) {
        boolean isStartOnWorkday = dayOfWeek < 6;
        long absBusinessDays = Math.abs(businessDays);

        if (isStartOnWorkday) {
            // if negative businessDays: count backwards by shifting weekday
            int shiftedWorkday = businessDays > 0 ? dayOfWeek : 6 - dayOfWeek;
            result = absBusinessDays + (absBusinessDays + shiftedWorkday - 1) / 5 * 2;
        } else { // start on weekend
            // if negative businessDays: count backwards by shifting weekday
            int shiftedWeekend = businessDays > 0 ? dayOfWeek : 13 - dayOfWeek;
            result = absBusinessDays + (absBusinessDays - 1) / 5 * 2 + (7 - shiftedWeekend);
        }
    }
    return result;
}

用法示例:

LocalDate startDate = LocalDate.of(2015, 11, 26);
int businessDays = 2;
LocalDate endDate = startDate.plusDays(getAllDays(startDate.getDayOfWeek().getValue(), businessDays));

System.out.println(startDate + (businessDays > 0 ? " plus " : " minus ") + Math.abs(businessDays)
        + " business days: " + endDate);

businessDays = -6;
endDate = startDate.minusDays(getAllDays(startDate.getDayOfWeek().getValue(), businessDays));

System.out.println(startDate + (businessDays > 0 ? " plus " : " minus ") + Math.abs(businessDays)
        + " business days: " + endDate);

示例输出:

2015-11-26加上2个工作日:2015-11-30

2015-11-26减去6个工作日:2015-11-18

2020-07-28