@dbpiper/timer
Version:
Simple module to time your code JavaScript or TypeScript code, to see how long it took to run.
224 lines (173 loc) • 6.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _moment = _interopRequireDefault(require("moment"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Represents a duration, however each unit is treated as the remainder
* starting from the largest possible one. In other words, it is setup
* just like how a person would say how much time has passed.
*
* Rounds all numbers to two decimal places as the main intended purpose is for
* printing output rather than internal programmatic use.
*
* @class FormattedDuration
*/
class FormattedDuration {
/**
* Gets the amount of milliseconds in the duration rounded to the number
* of digits provided by precision.
*/
get milliseconds() {
return FormattedDuration._roundNumber(this._duration.milliseconds());
}
static getUnitAndAmount(UAs, unitName) {
return _lodash.default.first(_lodash.default.filter(UAs, ua => ua.unitName === unitName));
}
static nonMsUnitAndAmounts(UAs) {
const nonMs = _lodash.default.filter(UAs, ua => !_lodash.default.includes(ua.unitName, 'milli'));
return nonMs;
}
/**
* Gets the amount of seconds in the duration rounded to the number
* of digits provided by precision.
*/
get seconds() {
return FormattedDuration._roundNumber(this._duration.seconds());
}
/**
* Gets the amount of minutes in the duration rounded to the number
* of digits provided by precision.
*/
get minutes() {
return FormattedDuration._roundNumber(this._duration.minutes());
}
/**
* Gets the amount of hours in the duration rounded to the number
* of digits provided by precision. Since hours is the largest unit
* that FormattedDuration supports, anything larger than an hour will
* simply be in this function. For example: the information that
* the duration is 5 days long would be found here as: 120 hours.
*/
get hours() {
return FormattedDuration._roundNumber(Math.trunc(this._duration.asHours()));
}
constructor(duration) {
_defineProperty(this, "_duration", void 0);
_defineProperty(this, "_stringifyAmounts", () => {
// if we're printing seconds then we don't want to print milliseconds
// that is, we only ever print milliseconds by themselves as they
// are so insignificantly small that if there are seconds involved,
// then we'll just print the milliseconds as parts of a second.
const millisecondsInSecond = 1000;
let seconds;
if (this.seconds >= 1) {
seconds = FormattedDuration._roundNumber(this.seconds + this.milliseconds / millisecondsInSecond);
} else {
seconds = FormattedDuration._roundNumber(this.seconds);
}
return {
milliseconds: `${this.milliseconds}`,
seconds: `${seconds}`,
minutes: `${this.minutes}`,
hours: `${this.hours}`
};
});
if (FormattedDuration._isNumber(duration)) {
const momentDuration = _moment.default.duration(duration, 'milliseconds');
this._duration = momentDuration;
} else {
this._duration = duration;
}
}
toString() {
const unitAndAmounts = this.getNonEmptyUnitAndAmounts();
const nonMs = FormattedDuration.nonMsUnitAndAmounts(unitAndAmounts);
const sortedNonMs = _lodash.default.sortBy(nonMs, 'priority');
const snmStrings = _lodash.default.map(sortedNonMs, ua => `${ua.amount} ${ua.unitString}`);
const lastNonMs = _lodash.default.last(snmStrings);
if (nonMs.length === 0) {
const milliseconds = FormattedDuration.getUnitAndAmount(unitAndAmounts, 'milliseconds');
if (milliseconds) {
return `${milliseconds.amount} ${milliseconds.unitString}`;
}
}
if (lastNonMs) {
const init = _lodash.default.initial(snmStrings);
const last = lastNonMs;
if (init.length > 0) {
return `${init.join(', ')} and ${last}`;
}
return `${last}`;
} // shouldn't ever happen, but this is here for completeness
// as typescript will say that all paths aren't covered if it isn't
// jest complains that this is uncovered though 😞
return '';
}
getNonEmptyUnitAndAmounts() {
const stringifiedUnits = this.stringifyUnits();
const stringifiedAmounts = this._stringifyAmounts();
const unitAndAmounts = [{
unitName: 'milliseconds',
amount: stringifiedAmounts.milliseconds,
unitString: stringifiedUnits.milliseconds,
priority: 3
}, {
unitName: 'seconds',
amount: stringifiedAmounts.seconds,
unitString: stringifiedUnits.seconds,
priority: 2
}, {
unitName: 'minutes',
amount: stringifiedAmounts.minutes,
unitString: stringifiedUnits.minutes,
priority: 1
}, {
unitName: 'hours',
amount: stringifiedAmounts.hours,
unitString: stringifiedUnits.hours,
priority: 0
}];
const nonEmptyUAs = _lodash.default.filter(unitAndAmounts, ua => {
const numAmount = Number(ua.amount);
if (!isNaN(numAmount) && numAmount > 0) {
return true;
}
return false;
});
return nonEmptyUAs;
}
stringifyUnits() {
const milliseconds = FormattedDuration._pluralizeIfNeeded(this.milliseconds, 'millisecond');
const seconds = FormattedDuration._pluralizeIfNeeded(this.seconds, 'second');
const minutes = FormattedDuration._pluralizeIfNeeded(this.minutes, 'minute');
const hours = FormattedDuration._pluralizeIfNeeded(this.hours, 'hour');
return {
milliseconds,
seconds,
minutes,
hours
};
}
}
_defineProperty(FormattedDuration, "_pluralizeIfNeeded", (amount, unit) => {
if (amount === 1) {
return unit;
}
return `${unit}s`;
});
_defineProperty(FormattedDuration, "_isNumber", duration => typeof duration === 'number');
_defineProperty(FormattedDuration, "_roundNumber", (toRound, precision = 2) => {
const locale = 'en-US';
const formattingOptions = {
maximumFractionDigits: precision
};
const rounded = Number(toRound.toLocaleString(locale, formattingOptions));
return rounded;
});
var _default = FormattedDuration;
exports.default = _default;