131 lines
3.9 KiB
JavaScript
131 lines
3.9 KiB
JavaScript
var _ = require('underscore');
|
|
|
|
var AGGREGATION_DATA = {
|
|
second: { unit: 'second', factor: 1 },
|
|
minute: { unit: 'minute', factor: 1 },
|
|
hour: { unit: 'hour', factor: 1 },
|
|
day: { unit: 'day', factor: 1 },
|
|
week: { unit: 'day', factor: 7 },
|
|
month: { unit: 'month', factor: 1 },
|
|
quarter: { unit: 'month', factor: 3 },
|
|
year: { unit: 'month', factor: 12 },
|
|
decade: { unit: 'month', factor: 120 },
|
|
century: { unit: 'month', factor: 1200 },
|
|
millennium: { unit: 'month', factor: 12000 }
|
|
};
|
|
|
|
var helper = {};
|
|
|
|
function trimBuckets (buckets, filledBuckets, totalBuckets) {
|
|
var index = null;
|
|
var keepGoing = true;
|
|
for (var i = filledBuckets.length - 1; i >= 0 && keepGoing && (_.isFinite(totalBuckets) ? i >= totalBuckets : true); i--) {
|
|
if (filledBuckets[i]) {
|
|
keepGoing = false;
|
|
} else {
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
return index !== null
|
|
? buckets.slice(0, index)
|
|
: buckets;
|
|
}
|
|
|
|
helper.fillTimestampBuckets = function (buckets, start, aggregation, numberOfBins, from, totalBuckets) {
|
|
var filledBuckets = []; // To catch empty buckets
|
|
var definedBucket = false;
|
|
|
|
for (var i = 0; i < numberOfBins; i++) {
|
|
definedBucket = buckets[i] !== undefined;
|
|
filledBuckets.push(definedBucket);
|
|
|
|
var bucketStart = this.add(start, i, aggregation);
|
|
var nextBucketStart = this.add(start, i + 1, aggregation);
|
|
|
|
buckets[i] = _.extend({
|
|
bin: i,
|
|
start: bucketStart,
|
|
end: nextBucketStart - 1,
|
|
next: nextBucketStart,
|
|
freq: 0
|
|
}, buckets[i]);
|
|
delete buckets[i].timestamp;
|
|
}
|
|
|
|
return from === 'totals'
|
|
? buckets
|
|
: trimBuckets(buckets, filledBuckets, totalBuckets);
|
|
};
|
|
|
|
helper.fillNumericBuckets = function (buckets, start, width, numberOfBins) {
|
|
for (var i = 0; i < numberOfBins; i++) {
|
|
var bucketStart = start + (i * width);
|
|
var commonBucketEnd = start + ((i + 1) * width);
|
|
var isLastBucket = (i + 1) === numberOfBins;
|
|
var bucketEnd = (isLastBucket && buckets[i]) ? buckets[i].max : commonBucketEnd;
|
|
var filledBucket = _.extend({}, {
|
|
bin: i,
|
|
start: bucketStart,
|
|
end: bucketEnd,
|
|
freq: 0
|
|
}, buckets[i]);
|
|
buckets[i] = filledBucket;
|
|
}
|
|
};
|
|
|
|
helper.hasChangedSomeOf = function (list, changed) {
|
|
return _.some(_.keys(changed), function (key) {
|
|
return _.contains(list, key);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Add a `number` of aggregations to the provided timestamp
|
|
*
|
|
* @param {number} timestamp - Starting timestamp
|
|
* @param {number} number - Number of aggregations to add
|
|
* @param {object} aggregation
|
|
* @param {string} aggregation.unit - unit of the aggregation
|
|
* @param {number} aggregation.factor - number of aggretagion units
|
|
*/
|
|
helper.add = function (timestamp, number, aggregation) {
|
|
if (!AGGREGATION_DATA.hasOwnProperty(aggregation)) {
|
|
throw Error('aggregation "' + aggregation + '" is not defined');
|
|
}
|
|
var date = new Date(timestamp * 1000);
|
|
var unit = AGGREGATION_DATA[aggregation].unit;
|
|
var factor = AGGREGATION_DATA[aggregation].factor;
|
|
var value = number * factor;
|
|
switch (unit) {
|
|
case 'second':
|
|
return date.setUTCSeconds(date.getUTCSeconds() + value) / 1000;
|
|
case 'minute':
|
|
return date.setUTCMinutes(date.getUTCMinutes() + value) / 1000;
|
|
case 'hour':
|
|
return date.setUTCHours(date.getUTCHours() + value) / 1000;
|
|
case 'day':
|
|
return date.setUTCDate(date.getUTCDate() + value) / 1000;
|
|
case 'month':
|
|
var n = date.getUTCDate();
|
|
date.setUTCDate(1);
|
|
date.setUTCMonth(date.getUTCMonth() + value);
|
|
date.setUTCDate(Math.min(n, _getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth())));
|
|
return date.getTime() / 1000;
|
|
default:
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
/* Internal functions */
|
|
|
|
function _getDaysInMonth (year, month) {
|
|
return [31, (_isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
|
|
}
|
|
|
|
function _isLeapYear (year) {
|
|
return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
|
|
}
|
|
|
|
module.exports = helper;
|