Home Identifier Source

src/util.js

import moment from "moment";
import _ from "underscore";
import TimeRange from "./range";

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

/**
 * This function will take an index, which may be of two forms:
 *     2015-07-14  (day)
 *     2015-07     (month)
 *     2015        (year)
 * or:
 *     1d-278      (range, in n x days, hours, minutes or seconds)
 *
 * and return a TimeRange for that time. The TimeRange may be considered to be
 * local time or UTC time, depending on the utc flag passed in.
 */
export default {

    rangeFromIndexString: function (index, utc) {
        const isUTC = !_.isUndefined(utc) ? utc : true;
        const parts = index.split("-");

        let beginTime;
        let endTime;

        switch (parts.length) {
            case 3:
                // A day, month and year e.g. 2014-10-24
                if (!_.isNaN(parseInt(parts[0], 10)) &&
                    !_.isNaN(parseInt(parts[1], 10)) &&
                    !_.isNaN(parseInt(parts[2], 10))) {
                    const year = parseInt(parts[0], 10);
                    const month = parseInt(parts[1], 10);
                    const day = parseInt(parts[2], 10);
                    beginTime = isUTC ? moment.utc([year, month - 1, day]) :
                                        moment([year, month - 1, day]);
                    endTime = isUTC ? moment.utc(beginTime).endOf("day") :
                                      moment(beginTime).endOf("day");
                }
            break;

            case 2:
                // Size should be two parts, a number and a letter if it's a
                // range based index, e.g 1h-23478
                const rangeRegex = /([0-9]+)([smhd])/;
                const sizeParts = rangeRegex.exec(parts[0]);
                if (sizeParts && sizeParts.length >= 3 &&
                    !_.isNaN(parseInt(parts[1], 10))) {
                    const pos = parseInt(parts[1], 10);
                    const num = parseInt(sizeParts[1], 10);
                    const unit = sizeParts[2];
                    const length = num * units[unit].length * 1000;

                    beginTime = isUTC ? moment.utc(pos * length) :
                                        moment(pos * length);
                    endTime = isUTC ? moment.utc((pos + 1) * length) :
                                      moment((pos + 1) * length);

                // A month and year e.g 2015-09
                } else if (!_.isNaN(parseInt(parts[0], 10)) &&
                    !_.isNaN(parseInt(parts[1], 10))) {
                    const year = parseInt(parts[0], 10);
                    const month = parseInt(parts[1], 10);
                    beginTime = isUTC ? moment.utc([year, month - 1]) :
                                        moment([year, month - 1]);
                    endTime = isUTC ? moment.utc(beginTime).endOf("month") :
                                      moment(beginTime).endOf("month");
                }
            break;

            // A year e.g. 2015
            case 1:
                const year = parts[0];
                beginTime = isUTC ? moment.utc([year]) :
                                    moment.utc([year]);
                endTime = isUTC ? moment.utc(beginTime).endOf("year") :
                                  moment(beginTime).endOf("year");
            break;
        }

        if (beginTime && beginTime.isValid() && endTime && endTime.isValid()) {
            return new TimeRange(beginTime, endTime);
        } else {
            return undefined;
        }
    },

    /**
     * Returns a nice string for the index. If the index is of the form
     * 1d-2345 then just that string is returned (there's not nice way to put
     * it), but if it represents a day, month, or year (e.g. 2015-07) then a
     * nice string like "July" will be returned. It's also possible to pass in
     * the format of the reply for these types of strings. See moment's format
     * naming conventions:
     * http://momentjs.com/docs/#/displaying/format/
     */
    niceIndexString: function (index, format) {
        let t;

        const parts = index.split("-");
        switch (parts.length) {
            case 3:
                if (!_.isNaN(parseInt(parts[0], 10)) &&
                    !_.isNaN(parseInt(parts[1], 10)) &&
                    !_.isNaN(parseInt(parts[2], 10))) {
                    const year = parseInt(parts[0], 10);
                    const month = parseInt(parts[1], 10);
                    const day = parseInt(parts[2], 10);
                    t = moment.utc([year, month - 1, day]);
                    if (format) {
                        return t.format(format);
                    } else {
                        return t.format("MMMM Do YYYY");
                    }

                }
            break;

            case 2:
                const rangeRegex = /([0-9]+)([smhd])/;
                const sizeParts = rangeRegex.exec(parts[0]);
                if (sizeParts && sizeParts.length >= 3 &&
                    !_.isNaN(parseInt(parts[1], 10))) {
                    return index;
                } else if (!_.isNaN(parseInt(parts[0], 10)) &&
                    !_.isNaN(parseInt(parts[1], 10))) {
                    const year = parseInt(parts[0], 10);
                    const month = parseInt(parts[1], 10);
                    t = moment.utc([year, month - 1]);
                    if (format) {
                        return t.format(format);
                    } else {
                        return t.format("MMMM");
                    }
                }
            break;

            case 1:
                const year = parts[0];
                t = moment.utc([year]);
                if (format) {
                    return t.format(format);
                } else {
                    return t.format("YYYY");
                }
            break;
        }
        return index;
    }
};