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

JavaScript日期处理嵌套循环:年度重复季节预订系统开发难题

嘿,我懂你现在的困扰——做预订系统时,处理年度重复的季节来生成多年的价格时段确实有点挠头,尤其是moment-range本身不支持重复时间范围的情况。我之前做过类似的项目,分享几个实用的思路给你:

处理年度重复季节生成多年数据的解决方案

1. 先提炼原始季节对象的核心信息

首先得从你的seasonsObject里把每个季节的关键信息拆出来:比如季节名称、开始月日、结束月日、对应价格,还有最重要的——这个季节是不是跨年度的(比如12月到次年2月这种跨年旺季)。举个实际的原始数据例子:

const seasonsObject = [
  { name: '旺季', start: '12-15', end: '02-28', price: 200 },
  { name: '平季', start: '03-01', end: '11-30', price: 150 }
];

startend拆成月份和数字,后面叠加年份的时候会方便很多。

2. 写个年份遍历+范围生成的工具函数

接下来核心就是写一个函数,传入起始年份、要生成的年限,还有原始季节数据,循环每个年份给每个季节生成对应年度的时间范围:

const generateMultiYearSeasons = (startYear, yearsCount, seasons) => {
  const multiYearSeasons = [];
  // 遍历每一年
  for (let yearOffset = 0; yearOffset < yearsCount; yearOffset++) {
    const currentYear = startYear + yearOffset;
    // 给每个季节生成对应年份的范围
    seasons.forEach(season => {
      const [startMonth, startDay] = season.start.split('-').map(Number);
      const [endMonth, endDay] = season.end.split('-').map(Number);
      
      let startDate, endDate;
      // 处理跨年季节的情况
      if (startMonth > endMonth) {
        // 开始日期在当前年,结束日期在次年
        startDate = moment(`${currentYear}-${startMonth}-${startDay}`);
        endDate = moment(`${currentYear + 1}-${endMonth}-${endDay}`);
      } else {
        // 同年度的季节
        startDate = moment(`${currentYear}-${startMonth}-${startDay}`);
        endDate = moment(`${currentYear}-${endMonth}-${endDay}`);
      }
      
      // 把生成的日期和原始季节信息整合,存起来
      multiYearSeasons.push({
        ...season,
        startDate: startDate.format('YYYY-MM-DD'),
        endDate: endDate.format('YYYY-MM-DD'),
        yearLabel: startMonth > endMonth ? `${currentYear}/${currentYear+1}` : currentYear
      });
    });
  }
  return multiYearSeasons;
};

// 调用示例:生成2024到2028这五年的季节数据
const fiveYearSeasons = generateMultiYearSeasons(2024, 5, seasonsObject);

3. 处理容易踩坑的边界情况

  • 闰年2月29日:如果你的季节结束日期是02-29,非闰年的时候这个日期是无效的,得自动调整成02-28,用moment的isLeapYear()就能判断:
    // 在生成endDate的时候加个判断
    if (endMonth === 2 && endDay === 29 && !moment(`${currentYear}-02-29`).isValid()) {
      endDate = moment(`${currentYear}-02-28`);
    }
    
  • 精确时间需求:如果需要时分秒的精度,格式化的时候加上HH:mm:ss就行,比如startDate.format('YYYY-MM-DD HH:mm:ss')

4. 验证生成的范围是否正确

生成完数据后,可以用moment-range的contains方法测试一下,确保某个日期能匹配到对应的季节:

const testDate = moment('2024-12-20');
const matchingSeason = fiveYearSeasons.find(season => {
  const range = moment.range(moment(season.startDate), moment(season.endDate));
  return range.contains(testDate);
});
console.log(matchingSeason); // 应该返回旺季的那条数据

这种方式相当于把“重复的季节”转换成了“多个年度的独立季节范围”,完美绕开了moment-range不支持重复范围的限制,而且生成的数据也能直接和你现有系统的其他功能兼容。

内容的提问来源于stack exchange,提问作者luke.hawk

火山引擎 最新活动