PHP计算1月订单周数时跨年周归属不一致如何解决
跨年周订单统计周数匹配异常解决方案
做订单周维度统计用于绘图时,会遇到周数计算错位问题:
- 创建时间为
2022-01-02的订单被默认周数计算逻辑识别为第52周 - 创建时间为
2022-01-03的订单被识别为第1周
每年跨年周落在1月的日期不固定,相邻的1月日期被拆分到不同年份的周,会导致图表跨年时段出现数据断层。
原有问题代码如下:
$date = "2022-01-02 00:00:00"; $week = (float) date("W", strtotime($date)); print $week . "\n"; // 输出52 $date = "2022-01-03 00:00:00"; $week = (float) date("W", strtotime($date)); print $week; // 输出1
问题原因
PHP内置
date("W")遵循ISO-8601周数规范:每周从周一开始,每年第一个包含至少4个当年公历日期的周记为第1周。按照这个规则,1月前3天如果落在周四之前,就可能被归属到上一年的最后一周,和业务统计常用的「1月日期统一归属到当年统计周」的需求不匹配。
调整方案
要实现1月相邻日期归属到同一统计周,改用自然年绑定的业务周规则:
- 每周起始日可按需配置,默认周一
- 每年1月1日所在的周,统一记为当年第1周,不将1月日期归属到上一年周数
- 分组统计时用「年份+周数」作为唯一标识,避免不同年同周数数据混淆
实现代码
/** * 计算自然年业务周(1月1日所在周为当年第1周) * @param string $dateStr 可被strtotime解析的日期字符串 * @param int $weekStart 每周起始星期,1=周一,0=周日 * @return array 包含统计年份、周数、展示标签 */ function getBusinessWeek(string $dateStr, int $weekStart = 1): array { $timestamp = strtotime($dateStr); $currentYear = (int)date('Y', $timestamp); $yearFirstDay = strtotime($currentYear . '-01-01'); // 计算1月1日与周起始日的偏移天数 $firstDayWeek = (int)date('w', $yearFirstDay); $offset = ($firstDayWeek - $weekStart + 7) % 7; // 计算当前日期与当年1月1日的天数差 $dayDiff = (int)floor(($timestamp - $yearFirstDay) / 86400); // 计算周数 $week = (int)ceil(($dayDiff + $offset + 1) / 7); return [ 'year' => $currentYear, 'week' => $week, 'label' => sprintf("%d年第%d周", $currentYear, $week) ]; } // 验证效果 $date1 = "2022-01-02 00:00:00"; $week1 = getBusinessWeek($date1); echo $date1 . " 归属:" . $week1['label'] . "\n"; // 输出2022年第1周 $date2 = "2022-01-03 00:00:00"; $week2 = getBusinessWeek($date2); echo $date2 . " 归属:" . $week2['label'] . "\n"; // 输出2022年第1周
补充说明
- 如果业务习惯以周日为一周起点,调用函数时第二个参数传
0即可 - 周数从1开始计数,全年最多53周,和日常认知一致
- 做数据库查询分组时,建议先把订单创建时间批量转换成对应的「年-周」格式再聚合,避免统计错位
内容的提问来源于stack exchange,提问作者Dan Rais
相关产品推荐
相关产品推荐

