Home Identifier Source

src/generator.js

import moment from "moment";
import _ from "underscore";
import Bucket from "./bucket";

var units = {
    s: {label: "seconds", length: 1},
    m: {label: "minutes", length: 60},
    h: {label: "hours", length: 60 * 60},
    d: {label: "days", length: 60 * 60 * 24}
};

/**
 * A BucketGenerator
 *
 * To use a BucketGenerator you supply the size of the buckets you want
 * e.g. "1h" for hourly. Then you call bucket() as needed, each time
 * with a date. The bucket containing that date will be returned.
 *
 * Buckets can then be used to aggregate data.
 *
 * @param {string} size The size of the bucket (e.g. 1d, 6h, 5m, 30s)
 */
export default class Generator {

    constructor(size) {
        this._size = size;
        this._length = Generator.getLengthFromSize(size);
    }

    /**
     * Takes the size (e.g. 1d, 6h, 5m, 30s) and returns the length
     * of the bucket in ms.
     */
    static getLengthFromSize(size) {
        let length;

        // Size should be two parts, a number and a letter. From the size
        // we can get the length
        const re = /([0-9]+)([smhd])/;
        const parts = re.exec(size);
        if (parts && parts.length >= 3) {
            const num = parseInt(parts[1], 10);
            const unit = parts[2];
            length = num * units[unit].length * 1000;
        }
        return length;
    }

    static getBucketPosFromDate(date, length) {
        let dd = moment.utc(date).valueOf();
        return parseInt(dd /= length, 10);
    }


    bucketIndex(date) {
        const pos = Generator.getBucketPosFromDate(date, this._length);
        const index = `${this._size}-${pos}`;
        return index;
    }

    bucketIndexList(date1, date2) {
        const pos1 = Generator.getBucketPosFromDate(date1, this._length);
        const pos2 = Generator.getBucketPosFromDate(date2, this._length);
        let indexList = [];
        if (pos1 <= pos2) {
            for (let pos = pos1; pos <= pos2; pos++) {
                indexList.push(`${this._size}-${pos}`);
            }
        }
        return indexList;
    }

    /**
     * Date in is assumed to be local and that the bucket will be
     * created in UTC time. Note that this doesn't really matter
     * for seconds, minutes, or hours. But days will be offset from
     * midnight to midnight, depending on local timezone.
     */
    bucket(date) {
        const index = this.bucketIndex(date);
        return new Bucket(index);
    }

    bucketList(date1, date2) {
        const indexList = this.bucketIndexList(date1, date2);
        return _.map(indexList, (index) => new Bucket(index));
    }
}