From 14b2bc40ad49d07f67c8b2792684a24fe9f37ebb Mon Sep 17 00:00:00 2001 From: lroyia Date: Wed, 15 Apr 2026 17:21:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E5=91=A8=E8=AE=A1=E7=AE=97BU?= =?UTF-8?q?G=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/work-weekly-report.js | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/skills/work-weekly-report/scripts/work-weekly-report.js b/skills/work-weekly-report/scripts/work-weekly-report.js index ef2bd85..5915b4f 100644 --- a/skills/work-weekly-report/scripts/work-weekly-report.js +++ b/skills/work-weekly-report/scripts/work-weekly-report.js @@ -87,15 +87,53 @@ function getWeekEndDate(weekStartDate) { /** * 获取 ISO 周编号 (YYYY-Www) + * 遵循 ISO 8601 标准:每周从周一开始,第一个包含1月4日的周是W1 */ function getWeekNumber(dateStr) { const date = new Date(dateStr); - // ISO 周码:每年的第一个周四所在的周为第1周 + const MS_PER_DAY = 24 * 60 * 60 * 1000; + + // 找到该日期所在周的周四(ISO 8601 以包含1月4日的周为W1) const thursday = new Date(date); thursday.setDate(date.getDate() + (4 - (date.getDay() === 0 ? 7 : date.getDay()))); + + // 计算该年的1月1日是周几 const yearStart = new Date(thursday.getFullYear(), 0, 1); - const weekNum = Math.ceil(((thursday - yearStart) / 86400000 + 1) / 7); - return `${thursday.getFullYear()}-W${String(weekNum).padStart(2, '0')}`; + const jan1Day = yearStart.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat + + // 计算这是该年的第几天(1月1日=1) + const dayOfYear = Math.floor((thursday - yearStart) / MS_PER_DAY) + 1; + + // ISO 周号:(dayOfYear + 该年1月1日的星期几 - 1) / 7 向上取整 + // 如果1月1日是周四(day=4),则 Jan1 就在 W01 中 + // 如果1月1日是周五/周六/周日,则需要调整(这些天属于上一年最后一周) + const weekNum = Math.ceil((dayOfYear + (jan1Day === 0 ? 6 : jan1Day) - 1) / 7); + + // 处理年末/年初边界情况: + // 如果计算的周号是0,说明属于上一年最后一周 + // 如果周号超过该年最大周数,说明属于下一年第一周 + let year = thursday.getFullYear(); + let finalWeek = weekNum; + + if (finalWeek === 0) { + // 上一年最后一周 + year = year - 1; + const prevJan1Day = new Date(year, 0, 1).getDay(); + finalWeek = prevJan1Day === 4 || (prevJan1Day === 3 && isLeapYear(year)) ? 53 : 52; + } else { + const maxWeeks = (jan1Day === 4 || (jan1Day === 3 && isLeapYear(thursday.getFullYear()))) ? 53 : 52; + if (finalWeek > maxWeeks) { + // 下一年第一周 + year = year + 1; + finalWeek = 1; + } + } + + return `${year}-W${String(finalWeek).padStart(2, '0')}`; +} + +function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); } /** @@ -188,37 +226,13 @@ function getWeekStartFromWeekNumber(year, weekNum) { const jan4 = new Date(year, 0, 4); const jan4Day = jan4.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat - // 找到W1的周一 - let firstMonday; - if (jan4Day === 1) { - // 1月4日是周一 -> W1周一是1月4日 - firstMonday = jan4; - } else if (jan4Day === 0) { - // 1月4日是周日 -> W1周一是上周一(12月X日) - // 1月4日 - 7天 = 12月28日(上上个周一),再 -1天 = 12月29日(上周一) - firstMonday = new Date(jan4.getTime() - 7 * MS_PER_DAY); - // 但这已经是12月28了,而1月4日是周日,那上周一是12月29日 - // 所以实际上 1月4日 - 8天 = 12月27... 这不对 - // 让我重新想: - // 如果1月4日是周日,那这一周是 Dec 28 - Jan 3 (W1 ends Jan 3) - // 所以W1的周一是 Dec 28 - // 那么 Dec 28 + 7 = Jan 4,W2从 Jan 5开始 - // 所以 W1 of 2026 = Dec 28 - Jan 3 - // W1 starts on Monday Dec 28 - // Let me recalculate: Jan 4 - 6 = Dec 29 (that's Monday if Jan 4 is Sunday) - // Wait, if Jan 4 is Sunday, then Jan 4 - 1 = Jan 3 (Saturday) - // Jan 4 - 2 = Jan 2, ..., Jan 4 - 7 = Dec 28 - // But that's 7 days back, not 6. And Dec 28 is Monday? - // Let me just use getTime() - const daysToSubtract = jan4Day === 0 ? 6 : jan4Day - 1; - firstMonday = new Date(jan4.getTime() - daysToSubtract * MS_PER_DAY); - } else { - // 1月4日是 Tue(2), Wed(3), Thu(4), Fri(5), Sat(6) -> 找到上溯到周一 - // 如果1月4日是周三,那周一就是1月4日 - 2天 - // daysToSubtract = 4 - 1 = 3, 1月4日 - 3天 = 1月1日 = 周一 ✓ - const daysToSubtract = jan4Day - 1; - firstMonday = new Date(jan4.getTime() - daysToSubtract * MS_PER_DAY); - } + // 找到W1的周一(ISO 8601:每年第一个包含1月4日的周是W1,该周的周一是W1起始) + // jan4Day: 0=Sun, 1=Mon, ..., 6=Sat + // 如果1月4日是周日,W1周一是Dec 29(上周一) + // 如果1月4日是周一,W1周一是1月4日 + // 否则,W1周一是1月4日往前到周一的天数 + const daysToSubtract = (jan4Day === 0 ? 7 : jan4Day) - 1; + const firstMonday = new Date(jan4.getTime() - daysToSubtract * MS_PER_DAY); // 计算目标周的周一 const targetMonday = new Date(firstMonday.getTime() + (weekNum - 1) * 7 * MS_PER_DAY);