Laravel 大V Povilas Korop(@PovilasKorop)分享了一条超级实用的 Tip

“Did you know CarbonPeriod can generate every date in a range? No more missing days in your charts.”

HD2TEOxW0AAAEne.jpg

CarbonPeriod::create(now()->subdays(29), now());

就这么一行,瞬间唤起了我的痛苦记忆……

这让我想起曾经吃过的苦,相信很多人也有过类似的经历:做报表、仪表盘、排班表、日历的时候,最头疼的就是数据不连续:某天没订单、某天没人预约,图表上就会出现断档,看起来很丑、分析也很麻烦。

下载.jpg

为什么呢?

因为在 PHP 里,手动处理日期区间简直是走“雷区”:

  • 今天 31 号,减一个月直接变成 3 月 3 号?
  • 跨年、跨闰年、夏令时切换,一不小心就少一天或多一天
  • 用 strtotime() + for 循环写出来的代码,又丑又容易出 bug
  • 做报表时最怕“某天突然没数据”,图表出现断档,领导一看就皱眉头

CarbonPeriod 正是专门解决痛点问题的利器,所以今天顺手分享给大家,以免还有人不知道而上当受罪。

什么是 CarbonPeriod?

CarbonPeriod 是 Laravel 自带的 Carbon 库提供的日期区间生成器。它可以按照你指定的起始日期、结束日期、间隔,生成一个完整的 Carbon 实例集合(可迭代)。

当然,CarbonPeriod 不限于仅在 Laravel 框架中使用。它是一个独立的 PHP 包,任何 PHP 项目都可以安装并使用。

CarbonPeriod 可以按照你指定的起始日期、结束日期和间隔,生成一个完整、连续、可迭代的 Carbon 实例集合,干净、优雅、少坑。

最简单用法:

use Carbon\CarbonPeriod;

$period = CarbonPeriod::create('2026-03-01', '2026-03-31'); // 默认每天

foreach ($period as $date) {
    echo $date->format('Y-m-d') . PHP_EOL;
}

支持自定义间隔、过滤、排除首尾等,功能非常强大。

CarbonPeriod 的 7 个实战妙用(强烈推荐收藏)

以下是社区和实际项目中最常用、最好用的场景,附完整代码示例:

1. 报表/图表补全日期(最经典用法)
没有数据的日期也显示出来(零值填充):

$period = CarbonPeriod::create($startDate, $endDate);
// 或 CarbonPeriod::since($startDate)->until($endDate);

$dailyData = YourModel::whereBetween('date', [$startDate, $endDate])
    ->groupBy('date')
    ->get()
    ->pluck('value', 'date');

$chartData = $period->map(fn($date) => [
    'date'  => $date->format('Y-m-d'),
    'value' => $dailyData[$date->format('Y-m-d')] ?? 0,
]);

2. 生成工作日历(只保留周一~周五)

$period = CarbonPeriod::create($start, $end)
    ->filter(fn($date) => $date->isWeekday());

$workingDays = $period->map(fn($date) => $date->format('Y-m-d'));

3. 生成每小时/每15分钟的时间槽(预约系统神器)

$period = CarbonPeriod::create('09:00', '18:00', '30 minutes');

$slots = $period->map(fn($time) => $time->format('H:i'));

4. 生成每周/每月汇总维度(报表分组)

// 每周
$period = CarbonPeriod::create($start, $end, '1 week');

// 每月
$period = CarbonPeriod::create($start, $end, '1 month');

5. 生成特定星期几的日期列表(比如只周一的会议)

$period = CarbonPeriod::create($start, $end)
    ->filter(fn($date) => $date->isMonday());

6. 生成测试数据 / 假数据(超级好用)

$fakeDates = CarbonPeriod::create(now()->subDays(30), now())
    ->map(fn($date) => [
        'date' => $date->format('Y-m-d'),
        'value' => rand(10, 100),
    ]);

7. 日历组件数据源(全月/全年的日期网格)

$monthPeriod = CarbonPeriod::create(
    now()->startOfMonth(),
    now()->endOfMonth()
);

进阶小技巧

  • 支持流式写法:CarbonPeriod::since(‘2026-03-01’)->until(‘2026-03-31’)
  • 支持无限周期:CarbonPeriod::create(‘now’, ‘1 day’, INF)
  • 推荐使用 CarbonPeriodImmutable 不可变,以避免意外修改
  • 高级方法:overlaps()、contains()、follows() 等,可判断两个时间段的关系
  • 排除首尾日期->excludeStartDate() / ->excludeEndDate()
  • 自定义间隔'1 week''15 minutes''2 days'
  • 结合 Eloquent:先用 CarbonPeriod 生成完整日期,再 left join 数据表,实现零值填充
  • 性能:CarbonPeriod 是迭代器,内存占用极低,适合大范围日期

总结

CarbonPeriod 是 Laravel 里一个被严重低估的工具。它真正强大的地方在于:让你用最少的代码,生成最完整、最干净的日期序列

尤其是做报表、仪表盘、排班、预约、日历这类功能时,几乎是必备神器。

感谢 Povilas Korop 分享这个 Tip!

如果你也有关于 CarbonPeriod 的奇淫巧用,欢迎在评论区分享给大家~

完整文档: https://carbon.nesbot.com/guide/specialized-use/carbon-period.html