Reputation: 337
I have some JSON data I need to divide then aggregate. Here is a sample of its format.
data2 = [{"startDate": 1396263600.0, "adId": 2483231759355, "endDate": 1401101940.0, "impressions": 754831},
{"startDate": 1393851600.0, "adId": 2750329551133, "endDate": 1404212340.0, "impressions": 3947368},
{"startDate": 1401620400.0, "adId": 1311595275159, "endDate": 1404212340.0, "impressions": 630000}];
I want to uniformly divide up the impressions for each day in the date range. (ie if there are 100 impressions in a range of 10 days then each day will get 10 impressions). Then I want to aggregate the number of impressions on all the adIds for each day (ie if there are 2 ads on one day, then they get combined). So the final result will be a array of days and impressions. Not too familiar with javascript so not sure if there are any functions to make my life easier here. Any suggestions?
I plan on using this function to count number of days between dates:
function days_between(date1, date2) {
// The number of milliseconds in one day
var ONE_DAY = 1000 * 60 * 60 * 24;
// Convert both dates to milliseconds
var date1_ms = date1 * 1000;
var date2_ms = date2 * 1000;
// Calculate the difference in milliseconds
var difference_ms = Math.abs(date1_ms - date2_ms);
// Convert back to days and return
return Math.round(difference_ms/ONE_DAY);
}
Upvotes: 0
Views: 2440
Reputation: 1654
Are you thinking about something like this?
function days_between(date1, date2) {
var date1_ms = new Date(date1*1000).getTime();
var date2_ms = new Date(date2*1000).getTime();
// Calculate the difference in milliseconds
var difference_ms = Math.abs(date1_ms - date2_ms);
// Convert back to days and return
return Math.ceil(difference_ms / (1000 * 3600 * 24));
}
function aggregate(data) {
result = [];
for (var i = 0; i < data.length; i++) {
var numOfDays = days_between( data[i].startDate, data[i].endDate );
var adId = data[i].adId;
var impressionPerDay = (data[i].impressions / numOfDays);
for (var j = 0; j < numOfDays; j++) {
var obj = {};
obj.date = new Date(new Date(data[i].startDate*1000).getTime() + (j * (1000 * 3600 * 24))).getTime();
obj.impressions = impressionPerDay;
obj.adId = adId;
result.push(obj);
}
}
return result;
}
function aggregateAdIds(data) {
var result = {};
for (var i = 0; i < data.length; i++) {
if (data[i].adId in result) result[data[i].adId].push({"date": data[i].date, "impressions": data[i].impressions});
else result[data[i].adId] = [{"date": data[i].date, "impressions": data[i].impressions}];
}
return result;
}
var data = [{"startDate": 1396263600.0, "adId": 2483231759355, "endDate": 1401101940.0, "impressions": 754831},{"startDate": 1393851600.0, "adId": 2750329551133, "endDate": 1404212340.0, "impressions": 3947368},{"startDate": 1401620400.0, "adId": 1311595275159, "endDate": 1404212340.0, "impressions": 630000}];
var final = aggregateAdIds(aggregate(data));
UPDATED
function days_between(date1, date2) {
var date1_ms = new Date(date1*1000).getTime();
var date2_ms = new Date(date2*1000).getTime();
// Calculate the difference in milliseconds
var difference_ms = Math.abs(date1_ms - date2_ms);
// Convert back to days and return
return Math.ceil(difference_ms / (1000 * 3600 * 24));
}
function aggregate(data) {
var map = {};
var result = [];
for (var i = 0; i < data.length; i++) {
var numOfDays = days_between( data[i].startDate, data[i].endDate );
console.log('days : '+ numOfDays);
var impressionPerDay = (data[i].impressions / numOfDays);
for (var j = 0; j < numOfDays; j++) {
var tempDate = new Date(data[i].startDate*1000);
tempDate.setDate(tempDate.getDate() + j);
var date = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate(), 0, 0 ,0, 0);
if (date.getTime() in map) map[date.getTime()] += impressionPerDay;
else map[date.getTime()] = impressionPerDay;
}
}
for (var key in map) {
result.push({'date' : Number(key), 'impressions' : map[key]});
}
result.sort(function(a,b){return a.date > b.date});
return result;
}
var data = [{"startDate": 1396263600.0, "adId": 2483231759355, "endDate": 1401101940.0, "impressions": 754831},{"startDate": 1393851600.0, "adId": 2750329551133, "endDate": 1404212340.0, "impressions": 3947368},{"startDate": 1401620400.0, "adId": 1311595275159, "endDate": 1404212340.0, "impressions": 630000}];
console.log(aggregate(data));
updated fiddle : link
Upvotes: 1
Reputation: 16068
So something like this? This gets the amount of impressions in each day into a javascript object, with each date in miliseconds as key (for example 1403953200000:21000 ). You can convert the miliseconds into a date if you want, and 21000 is the impressions on that day
var result={};
for(var i=0;i<data2.length;i++){
var end = new Date(data2[i].endDate*1000);
var start = new Date(data2[i].startDate*1000);
var diff= Math.abs(end.getTime() - start.getTime());
var diffDays = Math.ceil(diff / (1000 * 3600 * 24));
for (; start <= end; start.setDate(start.getDate() + 1)) {
var miliseconds=start.getTime();
if(!result.hasOwnProperty(miliseconds)) result[miliseconds]=0;
result[miliseconds]+=data2[i].impressions/diffDays;
}
}
console.log(result)
Update:
function aggregate(data2) {
var result={};
var result_arr=[];
for(var i=0;i<data2.length;i++){
var end = new Date(data2[i].endDate*1000);
end.setHours(0);
end.setMinutes(0);
end.setSeconds(0);
var start = new Date(data2[i].startDate*1000);
start.setHours(0);
start.setMinutes(0);
start.setSeconds(0);
var diff= Math.abs(end.getTime() - start.getTime());
var diffDays = Math.ceil(diff / (1000 * 3600 * 24));
console.log(start.toString(),end.toString(), diffDays)
for (; start <= end; start.setDate(start.getDate() + 1)) {
var miliseconds=start.getTime();
if(!result.hasOwnProperty(miliseconds)) result[miliseconds]=0;
result[miliseconds]+=data2[i].impressions/diffDays;
}
}
for(var key in result){
result_arr.push({date:Number(key), impressions: result[key]});
}
result_arr.sort(function(a,b){return a.date > b.date})
return result_arr;
}
Fiddle with my working solution: http://jsfiddle.net/juvian/6R7mu/14/
Upvotes: 0