C++如何正确实现计算日期对应年度周数的week_of_year函数
原有实现的问题
你写的第一版实现核心缺陷是默认每个月固定占5周、日期除以7直接对应当月周数,完全没有考虑跨年周和月份首日不是周首日的情况,比如任意一年的12月31日用你的算法算出来周数会达到60左右,远超过一年最多53周的合理范围,只能在极小范围的测试用例下偶然跑通,不具备通用性。
参考代码逻辑拆解
这份参考代码是按照「周日为一周第一天,每年第一周为包含当年1月1日的周」的规则实现的,拆分后逻辑非常清晰:
day_one 函数作用:找到目标日期对应周数体系的第一周第一天
- 首先处理特殊边界:12月26日及之后的日期,有可能属于下一年的第一周,所以先判断是否需要把计算基准年往后加1
- 拿到基准年的1月1日之后,往前倒推到最近的一个周日,这个周日就是当年周数体系的第一周第一天
week_of_year 函数作用:计算目标日期和第一周第一天的周数差
- 从第一周第一天开始每次累加7天,直到超过目标日期,累加的次数就是对应周数
更简洁易读的实现方案
可以用「当年第天数+周偏移」的思路实现,逻辑更直观,效率也比循环累加更高:
// 辅助函数:判断闰年 bool is_leap(int year) { if (year % 4 != 0) return false; if (year % 100 != 0) return true; return year % 400 == 0; } // 辅助函数:计算当前日期是当年的第几天 int day_of_year(const Date& d) { int days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if (is_leap(d.year())) days_in_month[2] = 29; int total = 0; for (int i = 1; i < int(d.month()); i++) { total += days_in_month[i]; } return total + d.day(); } int week_of_year(const Date& d) { Date jan1(d.year(), Month::jan, 1); // 当年1月1日是周几,周日为0 int jan1_weekday = int(day_of_week(jan1)); int doy = day_of_year(d); // 计算1月1日之前需要补的周偏移天数 int offset = jan1_weekday; // 总天数加偏移后向上取整除以7就是周数 int week = (doy + offset + 6) / 7; // 边界处理:算出来周数为0说明属于上一年最后一周 if (week == 0) { Date last_jan1(d.year()-1, Month::jan, 1); int last_jan1_weekday = int(day_of_week(last_jan1)); int last_year_days = is_leap(d.year()-1) ? 366 : 365; week = (last_year_days + last_jan1_weekday + 6) / 7; } // 边界处理:12月底周数超过53说明属于下一年第一周 else if (week > 53) { week = 1; } return week; }
内容的提问来源于stack exchange,提问作者yaelreshet11
相关产品推荐
相关产品推荐

