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

Laravel 使用Carbon按自然年拆分日期并生成对应月份统计表格

实现方案

核心逻辑

按自然年拆分日期区间可以直接通过遍历涉及年份计算边界,也可以通过日期差值逐月循环累加实现,两种方式都可以用Carbon快速完成,以下是符合你需求的实现代码:


方案1:按年遍历实现(效率更高)

use Carbon\Carbon;

// 初始化起止日期
$startDate = Carbon::parse('2018-10-01');
$endDate = Carbon::parse('2020-08-01');
$splitResult = [];

// 同一年直接返回单个区间
if ($startDate->year == $endDate->year) {
    $splitResult[] = [
        'year' => $startDate->year,
        'period_start' => $startDate->format('Y/m/d'),
        'period_end' => $endDate->format('Y/m/d'),
        'months' => $startDate->diffInMonths($endDate)
    ];
} else {
    // 遍历所有涉及的自然年
    for ($year = $startDate->year; $year <= $endDate->year; $year++) {
        if ($year == $startDate->year) {
            // 首年边界处理
            $currentStart = $startDate->copy();
            $currentEnd = Carbon::create($year, 12, 31);
        } elseif ($year == $endDate->year) {
            // 结束年边界处理
            $currentStart = Carbon::create($year, 1, 1);
            $currentEnd = $endDate->copy();
        } else {
            // 中间完整年处理
            $currentStart = Carbon::create($year, 1, 1);
            $currentEnd = Carbon::create($year, 12, 31);
        }
        // 计算间隔月份,diffInMonths默认返回完整满月差值,和你示例的计算规则对齐
        $months = $currentStart->diffInMonths($currentEnd);
        $splitResult[] = [
            'year' => $year,
            'period_start' => $currentStart->format('Y/m/d'),
            'period_end' => $currentEnd->format('Y/m/d'),
            'months' => $months
        ];
    }
}

// 输出结果可直接用于生成统计表格
dd($splitResult);

测试用例输出结果

array:3 [
  0 => array:4 [
    "year" => 2018
    "period_start" => "2018/10/01"
    "period_end" => "2018/12/31"
    "months" => 2
  ]
  1 => array:4 [
    "year" => 2019
    "period_start" => "2019/01/01"
    "period_end" => "2019/12/31"
    "months" => 12
  ]
  2 => array:4 [
    "year" => 2020
    "period_start" => "2020/01/01"
    "period_end" => "2020/08/01"
    "months" => 7
  ]
]

如果你需要统计包含首尾月的总月份数,将月份计算逻辑改为$currentStart->diffInMonths($currentEnd->copy()->addDay()) + 1即可。


方案2:日期差值循环实现

如果你要求必须通过循环日期差值的方式实现,可以按月步进累加统计:

use Carbon\Carbon;

$startDate = Carbon::parse('2018-10-01');
$endDate = Carbon::parse('2020-08-01');
$splitResult = [];
$currentDate = $startDate->copy();

while ($currentDate->lte($endDate)) {
    $year = $currentDate->year;
    // 初始化当前年份的区间
    if (!isset($splitResult[$year])) {
        $splitResult[$year] = [
            'year' => $year,
            'period_start' => $currentDate->format('Y/m/d'),
            'months' => 0
        ];
    }
    $splitResult[$year]['months']++;
    // 计算当前年的区间结束日期
    $yearEnd = $year == $endDate->year ? $endDate : Carbon::create($year, 12, 31);
    $splitResult[$year]['period_end'] = min($currentDate->copy()->endOfMonth(), $yearEnd)->format('Y/m/d');
    // 步进1个月循环
    $currentDate->addMonth();
}

// 重置数组索引
$splitResult = array_values($splitResult);
dd($splitResult);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 16:06:04