如何在Google Apps Script中协调使用SimpleDateFormat的周数(w)与工作日(u)
Google Apps Script中
w与u格式符周计数规则不一致问题解析与解决 问题背景
要实现Google Sheets功能:根据给定年周数返回该周起止日期。使用Google Apps Script的Utilities.parseDate和Utilities.formatDate时,结合SimpleDateFormat的w(年周数)和u(工作日)格式符,出现异常:某一周的第7个工作日早于第1个工作日。
测试代码:
const firstWeekday = Utilities.formatDate(Utilities.parseDate("2023-6-1", "GMT", "yyyy-w-u"), "GMT", "MMMM dd."); const lastWeekday = Utilities.formatDate(Utilities.parseDate("2023-6-7", "GMT", "yyyy-w-u"), "GMT", "MMMM dd.");
执行结果:firstWeekday为February 6,lastWeekday为February 5,完全不符合预期。
进一步测试2023年2月日期对应的周数-工作日编号,发现两者规则明显错位:
1: 05-2 2: 05-3 3: 05-4 4: 05-5 5: 05-6 6: 06-7 7: 06-1 8: 06-2 9: 06-3 10: 06-4 11: 06-5 12: 06-6 13: 07-7 14: 07-1 15: 07-2 16: 07-3 17: 07-4 18: 07-5 19: 07-6 20: 08-7 21: 08-1 22: 08-2 23: 08-3 24: 08-4 25: 08-5 26: 08-6 27: 09-7 28: 09-1
问题原因确认
你的推测完全正确:w和u的周计数规则确实不同,核心差异在于周起始日的定义:
w格式符遵循美国周历规则:一周从周日开始,年周数按此起始计算。u格式符遵循ISO 8601周历规则:一周从周一开始,工作日编号1=周一,7=周日。
这种规则差异导致两者组合解析时出现逻辑错位:比如2023年第6周(w=6)按美国规则是2月5日(周日)到2月11日(周六),但u=7对应周日(2月5日)、u=1对应周一(2月6日),所以解析2023-6-7会指向2月5日,解析2023-6-1指向2月6日,最终出现第7个工作日早于第1个的异常。
正确处理方案
要解决问题,需统一周历规则,根据业务需求选择以下两种方案之一:
方案一:统一使用ISO周历(周一至周日,推荐)
直接通过日期计算获取目标周的起止日期,避免依赖格式符组合的歧义:
function getISOWeekStartEnd(year, weekNum) { // 创建当年1月1日的日期对象 const startOfYear = new Date(year, 0, 1); // 计算1月1日的星期值(0=周日,1=周一...6=周六) const dayOfWeek = startOfYear.getDay(); // 调整到当年第一周的周一 const daysToFirstMonday = dayOfWeek === 0 ? 1 : (1 - dayOfWeek); const firstMonday = new Date(startOfYear); firstMonday.setDate(firstMonday.getDate() + daysToFirstMonday); // 计算目标周的周一(第一周对应weekNum=1) const targetMonday = new Date(firstMonday); targetMonday.setDate(targetMonday.getDate() + (weekNum - 1) * 7); // 目标周的周日为周一加6天 const targetSunday = new Date(targetMonday); targetSunday.setDate(targetSunday.getDate() + 6); // 格式化输出 const format = "MMMM dd."; const timeZone = "GMT"; return { start: Utilities.formatDate(targetMonday, timeZone, format), end: Utilities.formatDate(targetSunday, timeZone, format) }; } // 测试2023年第6周 const isoResult = getISOWeekStartEnd(2023, 6); console.log(isoResult.start); // February 06. console.log(isoResult.end); // February 12.
方案二:统一使用美国周历(周日至周六)
改用c格式符(美国星期编号:1=周日,2=周一...7=周六)配合w,确保周数与工作日的规则一致:
// 美国周历:周日为一周起始 const usFirstWeekday = Utilities.formatDate(Utilities.parseDate("2023-6-1", "GMT", "yyyy-w-c"), "GMT", "MMMM dd."); const usLastWeekday = Utilities.formatDate(Utilities.parseDate("2023-6-7", "GMT", "yyyy-w-c"), "GMT", "MMMM dd."); console.log(usFirstWeekday); // February 05.(周日) console.log(usLastWeekday); // February 11.(周六)
总结
你之前用"第7到第6个工作日"的规避方法只是适配了规则错位的临时方案,并非最优解。建议根据实际业务场景选择统一的周历规则,使用上述方案实现逻辑清晰、规则一致的周起止日期计算。
内容的提问来源于stack exchange,提问作者tp43793
相关产品推荐
相关产品推荐

