
本文介绍如何将 JSON 解析后的 PHP 数组,依据 d/m/Y 格式的日期字段(如 exam_date)按自然月名称(如 "February")分组,并同步将每条记录中的日期转换为 m/d/Y 格式。核心在于正确使用 DateTime::createFromFormat() 解析非标准日期,并采用 $result[$month][] = $item 的键值累积方式实现分组。
本文介绍如何将 json 解析后的 php 数组,依据 `d/m/y` 格式的日期字段(如 `exam_date`)按自然月名称(如 "february")分组,并同步将每条记录中的日期转换为 `m/d/y` 格式。核心在于正确使用 `datetime::createfromformat()` 解析非标准日期,并采用 `$result[$month][] = $item` 的键值累积方式实现分组。
在处理考试日程、活动排期等时间敏感型数据时,常需将原始 JSON 数据解析为 PHP 数组后,按月份聚合展示(例如前端渲染为“二月场次”、“三月场次”等模块)。但直接使用 strtotime() 解析 d/m/Y 格式(如 "21/02/2022")存在风险:PHP 默认按 m/d/Y 解释,易导致日期解析错误(如 32/03/2022 会静默失败或回退为无效日期)。因此,推荐使用更健壮的 DateTime::createFromFormat() 方法。
以下是一个完整、可运行的解决方案:
<?php $body = '{
"exam_dates": [
{"id":"1","uni_name":"uni1","exam_name":"University of Szeged Feb","exam_date":"02/02/2022","exam_mode":"Online","appl_deadline":"To be announced"},
{"id":"2","uni_name":"uni2","exam_name":"University of Szeged","exam_date":"21/02/2022","exam_mode":"Online","appl_deadline":"To be announced"},
{"id":"3","uni_name":"uni3","exam_name":"University of Szeged","exam_date":"22/02/2022","exam_mode":"Online","appl_deadline":"To be announced"},
{"id":"4","uni_name":"uni4","exam_name":"University of Szeged","exam_date":"22/03/2022","exam_mode":"Online","appl_deadline":"To be announced"}
]
}';
$data = json_decode($body);
$grouped = [];
foreach ($data->exam_dates as $record) {
// 使用 createFromFormat 精确解析 d/m/Y 格式,避免 strtotime 的歧义
$dateObj = DateTime::createFromFormat('d/m/Y', $record->exam_date);
// 【关键校验】检查解析是否成功(防止无效日期如 32/03/2022)
if (!$dateObj || $dateObj->format('d/m/Y') !== $record->exam_date) {
error_log("Invalid date format skipped: {$record->exam_date}");
continue;
}
$monthName = $dateObj->format('F'); // e.g., "February"
$record->exam_date = $dateObj->format('m/d/Y'); // 转换为 m/d/Y 格式
// 正确分组:以月份名为键,追加当前记录到对应数组
$grouped[$monthName][] = $record;
}
// 输出结果(按月份自然排序,可选)
ksort($grouped);
print_r($grouped);
?>
输出示例:
Array
(
[February] => Array
(
[0] => stdClass Object
([id] => 1, [uni_name] => uni1, ..., [exam_date] => 02/02/2022)
[1] => stdClass Object
([id] => 2, [uni_name] => uni2, ..., [exam_date] => 02/21/2022)
[2] => stdClass Object
([id] => 3, [uni_name] => uni3, ..., [exam_date] => 02/22/2022)
)
[March] => Array
(
[0] => stdClass Object
([id] => 4, [uni_name] => uni4, ..., [exam_date] => 03/22/2022)
)
)
注意事项与最佳实践:
- ✅ 始终校验 DateTime::createFromFormat() 返回值:它在解析失败时返回 false,需显式判断,否则后续调用 format() 会触发警告;
- ✅ 避免 strtotime() 处理 d/m/Y:因其依赖区域设置且默认按美式解析,极易出错;
- ✅ 分组逻辑关键在 $grouped[$monthName][] = $record:[] 表示追加到该月数组末尾,而非 $grouped[][$monthName](后者创建嵌套索引数组,不符合需求);
- ✅ 如需保持原始顺序或按时间升序,可在分组后对各月数组调用 usort();
- ⚠️ 原始 JSON 中 "32/03/2022" 是非法日期,本方案会跳过并记录错误,确保数据健壮性。
该方法结构清晰、容错性强,适用于任何需按日期字段分组并标准化格式的 PHP 数据处理场景。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











