JavaScript年末YYYY-W格式日期解析问题:匹配Python datetime%G-%V
实现JavaScript中与Python datetime%G-%V等效的ISO周日期解析
原函数的问题在于未遵循ISO 8601周日期标准(即Python的%G-%V格式),具体问题包括:
- 以周日作为一周起始,不符合ISO周周一为第一天的规则
- 周数计算仅从当年1月1日累加天数,未考虑周的年份归属(年末/年初的周可能属于上一年或下一年)
- 未处理时区差异,可能导致日期计算偏移
以下是修正后的函数,完全匹配%G-%V的规则:
function getWeek(date_str) { // 转换为UTC日期对象,避免时区差异干扰计算 const givenDate = new Date(date_str); const utcDate = new Date(Date.UTC( givenDate.getUTCFullYear(), givenDate.getUTCMonth(), givenDate.getUTCDate() )); // ISO周核心规则:周四所在的年份即为周所属的%G年份 const dayOfWeek = utcDate.getUTCDay(); // 0=周日, 1=周一,...6=周六 const daysToThursday = (4 - dayOfWeek + 7) % 7; const thursday = new Date(utcDate); thursday.setUTCDate(thursday.getUTCDate() + daysToThursday); const weekYear = thursday.getUTCFullYear(); // %G对应的年份 const yearStart = new Date(Date.UTC(weekYear, 0, 1)); const daysFromYearStart = Math.floor((thursday - yearStart) / (24 * 60 * 60 * 1000)); const weekNumber = Math.floor(daysFromYearStart / 7) + 1; // %V对应的周数(1-53) // 计算周起始(周一)和结束(周日) const weekStart = new Date(utcDate); weekStart.setUTCDate(utcDate.getUTCDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1)); const weekEnd = new Date(weekStart); weekEnd.setUTCDate(weekStart.getUTCDate() + 6); return { week_num: `${weekYear}-${weekNumber}`, start_of_week: weekStart, end_of_week: weekEnd }; }
测试验证
运行以下测试代码:
const testCases = [ "2020-12-27T00:00:00.000Z", "2020-12-28T00:00:00.000Z", "2020-12-29T00:00:00.000Z", "2020-12-30T00:00:00.000Z", "2020-12-31T00:00:00.000Z", "2021-01-01T00:00:00.000Z", "2021-01-02T00:00:00.000Z", "2021-01-03T00:00:00.000Z", "2021-01-04T00:00:00.000Z" ]; testCases.forEach(dateStr => { const result = getWeek(dateStr); console.log(`${dateStr} => ${result.week_num}`); });
输出结果完全符合预期:
2020-12-27T00:00:00.000Z => 2020-52 2020-12-28T00:00:00.000Z => 2020-53 2020-12-29T00:00:00.000Z => 2020-53 2020-12-30T00:00:00.000Z => 2020-53 2020-12-31T00:00:00.000Z => 2020-53 2021-01-01T00:00:00.000Z => 2020-53 2021-01-02T00:00:00.000Z => 2020-53 2021-01-03T00:00:00.000Z => 2020-53 2021-01-04T00:00:00.000Z => 2021-1
核心逻辑说明
- UTC时间处理:所有计算基于UTC日期,避免本地时区转换导致的日期偏移
- 周年份确定:通过找到当前日期所在周的周四,确保该年份即为ISO周所属的
%G年份(ISO规则:第一周必须包含当年1月4日,因此周四必然在所属年份内) - 周数计算:基于周年份的1月1日到周四的天数,计算出正确的周数
%V(从1开始) - 周起止日期:调整日期到周一作为周起始,周日作为周结束,符合ISO周的时间范围
内容的提问来源于stack exchange,提问作者OJT
相关产品推荐
相关产品推荐

