使用 while 和 reduce 转换对象数组

Transform array of objects with while and reduce

我需要有关转换对象数组的帮助。到目前为止,我已经设法获得了初始(开始)和结束(结束)之间的所有日期。

这是我收到并尝试转化的。

 const fetchedOffers = [{
    _id: 'dsd87878',
    professional: 'd2ycdd',
    specialty: '704505',
    begin: new Date('2020-04-10T07:00:00.169Z'),
    end: new Date('2020-04-11T21:00:00.169Z'),
    interval: 1200000,
  },
  {
    _id: 'ddd67878',
    professional: '25c0a8',
    specialty: '704505',
    begin: new Date('2020-06-29T08:00:00.169Z'),
    end: new Date('2020-06-30T12:00:00.169Z'),
    interval: 1200000,
  }
];

const hours = fetchedOffers.reduce((prev, acc) => {
  let currentDate = acc.begin.getTime()
  const endDate = acc.end.getTime()

  while (currentDate < endDate) {
    const d = new Date(currentDate)
    if (d.getHours() > 7 && d.getHours() < 20 && d.getDay() < 6 && d.getDay() > 0) {
      prev.push({
        date: new Date(d).toLocaleString('es-CL')
      })
    }
    currentDate = currentDate + acc.interval
  }
  return prev
}, [])
  console.log(hours)

我们的想法是您可以像这样生成一个对象数组:

    [
      {
        professional: 'd2ycdd',
        specialty: '704505',
        date: [
          {
            offer: 'dsd87878',
            date: '4/10/2020',
            hours: ['07:00', '07:20', '07:40', '08:00',...]
          },
          {
            offer: 'dsd87878',
            date: '4/11/2020',
            hours: [..., '20:00', '20:20', '20:40', '21:00']
          }
        ]
      },
      {
        professional: '25c0a8',
        specialty: '704505',
        date: [
          {
            offer: 'ddd67878',
            date: '6/29/2020',
            hours: ['08:00', '08:20', '08:40', '09:00',...]
          },
          {
            offer: 'ddd67878',
            date: '6/30/2020',
            hours: [..., '11:00', '11:20', '11:40', '12:00']
          }
        ]
      },
    ]

我想按专业 ID 和日期(没有时间)分组。每个日期都是从开始日期 (begin) 开始并添加间隔直到到达结束日期。此外,我在显示小时数时添加了其他条件,例如省略 20 到 7 小时之间的小时数以及仅从周一到周五。

我该怎么做?到目前为止,我只得到开始日期和结束日期之间的所有日期,但我需要按日期和专业分组

这里会告诉 reduce 不是正确的方法,您可能需要复杂的转换。

也检查时区或使用一些库 (moment.js?),一些日期可能是本地日期、UTC 等。使代码段中的 I/O 小时值(字符串)看起来相同。

const fetchedOffers = [{
    _id: 'dsd87878',
    professional: 'd2ycdd',
    specialty: '704505',
    begin: new Date('2020-04-10T07:00:00.169Z'),
    end: new Date('2020-04-11T21:00:00.169Z'),
    interval: 1200000,
  },
  {
    _id: 'ddd67878',
    professional: '25c0a8',
    specialty: '704505',
    begin: new Date('2020-06-29T08:00:00.169Z'),
    end: new Date('2020-06-30T12:00:00.169Z'),
    interval: 1200000,
  }
];

let res = [];
document.body.innerText = JSON.stringify(
    createNewOffers(fetchedOffers, res)
).replace(/,/g, ',\n').replace(/(["0-9:]{7}),\n/g, ',');
function createNewOffers(fetchedOffers, res) {
    for(var acc of fetchedOffers) {
        let currentDate = acc.begin;
        currentDate = currentDate.setHours(currentDate.getHours() + currentDate.getTimezoneOffset() / 60);
        let endDate = acc.end;
        endDate = endDate.setHours(endDate.getHours() + endDate.getTimezoneOffset() / 60);
        let date = [null, null];
    
        while (currentDate <= endDate) {
            let d = new Date(currentDate)
            if (d.getHours() >= 7 && (d.getHours() + d.getMinutes()/60) <= 20 && d.getDay() < 6 && d.getDay() > 0 && date[1] == null) {
                if (date[0] == null) date[0] = {
                    offer: acc._id,
                    date: d.toLocaleDateString('en'),
                    hours: []
                };
                date[0].hours.push(new Date(d).toLocaleTimeString('es-CL').substr(0,5))
            } else {
                if (date[1] == null) {
                  d.setDate(d.getDate() + 1);
                  d.setMinutes(0);
                  currentDate = d.setHours(8);
                  date[1] = {
                    offer: acc._id,
                    date: d.toLocaleDateString('en'),
                    hours: []
                  };
                }
                date[1].hours.push(new Date(d).toLocaleTimeString('es-CL').substr(0,5))
            }
            currentDate = currentDate + acc.interval
        } 
        res.push({
            professional: acc.professional,
            specialty: acc.specialty,
            date: date
        });
    }
    return res;
}