
本文介绍如何将形如 '202201'(年+周序号)或 '202201'(年+月序号)格式的时间键数据,通过 DateTime 解析动态归类到标准 YYYY-MM 月份维度,并完成多维度值的累加聚合。
本文介绍如何将形如 '202201'(年+周序号)或 '202201'(年+月序号)格式的时间键数据,通过 datetime 解析动态归类到标准 `yyyy-mm` 月份维度,并完成多维度值的累加聚合。
在实际业务中(如统计报表、BI 数据预处理),我们常遇到以紧凑字符串(如 '202201')表示时间维度的原始数据——它可能是“2022年第1周”(ISO week),也可能是“2022年1月”(年月)。由于数据库结构不可修改,必须在 PHP 层完成语义解析与重组织。核心思路是:将字符串安全转换为 DateTime 对象 → 提取标准化月份标识(Y-m)→ 按该标识聚合数值。
以下是一个健壮、可复用的实现方案:
function aggregateByMonth($dataset) {
$perMonth = [];
foreach ($dataset as $key => $series) {
foreach ($series as $timeCode => $value) {
// 尝试解析为「年+月」格式(如 202201 → 2022-01)
$date = null;
if (strlen($timeCode) === 6 && ctype_digit($timeCode)) {
$year = substr($timeCode, 0, 4);
$month = substr($timeCode, 4, 2);
if ($month >= 1 && $month format('Y-m'); // e.g., '2022-01'
if (!isset($perMonth[$monthKey])) {
$perMonth[$monthKey] = [];
}
if (!isset($perMonth[$monthKey][$key])) {
$perMonth[$monthKey][$key] = 0;
}
$perMonth[$monthKey][$key] += (float)$value;
}
}
return $perMonth;
}
// 示例使用
$dataset = [
'val1' => ['202201' => '1', '202202' => '2', '202203' => '3', '202206' => '5', '202207' => '4'],
'val2' => ['202201' => '54', '202202' => '43', '202203' => '12']
];
$result = aggregateByMonth($dataset);
print_r($result);
关键注意事项:
- ✅ 格式优先级判断:
202201默认按「年月」解析(最常见场景)。若实际为 ISO 周编号(如2022W01),需改用DateTime::createFromFormat('o\WW', $code)并调用modify('this week')获取当周任意日期再提取月份; - ✅ 类型安全:始终将
$value转为(float)或(int)再累加,避免字符串拼接错误; - ✅ 异常防御:对非法
timeCode(如202213、abcd)添加日志与跳过逻辑,保障程序健壮性; - ✅ 扩展性:函数支持任意嵌套层级的
$dataset,新增指标(如'val3')无需修改逻辑。
最终输出符合预期:
[ '2022-01' => ['val1' => 1.0, 'val2' => 54.0], '2022-02' => ['val1' => 2.0, 'val2' => 43.0], '2022-03' => ['val1' => 3.0, 'val2' => 12.0], '2022-06' => ['val1' => 5.0], '2022-07' => ['val1' => 4.0] ]
此方案兼顾准确性、可维护性与生产环境适应性,可直接集成至 Laravel、Symfony 等框架的数据处理层。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











