COleDateTime::Format周数检测异常求助:2023-01-01返回0而非52
问题原因
COleDateTime的Format(L"%W")遵循Windows系统的周编号规则:
- %W定义为以当年第一个周一作为第1周起始,周范围是周一到周日
- 2023年的第一个周一是1月2日,因此1月1日(周日)属于2023年的"第0周",这符合文档中"返回0-53数值"的说明
- 2022年12月26日是周一,属于2022年第52周,因为2022年第一个周一是1月3日,到12月26日刚好是第52个周一所在的周
解决方案
方法1:手动修正跨年度周日
如果你的业务要求"周日必须归属到上一个周一所在的周",可以在获取周数后做针对性判断:
CString strDate = L"2023-01-01 00:00:00"; COleDateTime datMeeting; datMeeting.ParseDateTime(strDate); int iPublicTalkWeekNumber = _ttoi(datMeeting.Format(L"%W")); int dayOfWeek = datMeeting.GetDayOfWeek(); // 1=周日,2=周一,...,7=周六 // 处理跨年周日的情况:周日且周数为0时,取上一年的最后一周 if (dayOfWeek == 1 && iPublicTalkWeekNumber == 0) { datMeeting -= COleDateTimeSpan(1, 0, 0, 0); // 日期减1天 iPublicTalkWeekNumber = _ttoi(datMeeting.Format(L"%W")); }
方法2:使用ISO周编号规则(需Windows 10 1709+)
如果业务可以适配ISO周规则(周一为周起始,跨年周归属包含更多天数的年份),可以直接用%V格式获取1-53的周数:
// 获取ISO周数,2023-01-01会返回52 int isoWeekNumber = _ttoi(datMeeting.Format(L"%V")); // 同时可以用%G获取ISO周对应的年份,2023-01-01会返回"2022" CString isoYear = datMeeting.Format(L"%G");
方法3:自定义周数计算逻辑
完全脱离系统格式依赖,自己实现符合业务需求的周数计算:
int GetCustomWeekNumber(const COleDateTime& date) { // 获取当年1月1日 COleDateTime firstDayOfYear(date.GetYear(), 1, 1, 0, 0, 0); int firstDayWeek = firstDayOfYear.GetDayOfWeek(); // 1=周日,2=周一... // 找到当年第一个周一 COleDateTime firstMonday = firstDayOfYear; if (firstDayWeek != 2) { int daysToAdd = (2 - firstDayWeek + 7) % 7; firstMonday += COleDateTimeSpan(daysToAdd, 0, 0, 0); } // 如果目标日期早于当年第一个周一,递归计算上一年的周数 if (date < firstMonday) { COleDateTime lastDayOfPrevYear(date.GetYear()-1, 12, 31, 0, 0, 0); return GetCustomWeekNumber(lastDayOfPrevYear); } // 计算周数:第一个周一为第1周 COleDateTimeSpan diff = date - firstMonday; return (int)(diff.GetTotalDays() / 7) + 1; }
调用该函数,2023年1月1日会返回52,完全匹配你的业务逻辑。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

