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

如何为生成的日期区间填充缺失月份的对应金额值(Java)

解决方案

现有代码的问题

  • 错误使用List<LocalDate>作为Map的Key,每次循环都会覆盖之前的条目,最终Map仅保留最后一条记录的金额,完全无法实现日期与金额的对应。
  • 生成的totalMonths未包含原始起始日期,且没有针对相邻原始记录的区间填充逻辑,无法覆盖所有需要补全的月份。

正确实现代码

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChildReports {
    private LocalDate date;
    private BigDecimal amount;
}

// 服务类中的补全方法
public List<ChildReports> fillMissingMonths(List<ChildReports> childReports) {
    // 1. 按日期排序原始数据,确保顺序正确
    List<ChildReports> sortedReports = childReports.stream()
            .sorted(Comparator.comparing(ChildReports::getDate))
            .collect(Collectors.toList());

    List<ChildReports> filledReports = new ArrayList<>();
    if (sortedReports.isEmpty()) {
        return filledReports;
    }

    // 添加第一条原始记录作为起始
    filledReports.add(sortedReports.get(0));

    // 遍历相邻记录,填充中间月份数据
    for (int i = 1; i < sortedReports.size(); i++) {
        ChildReports prevReport = sortedReports.get(i - 1);
        ChildReports currReport = sortedReports.get(i);

        LocalDate prevDate = prevReport.getDate();
        LocalDate currDate = currReport.getDate();
        BigDecimal fillAmount = prevReport.getAmount();
        int targetDay = prevDate.getDayOfMonth();

        // 生成从prevDate下一个月到currDate前一个月的所有日期
        LocalDate currentFillDate = prevDate.plusMonths(1);
        while (currentFillDate.isBefore(currDate)) {
            // 处理当月无目标日的情况(如2月无30号),自动调整为当月最后一天
            LocalDate fillDate = adjustDayIfNeeded(currentFillDate, targetDay);
            filledReports.add(ChildReports.builder()
                    .date(fillDate)
                    .amount(fillAmount)
                    .build());
            currentFillDate = currentFillDate.plusMonths(1);
        }

        // 添加当前原始记录
        filledReports.add(currReport);
    }

    return filledReports;
}

// 辅助方法:调整日期的日,避免月份天数不足的问题
private LocalDate adjustDayIfNeeded(LocalDate date, int targetDay) {
    int maxDayInMonth = date.lengthOfMonth();
    return date.withDayOfMonth(Math.min(targetDay, maxDayInMonth));
}

代码逻辑说明

  1. 排序原始数据:确保数据按日期从小到大排列,避免原始数据顺序混乱导致填充错误。
  2. 初始化结果列表:先加入第一条原始记录作为填充的起始基准。
  3. 遍历相邻记录:针对每一对相邻的原始记录,生成它们之间所有月份的补全记录:
    • 补全日期从原始前一条记录的下一个月开始,到当前原始记录的前一个月结束。
    • 补全日期保持与前一条记录的日一致,若当月没有该日(如31号遇到2月),自动调整为当月最后一天。
    • 补全金额直接复用前一条记录的金额。
  4. 添加当前记录:每处理完一段区间的补全后,加入当前的原始记录,继续下一段区间的处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:30:51