PHP按d/m/Y日期列月份分组多维数组并重格式化行内日期
问题根因
代码运行结果不符合预期有两个核心原因:
- 日期解析逻辑错误:
exam_date字段是d/m/Y格式,直接传入strtotime()时,PHP会默认将斜杠分隔的日期识别为美式m/d/Y格式,解析出的时间戳完全错误,直接导致提取的月份名偏差。 - 分组逻辑不严谨:遍历写入时没有提前判断月份键是否存在,也没有按子数组结构追加数据,容易出现键不存在警告、数据覆盖问题。
实现方案
处理时不要依赖strtotime()的自动格式识别,用DateTime类显式指定输入日期格式解析,同时按分组逻辑逐层构建数组结构,步骤如下:
- 调用
json_decode()时第二个参数传true,将原始JSON转为关联数组,比对象形式更方便遍历处理 - 遍历每条考试记录时,用
DateTime::createFromFormat('d/m/Y', 原日期值)显式按输入格式解析日期,从根源避免格式识别错误 - 从解析完成的日期对象中,分别提取
F格式的完整月份名作为分组键,以及你需要的目标格式日期值替换原字段 - 写入结果数组时,先判断对应月份的子数组是否存在,不存在则初始化为空数组,再将处理完的记录追加到该子数组下
可直接运行的代码示例
<?php // 此处替换为你的原始JSON字符串 $rawJson = '[ {"exam_name":"Math Midterm","exam_date":"12/02/2024","location":"Room 301"}, {"exam_name":"English Final","exam_date":"25/02/2024","location":"Room 205"}, {"exam_name":"Physics Quiz","exam_date":"08/03/2024","location":"Lab 1"}, {"exam_name":"Chemistry Exam","exam_date":"22/03/2024","location":"Lab 2"} ]'; // JSON转关联数组 $examList = json_decode($rawJson, true); $groupedResult = []; foreach ($examList as $exam) { // 显式指定d/m/Y格式解析日期,规避strtotime的格式歧义 $dateObj = DateTime::createFromFormat('d/m/Y', $exam['exam_date']); // 跳过解析失败的脏数据,避免报错 if (!$dateObj) { continue; } // 提取月份名作为分组键 $monthKey = $dateObj->format('F'); // 重格式化日期,此处示例转为Y-m-d格式,可按需修改格式串 $exam['exam_date'] = $dateObj->format('Y-m-d'); // 初始化月份子数组 if (!isset($groupedResult[$monthKey])) { $groupedResult[$monthKey] = []; } // 追加记录到对应分组 $groupedResult[$monthKey][] = $exam; } // 输出最终结果 print_r($groupedResult); ?>
输出结构参考
上述测试代码运行后输出的数组结构如下,完全符合按月份归集、日期重格式化的要求:
Array ( [February] => Array ( [0] => Array ( [exam_name] => Math Midterm [exam_date] => 2024-02-12 [location] => Room 301 ) [1] => Array ( [exam_name] => English Final [exam_date] => 2024-02-25 [location] => Room 205 ) ) [March] => Array ( [0] => Array ( [exam_name] => Physics Quiz [exam_date] => 2024-03-08 [location] => Lab 1 ) [1] => Array ( [exam_name] => Chemistry Exam [exam_date] => 2024-03-22 [location] => Lab 2 ) ) )
补充说明
如果一定要用strtotime()实现日期解析,必须先将日期字符串中的斜杠替换为横杠,PHP会将横杠分隔的日期识别为欧式d-m-Y格式,写法为strtotime(str_replace('/', '-', $exam['exam_date']))。但这种写法容错率低,遇到不规范的脏数据很容易返回错误时间戳,优先推荐显式指定格式的DateTime方案。
内容的提问来源于stack exchange,提问作者MIK FOLLEY
相关产品推荐
相关产品推荐

