You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

核心逻辑说明

  1. UTC时间处理:所有计算基于UTC日期,避免本地时区转换导致的日期偏移
  2. 周年份确定:通过找到当前日期所在周的周四,确保该年份即为ISO周所属的%G年份(ISO规则:第一周必须包含当年1月4日,因此周四必然在所属年份内)
  3. 周数计算:基于周年份的1月1日到周四的天数,计算出正确的周数%V(从1开始)
  4. 周起止日期:调整日期到周一作为周起始,周日作为周结束,符合ISO周的时间范围

内容的提问来源于stack exchange,提问作者OJT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:06:18