通过周数获取周一为起始的周首日,现有代码返回错误能否加1天修复
根因分析
原代码存在三个核心错误,才导致返回日期比预期少1天:
Date.prototype.setDate()方法的返回值是修改后日期对应的毫秒时间戳,而非Date对象,你将返回的时间戳转成日期时如果混用了本地时区和UTC时区,非常容易出现跨天偏移- 53周的校验语句写错了,
weekNo = 53是赋值操作而非相等判断,所有大于52的周数都会进入这个分支,周数校验逻辑完全失效 - 原代码没有处理跨年周的边界校验,部分年份的第53周判断规则错误
直接加1天的风险
这种做法非常不安全,会触发多个边界bug:
- 年初第1周的计算直接错误,首日会从周一变成周二
- 闰年12月的最后一周加1天会直接跳到下一年1月1日,周数归属完全错误
- 没有从根本上解决时区偏移问题,换时区运行时还是会出现日期差问题
修正后可用的代码
function getFirstMondayOfWeek(weekNo) { const year = new Date().getFullYear(); // ISO周规则:1月4日永远属于当年第1周 let firstWeekMonday = new Date(year, 0, 4, 0, 0, 0, 0); // 调整到当周周一,getDay()返回值规则:周日0,周一1,周六6 while (firstWeekMonday.getDay() !== 1) { firstWeekMonday.setDate(firstWeekMonday.getDate() - 1); } // 基础周数校验 if (weekNo < 1 || weekNo > 53) { return null; } // 计算目标周的周一 const targetMonday = new Date(firstWeekMonday); targetMonday.setDate(targetMonday.getDate() + 7 * (weekNo - 1)); // 第53周合法性校验:仅当年最后一天是周四,或闰年最后一天是周五时存在第53周 if (weekNo === 53) { const lastDay = new Date(year, 11, 31); const isLeap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; const has53Week = lastDay.getDay() === 4 || (isLeap && lastDay.getDay() === 5); if (!has53Week) { return null; } } return targetMonday; }
调用后直接拿到对应周一的Date对象,不需要额外加1天,时区和边界场景都做了兼容。
内容的提问来源于stack exchange,提问作者hampani
相关产品推荐
相关产品推荐

