使用Laravel的Carbon获取日期间隔内指定星期几对应的所有日期
实现方法
Carbon 提供的dayOfWeekIso属性返回值刚好匹配你给出的规则:1 对应周一,2 对应周二,以此类推7对应周日,不需要额外做数值转换。根据使用场景可以选择以下两种方案:
场景1:直接生成指定范围内所有符合要求的日期
适合需要拿到具体日期列表的场景,用CarbonPeriod遍历日期范围过滤即可:
// 配置参数 $targetWeekdays = [1, 3, 5]; // 目标星期:周一、周三、周五 $start = \Carbon\Carbon::parse('2024-05-01')->startOfDay(); $end = \Carbon\Carbon::parse('2024-05-31')->endOfDay(); // 遍历日期范围过滤匹配项 $matchedDates = collect(\Carbon\CarbonPeriod::create($start, '1 day', $end)) ->filter(fn($date) => in_array($date->dayOfWeekIso, $targetWeekdays)) ->values(); // 可选:转成 Y-m-d 格式的字符串数组 $dateStrings = $matchedDates->map->toDateString()->toArray();
场景2:查询数据库中符合规则的记录
如果是要筛选表中日期字段符合要求的记录,直接用查询构造器配合数据库原生周函数即可,性能远高于遍历后过滤:
$targetWeekdays = [1, 3, 5]; $start = '2024-05-01'; $end = '2024-05-31'; // MySQL 环境写法 $records = \DB::table('你的表名') ->whereBetween('date_field', [$start, $end]) ->whereRaw('WEEKDAY(date_field) + 1 IN (?)', [implode(',', $targetWeekdays)]) ->get(); // PostgreSQL 环境写法,直接用ISODOW属性匹配规则 // $records = \DB::table('你的表名') // ->whereBetween('date_field', [$start, $end]) // ->whereRaw('EXTRACT(ISODOW FROM date_field) IN (?)', [implode(',', $targetWeekdays)]) // ->get();
注意事项
- 若起止日期包含时间部分,务必用
startOfDay()和endOfDay()处理边界,避免首尾日期的记录被漏算 - 若日期范围跨度超过1年,优先使用数据库查询方案,避免遍历大量日期导致性能下降
内容的提问来源于stack exchange,提问作者Santiago Ramirez
相关产品推荐
相关产品推荐

