捕获两个日期之间的每个星期五、星期日和星期三

Capture every Friday, Sunday and Wednesday between two dates

晚安。我正在尝试使用 Moment.js 捕获两个日期之间的每个星期五、星期日和星期三。我不明白为什么它没有捕捉到日子:

我做到了这一点:

const allDays = [0, 3, 5];

function formatToPush(dt_inicio, dt_final, dia, horas) {

    let start = moment(dt_inicio);
    let end = moment(dt_final);

    let result = [];
    let datas = [];
    let current = start.clone();

    if ((current.day(dia).isSameOrAfter(start)) || (current.day(dia).isSameOrAfter(end)) || (current.day(7 + dia).isSameOrBefore(end))) {
        result.push(current.clone());
    }

    result.map(m => {
        horas.map(h => {
            m.set({ hour: h.split(':')[0], minute: h.split(':')[1], second: 0, millisecond: 0 });
            datas.push(m.format('YYYY-MM-DD HH:mm:ss'))
        })
    });

    return datas;
}

let final = [];

for (let i in allDays) {
    final.push(...formatToPush('2021-12-01', '2021-12-10', allDays[i], ["10:00", "16:00", "22:30"]))
}

console.log(final)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

谁能帮我找出错误?

谢谢!

对于前两个子句中的一个或两个,日期是否在范围内的条件始终为真。这意味着整个表达式为真,无需评估第三个子句,该子句可以将日期设置为您丢失的较晚日期之一。由于您不是 运行 循环中的 if 语句,它只会将一个日期推送到结果数组。

更通用的算法将使用循环。

let current = start.clone();
if (current.day(dia).isSameOrAfter(start) && current.isSameOrBefore(end)) {
  result.push(current.clone());
}
while (current.day(7 + dia).isSameOrAfter(start) && current.isSameOrBefore(end)) {
  result.push(current.clone());
}

注意:我还将连词更改为 && 因为在循环中,isAfter 将始终为真。另外,我在第二个子句中省略了 current.day(dia),因为第一个子句已经为当前设置了星期几。

您一天 (result.push(current.clone())) 恰好推送一次,因此您不能期望每天有超过一个约会。您可以使用此条件创建第二个 if 语句:(current.day(7 + dia).isSameOrBefore(end)) 并第二次推送它。

此外,在js中,当满足if中的第一个条件时,其他条件未解决。

const allDays = [0, 3, 5];

function formatToPush(dt_inicio, dt_final, dia, horas) {

    let start = moment(dt_inicio);
    let end = moment(dt_final);

    let result = [];
    let datas = [];
    let current = start.clone();

    if ((current.day(dia).isSameOrAfter(start)) || (current.day(dia).isSameOrAfter(end)) || (current.day(7 + dia).isSameOrBefore(end))) {
        result.push(current.clone());
    }

    if (current.day(7 + dia).isSameOrBefore(end)) {
        result.push(current.clone());
    }

    result.map(m => {
        horas.map(h => {
            m.set({ hour: h.split(':')[0], minute: h.split(':')[1], second: 0, millisecond: 0 });
            datas.push(m.format('YYYY-MM-DD HH:mm:ss'))
        })
    });

    return datas;
}

let final = [];

for (let i in allDays) {
    final.push(...formatToPush('2021-12-01', '2021-12-10', allDays[i], ["10:00", "16:00", "22:30"]))
}

console.log(final)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

如果想使用日期 API 在三行简单的代码中执行此操作,这里有一个替代方法。

考虑到 momentjs 在 42k 中有 17,000 多行代码,我提供了这个替代方案。

供您考虑。

处理从开始到结束(含)的范围时

  1. 将日期转换为 dateString 并查找 Fri 或 Sun 或 Wed
  2. 如果找到 -> 将日期添加到结果数组
  3. 检查下一个日期

const startDate = new Date('2021', '11', '1');
const endDate = new Date('2021', '11', '31');
var tempDate = new Date('2021', '11', '1');
var result = [];

while (tempDate.valueOf() !== endDate.valueOf()) {
  if (/Fri|Sun|Wed/.test(tempDate.toDateString())) result.push(new Date(tempDate));
  tempDate.setDate(tempDate.getDate() + 1);
}
result.forEach(day => console.log(day.toDateString(), day.toISOString().replace("T",' ')));