UNPKG

human-duration

Version:

Formats a duration as a human-readable string

93 lines (92 loc) 3.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.millisecond = { unit: '%ms', milliseconds: 1 }; exports.second = { unit: '%s', milliseconds: 1000 }; exports.minute = { unit: '%m', milliseconds: 60 * 1000 }; exports.hour = { unit: '%h', milliseconds: 60 * 60 * 1000 }; exports.day = { unit: '%d', milliseconds: 24 * 60 * 60 * 1000 }; function renderUnit(count, formatter) { return typeof formatter === 'function' ? formatter(count) : formatter.replace(/%/g, String(count)); } var Duration = (function () { function Duration(_duration) { this._duration = _duration; this._grading = [exports.day, exports.hour, exports.minute, exports.second]; this._separator = ' '; } /** * Sets the grading used for handling durations. */ Duration.prototype.grading = function (grading) { this._grading = grading; return this; }; /** * Sets the separator used between durations. */ Duration.prototype.separator = function (separator) { this._separator = separator; return this; }; /** * Returns the duration formatted into the given number of segments. */ Duration.prototype.segments = function (max) { if (max === void 0) { max = Infinity; } // 1. First pass, sort the parts and give them their own unit durations var sorted = this._grading.slice().sort(function (a, b) { return a.milliseconds - b.milliseconds; }); var duration = this._duration / sorted[0].milliseconds; // Special cases: empty string if no segments, 0 on the smallest // segment if the time is less than its unit. if (sorted.length === 0) { return ''; } if (this._duration < sorted[0].milliseconds) { return renderUnit(Math.floor(duration), sorted[0].unit); } var parts = sorted.map(function (grade, i) { if (i === sorted.length - 1) { return { grade: grade, count: Math.floor(duration) }; } var next = sorted[i + 1]; var count = Math.floor(duration % Math.round(next.milliseconds / grade.milliseconds)); duration /= next.milliseconds / grade.milliseconds; return { grade: grade, count: count }; }); // 2. Second pass, filter out for the max number of segments. var started = false; parts = parts .reverse() .filter(function (metric) { if (max === 0) { return false; } started = started || metric.count > 0; if (!started) { return false; } max--; return true; }); // 3. Get everything back in order and format the string. return this._grading .map(function (grade) { return parts.find(function (p) { return p.grade === grade; }); }) .filter(Boolean) .map(function (part) { return renderUnit(part.count, part.grade.unit); }) .join(this._separator); }; /** * Converts the duration to a string. */ Duration.prototype.toString = function (segments) { return this.segments(segments); }; return Duration; }()); exports.Duration = Duration; function fmt(duration) { return new Duration(duration); } exports.fmt = fmt;