You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Moment.js获取去年同周同日出错,求修正方案及原因解析

解决Moment.js获取去年同月同周指定日期的问题

我来帮你分析问题并修正代码:

为什么你的测试代码会出错?

你写的这段代码:

console.log(moment().subtract(1, 'years').day(moment().day()).format('DD/MM/YYYY'))

核心问题有两个:

  1. 逻辑偏差:你想要的是去年同月第N周的周一,但这段代码完全没考虑“当月周数”的规则,只是简单把当前日期减一年后,调整成和今天一样的星期几——这和“同周”的需求根本不是一回事。
  2. 日期错位:由于闰年、不同年份的月份星期分布不同,减一年后的日期的星期几大概率和今天不一样。比如假设你当前是2020年3月2日(周一),减一年后是2019年3月2日(周六),调用.day(1)会自动跳到最近的周一也就是2019年3月4日,这就是你得到04/03/2019的原因。

修正方案(匹配你的周定义)

根据你描述的规则:周从周日起始,某周只要包含当月一天就算当月的周,当前是3月第三周的周一,目标是去年3月第三周的周一。我们可以分两步实现:

第一步:计算当前是当月的第几周

先确定当前日期在当月的周序号:

const currentDate = moment(); // 你的当前日期,比如2020-03-16

// 获取当月第一天
const firstDayOfCurrentMonth = currentDate.clone().startOf('month');
// 找到当月第一周的起始日(周日)
const firstWeekStart = firstDayOfCurrentMonth.clone().day(0);
// 找到当前日期所在周的起始日(周日)
const currentWeekStart = currentDate.clone().day(0);
// 计算当前是当月第几个周
const weekNumInMonth = Math.floor(currentWeekStart.diff(firstWeekStart, 'weeks')) + 1;

第二步:找到去年同月对应周的周一

基于上面得到的周数,计算目标日期:

// 获取去年同月的第一天
const firstDayOfLastYearSameMonth = currentDate.clone().subtract(1, 'years').startOf('month');
// 找到去年同月第一周的起始日(周日)
const lastYearFirstWeekStart = firstDayOfLastYearSameMonth.clone().day(0);
// 找到去年同月第N周的起始日(周日)
const targetWeekStart = lastYearFirstWeekStart.clone().add(weekNumInMonth - 1, 'weeks');
// 该周的周一就是起始日加1天
const targetMonday = targetWeekStart.clone().add(1, 'days');

// 输出结果
console.log(targetMonday.format('DD/MM/YYYY'));

验证你的案例

如果当前是2020年3月16日(第三周周一):

  • 当月第一周起始是2020-03-01(周日),当前周起始是2020-03-15(周日),相差2周,所以weekNumInMonth=3
  • 去年3月第一周起始是2019-02-24(周日),加2周后是2019-03-10(周日),加1天就是2019-03-11,正好是你预期的11/03/2019

简化版(如果用ISO周规则)

如果你的周定义是国际通用的ISO周(周一为一周起始,每年第1周包含1月4日),可以用更简洁的代码:

const currentDate = moment();
const targetDate = currentDate.clone()
  .subtract(1, 'years')
  .isoWeek(currentDate.isoWeek()) // 匹配去年的同一ISO周
  .startOf('isoWeek'); // 获取该周的周一

console.log(targetDate.format('DD/MM/YYYY'));

这段代码直接定位到去年同一ISO周的周一,对于你的案例同样会返回11/03/2019

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

火山引擎 最新活动