human-duration
Version:
Formats a duration as a human-readable string
93 lines (92 loc) • 3.43 kB
JavaScript
;
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;