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

如何在JavaScript中借助Moment.js计算两个日期的日历周差值?

计算两个日期的日历周差值(含跨年处理)

这个问题我太熟悉了!Moment.js默认的diff('week')是按7天为一个周期计算,完全不考虑实际的日历周边界,所以会和你想要的结果对不上。而直接减周数又会在跨年时翻车——比如2023年最后一周和2024年第一周,直接减会得到负数,完全不符合预期。下面给你两种靠谱的解决方案,根据你的需求选:

先明确你的日历周定义

首先得确定你用的是哪种日历周规则,这很关键:

  • ISO周:周一为一周起始,每年第1周是包含该年1月4日(或周四)的那周(每年最少52周,最多53周)
  • 地区周:比如美国常用周日为起始,第1周是包含当年1月1日的周

方案1:计算两个日期所在日历周的差值(周数差,如周19到周20差1)

如果你的“差值”指的是周数的绝对差,这个方法能完美处理跨年:

function getWeekDiff(dateA, dateB, useISO = false) {
  const momentA = moment(dateA, 'DD-MMM-YYYY');
  const momentB = moment(dateB, 'DD-MMM-YYYY');
  
  const getWeekInfo = (m) => {
    if (useISO) {
      return {
        year: m.isoWeekYear(),
        week: m.isoWeek(),
        totalWeeks: moment(m.isoWeekYear()).isoWeeksInYear()
      };
    } else {
      return {
        year: m.year(),
        week: m.week(),
        totalWeeks: moment(m.year()).weeksInYear()
      };
    }
  };
  
  const { year: yearA, week: weekA, totalWeeks: weeksA } = getWeekInfo(momentA);
  const { year: yearB, week: weekB, totalWeeks: weeksB } = getWeekInfo(momentB);
  
  let diff;
  if (yearA === yearB) {
    diff = Math.abs(weekB - weekA);
  } else if (yearB > yearA) {
    // 从A的周数到当年年底的周数 + 中间年份的总周数 + B当年的周数
    diff = (weeksA - weekA);
    for (let y = yearA + 1; y < yearB; y++) {
      diff += useISO ? moment(y).isoWeeksInYear() : moment(y).weeksInYear();
    }
    diff += weekB;
  } else {
    // 反过来计算跨年前的差值
    diff = (weeksB - weekB);
    for (let y = yearB + 1; y < yearA; y++) {
      diff += useISO ? moment(y).isoWeeksInYear() : moment(y).weeksInYear();
    }
    diff += weekA;
  }
  
  return diff;
}

方案2:计算两个日期跨越的日历周数量(含起止周,如周19到周20算2)

看你的例子需要得到差值2,应该是要统计包含起止周的总数量。这个方案基于方案1,额外处理了同周的情况:

function getWeekCount(dateA, dateB, useISO = false) {
  const diff = getWeekDiff(dateA, dateB, useISO);
  // 判断两个日期是否在同一周
  const momentA = moment(dateA, 'DD-MMM-YYYY');
  const momentB = moment(dateB, 'DD-MMM-YYYY');
  const sameWeek = useISO 
    ? momentA.isoWeek() === momentB.isoWeek() && momentA.isoWeekYear() === momentB.isoWeekYear()
    : momentA.week() === momentB.week() && momentA.year() === momentB.year();
  
  return sameWeek ? 1 : diff + 1;
}

// 测试你的例子(默认用周日为起始的地区周)
const a = '09-May-2018';
const b = '14-May-2018';
console.log(getWeekCount(a, b)); // 输出2,完全符合你的需求!

关键注意点

  • 一定要明确周的起始规则,不同地区的日历周起始不同,用useISO参数切换即可
  • 如果需要自定义周起始(比如周六为起始),可以用moment.updateLocale设置:
    moment.updateLocale('en', {
      week: {
        dow: 6 // 周六为一周的第一天
      }
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:54:16