简体   繁体   中英

Fill missing dates for sequential data

My input data is in the format of:

 { "BeginDate": "2017-01-05", "EndDate": "2017-01-31", "Points": [ { "Date": "2017-01-05", "Value": 64 }, { "Date": "2017-01-08", "Value": 251 }, { "Date": "2017-01-15", "Value": 144 }, { "Date": "2017-01-29", "Value": 216 }] } 

Except for the BeginDate, other dates are the beginning of a week. What may be a good way for me to auto-fill zero for the missing date, for example, "2017-01-22"?

My expected output is:

 { "BeginDate": "2017-01-05", "EndDate": "2017-01-31", "Points": [ { "Date": "2017-01-05", "Value": 64 }, { "Date": "2017-01-08", "Value": 251 }, { "Date": "2017-01-15", "Value": 144 }, { "Date": "2017-01-22", "Value": 0 }, { "Date": "2017-01-29", "Value": 216 }] } 

Create a nextWeek from start date. Use a while loop to check each time if that week exists then increment 7 days until nextWeek exceeds end date

 const end = new Date(data.EndDate), start = new Date(data.BeginDate), nextWeek = new Date(start); // adjust to Sunday nextWeek.setDate(start.getDate() + (7 - start.getDay()) % 7); while (+nextWeek <= +end) { // create formated date string YYYY-MM-DD const dateStr = [nextWeek.getFullYear(), padNum(nextWeek.getMonth() + 1), padNum(nextWeek.getDate())].join('-'), // see if that Date exists weekExists = data.Points.find(o=> o.Date === dateStr); if (!weekExists) { // push new point if not data.Points.push({ Date: dateStr, Value: 0 }) } // increment 7 days nextWeek.setDate(nextWeek.getDate() + 7) } // sort Points if needed data.Points.sort((a,b) => new Date(a.Date)- new Date(b.Date)); console.log(JSON.stringify(data.Points)) // helper to add leading zeros function padNum(num) { return ('0' + num).slice(-2) } 
 <script> var data = { "BeginDate": "2017-01-05", "EndDate": "2017-01-31", "Points": [{ "Date": "2017-01-05", "Value": 64 }, { "Date": "2017-01-08", "Value": 251 }, { "Date": "2017-01-15", "Value": 144 }, { "Date": "2017-01-29", "Value": 216 }] } </script> 

The following will pretty much do it. Please let me know if you need any help explaining what the code does.

 var data = { "BeginDate": "2018-01-05", "EndDate": "2018-01-31", "Points": [ { "Date": "2018-01-05", "Value": 64 }, { "Date": "2018-01-08", "Value": 251 }, { "Date": "2018-01-15", "Value": 144 }, { "Date": "2018-01-29", "Value": 216 }] }; var mondays = (dates=[]) => start => end => { if(start>=end){ return dates; } const newStart = new Date(start.getTime()); if(newStart.getDay()!==1){ return mondays(dates)( //optimization from charlietfl except getting mondays new Date(newStart.setDate(newStart.getDate() + (8 - newStart.getDay()) % 7)) )(end); } return mondays ( (start.getDay()===1) ? dates.concat([start]) : dates ) ( new Date(newStart.setDate(newStart.getDate()+7)) ) (end); } var twoDigits = num =>//or you could try leftPad ("00"+num.toString()).slice(-2); //dates are indeed iso 8601 var dataWithAllMondays = mondays()(new Date(data.BeginDate))(new Date(data.EndDate)) .map( date=> `${date.getFullYear()}-${twoDigits(date.getMonth()+1)}-${twoDigits(date.getDate())}` ) .reduce( (data,date)=>{ if(data.Points.filter(d=>d.Date===date).length===0){ return { ...data, Points:data.Points.concat([{ Date:date,Value:0 }]) }; } return data; }, data ); dataWithAllMondays.Points=dataWithAllMondays.Points.sort( (a,b)=> (a.Date>b.Date)//there is no a === b ? 1 : -1 ) console.log(dataWithAllMondays.Points); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM