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

如何从当前日期倒推至指定日期生成年月数组?是否可用Moment简化

问题:生成从当前日期倒推至指定日期的年月数组

需求:从当前日期倒推至指定的最早加入日期(示例:2021年7月25日),生成格式如「August 2022」的年月数组。现有JS代码仅支持两年范围,需重构以支持任意年数,同时询问用Moment.js实现是否更简便。

现有代码:

function getMonthDifference(startDate: Date, endDate: Date) {
  return (
    endDate.getMonth() -
    startDate.getMonth() +
    12 * (endDate.getFullYear() - startDate.getFullYear())
  )
}

const earliestDateJoined = "2020-07-25"
const now = new Date()
const earliestDate = new Date(earliestDateJoined)

for (let i = 0; i < getMonthDifference(earliestDate, now) + 1; i++) {
  let month = new Date().getMonth() + 1 - i
  let year = new Date().getFullYear()
  // console.log("before", year, month)
  if (month < 1) {
    month = month + 12
    year = year - 1
    if (month < 1) {
      month = month + 12
      year = year - 1
    }
  }
  const nameMonth = {
    1: "Jan",
    2: "Feb",
    3: "Mar",
    4: "Apr",
    5: "May",
    6: "Jun",
    7: "Jul",
    8: "Aug",
    9: "Sep",
    10: "Oct",
    11: "Nov",
    12: "Dec"
  }
  console.log(year + " Year " + nameMonth[month] + " Month ")
}

原生JS重构方案(支持任意年数)

原代码的问题在于处理月份小于1时仅嵌套了两层判断,超过两年就会失效。下面提供两种可靠的重构方案,无需硬编码年份修正逻辑:

方案1:基于日期对象的安全回退

利用日期对象的setMonth方法自动处理年份进位,避免手动计算边界:

function generateMonthArray(earliestDateStr) {
  const earliestDate = new Date(earliestDateStr);
  const now = new Date();
  const monthArray = [];
  
  // 初始化迭代日期为当前月第一天,避免日期溢出问题
  const currentDate = new Date(now.getFullYear(), now.getMonth(), 1);
  
  while (currentDate >= earliestDate) {
    // 格式化年月为「August 2022」格式
    const formattedMonth = new Intl.DateTimeFormat('en-US', {
      year: 'numeric',
      month: 'long'
    }).format(currentDate);
    
    monthArray.push(formattedMonth);
    
    // 回退一个月
    currentDate.setMonth(currentDate.getMonth() - 1);
  }
  
  return monthArray;
}

// 使用示例
const earliestDateJoined = "2020-07-25";
const result = generateMonthArray(earliestDateJoined);
console.log(result);

方案2:数学计算推导年月

通过数学计算直接得出目标年月,逻辑更直观:

function getMonthDifference(startDate, endDate) {
  return endDate.getMonth() - startDate.getMonth() + 12 * (endDate.getFullYear() - startDate.getFullYear());
}

function generateMonthArray(earliestDateStr) {
  const earliestDate = new Date(earliestDateStr);
  const now = new Date();
  const totalMonths = getMonthDifference(earliestDate, now);
  const monthArray = [];
  
  for (let i = 0; i <= totalMonths; i++) {
    let year = now.getFullYear();
    let month = now.getMonth() - i;
    
    // 处理月份为负数的情况
    if (month < 0) {
      const yearOffset = Math.floor(Math.abs(month) / 12);
      const monthOffset = Math.abs(month) % 12;
      year -= yearOffset;
      month = monthOffset === 0 ? 12 : 12 - monthOffset;
      year -= monthOffset === 0 ? 1 : 0;
    }
    
    // 获取完整月份名称
    const monthName = new Intl.DateTimeFormat('en-US', { month: 'long' }).format(new Date(year, month));
    monthArray.push(`${monthName} ${year}`);
  }
  
  return monthArray;
}

// 使用示例
const earliestDateJoined = "2020-07-25";
const result = generateMonthArray(earliestDateJoined);
console.log(result);

两种方案均支持任意年数范围,同时用Intl.DateTimeFormat替代手动月份映射,更可靠且支持多语言适配。


Moment.js实现方案(更简便)

如果项目中已经引入Moment.js,用它实现会大幅简化代码——内置的日期加减、格式化和比较方法,无需手动处理边界:

// 先安装依赖:npm install moment
const moment = require('moment');

function generateMonthArray(earliestDateStr) {
  const earliestMoment = moment(earliestDateStr);
  const nowMoment = moment();
  const monthArray = [];
  
  let currentMoment = nowMoment.clone().startOf('month');
  
  while (currentMoment.isSameOrAfter(earliestMoment, 'month')) {
    // 直接格式化为「August 2022」
    monthArray.push(currentMoment.format('MMMM YYYY'));
    currentMoment.subtract(1, 'month');
  }
  
  return monthArray;
}

// 使用示例
const earliestDateJoined = "2020-07-25";
const result = generateMonthArray(earliestDateJoined);
console.log(result);

Moment.js版本的代码逻辑更清晰、可读性更高,适合已有依赖的项目;如果不需要引入第三方库,原生JS方案也足够可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:06:16