You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Reactive WebFlux调用外部API并计算工作日数的问题

解决方案:响应式计算两日之间的工作日数

核心思路

先将API返回的节假日集合转为Set<LocalDate>(方便快速查找),再遍历起止日期范围内的每一天,过滤掉周六、周日及节假日后统计数量。以下是具体实现步骤和代码:


1. 日期格式转换工具方法

先处理前端和API的日期格式差异:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

// 解析前端传入的dd/mm/yyyy格式日期
private LocalDate parseFrontendDate(String dateStr) {
    return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}

// 解析API返回的yyyy-MM-dd格式日期(默认ISO格式,直接调用parse即可)
private LocalDate parseApiDate(String dateStr) {
    return LocalDate.parse(dateStr);
}

2. 响应式工作日数计算实现

根据你的CompanyCalendarService,在getDaysCount方法中结合Flux完成逻辑:

import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;
import java.util.Set;
import java.util.stream.Collectors;
import java.time.DayOfWeek;

public Mono<Integer> getWorkDaysCount(String startDateStr, String endDateStr) {
    LocalDate start = parseFrontendDate(startDateStr);
    LocalDate end = parseFrontendDate(endDateStr);

    // 1. 将Flux<CompanyHolidayCalendar>转为Mono<Set<LocalDate>>
    Mono<Set<LocalDate>> holidaysSet = yourHolidayApiClient.getHolidays() // 替换为你获取Flux的实际方法
            .map(holidayDto -> parseApiDate(holidayDto.getDate())) // 假设CompanyHolidayCalendar有getDate()返回日期字符串
            .collect(Collectors.toSet());

    // 2. 遍历日期范围,过滤工作日并排除节假日
    return holidaysSet.map(holidays -> {
        int workDayCount = 0;
        LocalDate currentDate = start;
        
        while (!currentDate.isAfter(end)) {
            DayOfWeek day = currentDate.getDayOfWeek();
            // 排除周六、周日,且不在节假日集合中
            if (day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY && !holidays.contains(currentDate)) {
                workDayCount++;
            }
            currentDate = currentDate.plusDays(1);
        }
        return workDayCount;
    });
}

3. 大日期范围优化(可选)

如果起止日期跨度极大(如跨年),用Flux.generate生成日期流更贴合响应式风格,避免同步循环的潜在性能问题:

return holidaysSet.flatMap(holidays -> 
    Flux.generate(() -> start, (current, sink) -> {
            if (current.isAfter(end)) {
                sink.complete();
            } else {
                sink.next(current);
            }
            return current.plusDays(1);
        })
        .filter(date -> {
            DayOfWeek day = date.getDayOfWeek();
            return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY && !holidays.contains(date);
        })
        .count()
        .map(Long::intValue)
);

关键注意事项

  • 日期转换时建议添加异常处理(如前端传错格式),可结合try-catch或DateTimeFormatter的宽松模式。
  • 确保API返回的节假日数据覆盖起止日期的所有年份,避免漏判节假日。
  • 所有外部API调用必须保持响应式(使用WebClient的retrieve().bodyToFlux(...)),不要切换到同步阻塞操作。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 00:35:31