-
Notifications
You must be signed in to change notification settings - Fork 264
/
histogram-helper.js
130 lines (114 loc) · 3.88 KB
/
histogram-helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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;