javascript - 将按升序排序的日期数组合并为日期范围数组

标签 javascript arrays node.js date

我有一个日期数组,我想通过检查连续日期来创建包含开始和结束的对象。 例如。

dateArray = [
                "2020-01-22T00:00:00.000Z",
                "2020-01-23T00:00:00.000Z",
                "2020-01-28T00:00:00.000Z",
                "2020-01-29T00:00:00.000Z",
                "2020-01-30T00:00:00.000Z",
                "2020-01-31T00:00:00.000Z",
                "2020-02-01T00:00:00.000Z",
                "2020-02-02T00:00:00.000Z",
                "2020-02-03T00:00:00.000Z",
                "2020-02-04T00:00:00.000Z",
                "2020-02-05T00:00:00.000Z",
                "2020-02-06T00:00:00.000Z",
                "2020-02-07T00:00:00.000Z",
                "2020-02-16T00:00:00.000Z",
                "2020-02-17T00:00:00.000Z",
                "2020-02-18T00:00:00.000Z",
                "2020-02-19T00:00:00.000Z",
                "2020-02-20T00:00:00.000Z"
            ]

myRequirement = [{
    start: "2020-01-22T00:00:00.000Z",
    end: "2020-01-23T00:00:00.000Z"
  },
  {
    start: "2020-01-28T00:00:00.000Z",
    end: "2020-02-07T00:00:00.000Z"
  },
  {
    start: "2020-02-16T00:00:00.000Z",
    end: "2020-02-20T00:00:00.000Z"
  }
]

我想在node.js 中使用它。 我尝试使用一些嵌套的 for 循环。 首先,我在主 dateArray 上运行循环,然后检查它是否是第一个日期,如果是第一个日期,则将其存储为第一个对象开始日期,然后在下一个日期情况下检查它是否是前一个日期的下一个最日期。

let gapArray = [];
            let startEndObj = {};
            let tempStartDate;
            let tempEndDate;

            let tempNextDate;
            await asyncForEach(finalAvailablityDatesArrayOFi.availeblityDatesArray, async (availeblityDatesArrayOFi) => {
                console.log("availeblityDatesArrayOFi", availeblityDatesArrayOFi);

                if (!tempStartDate) {
                    console.log("In if");
                    startEndObj.startDate = availeblityDatesArrayOFi;
                    tempStartDate = availeblityDatesArrayOFi;
                    let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
                    tempNextDate = new Date(oneDatePlus);
                    console.log("startEndObj", startEndObj);
                }
                else if (tempStartDate) {
                    console.log("in else");

                    if (new Date(availeblityDatesArrayOFi).getTime() == new Date(tempNextDate).getTime()) {
                        console.log("Do nothing!");
                        tempStartDate = availeblityDatesArrayOFi;
                        tempEndDate = availeblityDatesArrayOFi;
                        let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
                        tempNextDate = new Date(oneDatePlus);
                    }
                    else {
                        startEndObj.endDate = new Date(tempEndDate);
                        gapArray.push(startEndObj);
                        tempStartDate = '';
                        tempEndDate = '';
                        startEndObj = {};
                    }
                }
            });

谢谢!

最佳答案

看起来像是 Array.prototype.reduce() 的工作.

<小时/>

注意:以下假设满足几个先决条件:

  • 源数组项是有效的 ISO 格式的日期字符串或其他字符串,可通过 new Date() 进行解析构造函数,否则应采用受支持的格式之一
  • 源数组项按升序排序,否则 Array.prototype.sort()方法必须提前申请
  • 数组项不包含一天中的时间部分(或者这部分对于所有项都完全相同),否则连续的日期记录可能恰好有大于 864e5 毫秒(1 天)的差异,需要更复杂的比较
<小时/>

您可以遍历数组并将当前项目与上一个/下一个项目进行比较,一旦间隔大于 1 天,您就可以将新范围插入结果数组或修改最后一个项目的结束日期:

const src = ["2020-01-22T00:00:00.000Z","2020-01-23T00:00:00.000Z","2020-01-28T00:00:00.000Z","2020-01-29T00:00:00.000Z","2020-01-30T00:00:00.000Z","2020-01-31T00:00:00.000Z","2020-02-01T00:00:00.000Z","2020-02-02T00:00:00.000Z","2020-02-03T00:00:00.000Z","2020-02-04T00:00:00.000Z","2020-02-05T00:00:00.000Z","2020-02-06T00:00:00.000Z","2020-02-07T00:00:00.000Z","2020-02-16T00:00:00.000Z","2020-02-17T00:00:00.000Z","2020-02-18T00:00:00.000Z","2020-02-19T00:00:00.000Z","2020-02-20T00:00:00.000Z"],
     ranges = src.reduce((res,date,idx,self) => {
      const rangeStart = !idx || new Date(date) - new Date(self[idx-1]) > 864e5,
            rangeEnd = idx == self.length-1 || new Date(self[idx+1]) - new Date(date) > 864e5
      if(rangeStart) res.push({startdate:date,enddate:date}) 
      else if(rangeEnd) res[res.length-1]['enddate'] = date 
      return res
     }, [])
     
console.log(ranges)
.as-console-wrapper {min-height:100%}

关于javascript - 将按升序排序的日期数组合并为日期范围数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59859997/

相关文章:

java - 如何以毫秒精度同步 2 个系统之间的时间?

javascript - 如何使 for 循环与 async.parallel() 一起工作

c - 将合并操作的结果直接复制到辅助数组时,合并排序不起作用

javascript - 嵌套在 JSON 对象数组中的 JSON 对象数组

node.js - 如何从主机连接到 docker 容器的链接别名

javascript - 关闭所有通过委托(delegate)创建的打开的 Bootstrap 弹出窗口

Javascript:生成范围内的随机数,避免前两个

arrays - Bash 脚本和 gdal - 如何引用数组变量中的元素?

node.js - 即使 detached 设置为 true,父进程也会杀死子进程

javascript - 使用 multer-s3-transform 上传到 s3 之前使用 imagemin 转换照片