ts-rollup
Version:
Aggragation util for timestamps
90 lines (85 loc) • 3.3 kB
JavaScript
var spigot = require("stream-spigot")
var concat = require("concat-stream")
let moment = require('moment-timezone');
var bluepromise = require("bluebird");
let _ = require('lodash');
var agg = require("./aggregates");
function isFunction(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
function timeseries(opts, cb) {
try {
var localFunction;
if (isFunction(opts.fcn)) {
localFunction = agg['func'](opts.fcn)
} else {
localFunction = agg[opts.fcn];
}
spigot({ objectMode: true }, opts.data).pipe(localFunction(opts.timestampField, opts.interval, null, opts.tz || 'UTC')).pipe(concat(function (r) {
if (!opts.interval) return cb(null, r);
if (opts.fill == undefined) return cb(null, r);
// console.log(moment(opts.start).tz(opts.tz || 'UTC').startOf(opts.interval), "start");
// fit the sparse bins into strict bins
let start = moment(opts.start).startOf(opts.interval);
let end = opts.end;
let bins = [];
while (start.valueOf() <= end) {
let b = {};
b[opts.timestampField] = start.valueOf();
let hit = _.find(r, b);
if (hit) {
bins.push(hit);
}
else {
if (opts.indicateGenerated) {
b[opts.indicateGenerated] = true;
}
if (_.isNumber(opts.fill)) {
_.forIn(r[0], function (v, k) {
if (k == opts.timestampField) return;
if (typeof v == 'string') return;
b[k] = opts.fill;
});
}
else if (opts.fill == 'previous') {
let ref;
if (bins.length == 0) ref = r[0];
else ref = bins[bins.length - 1];
_.forIn(ref, function (v, k) {
if (k == opts.timestampField) return;
b[k] = (bins.length == 0) ? 0 : v;
});
}
else {
throw ('unsupported fill: ', opts.fill);
}
bins.push(b);
}
start = start.add(1, opts.interval);
}
cb(null, bins);
}));
} catch (err) {
cb(err);
}
};
/*
var options = {
data: tData,
timestampField: "timestamp",
fcn: "sum" | "mean" | "median" | "mode" | "variance" | "percentile"
interval: "hour",
tz: "America/Los_Angeles",
fill: 0,
};
*/
module.exports.rollup = function (options) {
timeseriesFunction = bluepromise.promisify(timeseries);
var dates = options.data.map(function (x) { return x[options.timestampField]; });
var earliest = Math.min.apply(null, dates);
var latest = Math.max.apply(null, dates);
options.start = options.start || earliest;
options.end = options.end || latest;
return timeseriesFunction(options);
}