You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Java基于自定义节假日日历计算指定天数后的工作日

基于自定义节假日计算下一个工作日的Java实现

嘿,这个需求在业务场景里真的很常见!先帮你捋捋现有代码里的小问题,再给你推荐更简洁可靠的实现方式~

先说说你现有代码的小问题

你的思路方向是对的,但有几个细节需要调整:

  • checkIfNonWorkingDay的逻辑搞反了:如果日期在节假日列表里,应该属于非工作日,这个方法应该返回true表示当天是休息日,但你现在的逻辑刚好相反,会导致循环计算出错。
  • 使用SimpleDateFormatCalendar这些旧API,它们不仅线程不安全,代码写起来也繁琐冗余,Java 8之后官方推荐用java.time包下的新日期API。
  • ArrayList存储节假日,contains操作的时间复杂度是O(n),如果节假日数量较多,换成HashSet会大幅提升查询效率。

更简便的Java 8+实现方式

Java 8引入的java.time包(JSR-310)提供了线程安全、类型安全的日期处理工具,用它来实现这个需求会简洁很多。我们可以这样做:

  1. 把自定义节假日转换成LocalDate的集合(推荐用Set提升查询效率)
  2. 从起始日期开始,逐日往后遍历,判断当天是否是工作日(非周六周日 + 不在节假日列表中)
  3. 每找到一个工作日,就把需要添加的工作日天数减1,直到减到0为止

下面是完整的示例代码,完全匹配你给出的测试场景:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;

public class NextWorkingDayCalculator {

    public static void main(String[] args) {
        // 测试示例:当前日期3月9日,节假日3月10日、12日、13日,添加5个工作日
        LocalDate startDate = LocalDate.of(2024, 3, 9);
        int addWorkDays = 5;
        Set<LocalDate> holidays = new HashSet<>();
        holidays.add(LocalDate.of(2024, 3, 10));
        holidays.add(LocalDate.of(2024, 3, 12));
        holidays.add(LocalDate.of(2024, 3, 13));

        LocalDate nextWorkingDay = calculateNextWorkingDay(startDate, addWorkDays, holidays);
        System.out.println("预期结果:2024-03-17,实际计算结果:" + nextWorkingDay);
    }

    public static LocalDate calculateNextWorkingDay(LocalDate startDate, int workDaysToAdd, Set<LocalDate> holidays) {
        LocalDate currentDate = startDate;
        int remainingDays = workDaysToAdd;

        while (remainingDays > 0) {
            // 往后推一天
            currentDate = currentDate.plusDays(1);
            // 判断是否是工作日:非周末 + 不在节假日列表
            DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
            if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY && !holidays.contains(currentDate)) {
                remainingDays--;
            }
        }

        return currentDate;
    }
}

代码优势说明

  • 类型安全:用LocalDate直接处理日期,避免了旧API的类型转换和空值风险
  • 效率更高HashSetcontains操作是O(1)时间复杂度,节假日数量多的时候优势明显
  • 可读性强plusDays()getDayOfWeek()这些方法语义明确,逻辑一目了然
  • 线程安全java.time下的所有类都是不可变设计,天生支持多线程场景

如果需要兼容Java 8之前的版本,可以考虑使用Joda-Time库(它是java.time的前身),不过现在更推荐尽量升级到Java 8+版本哦。

内容的提问来源于stack exchange,提问作者kamathsachin7

火山引擎 最新活动