2018-05-30 08:03:32 +00:00
|
|
|
import moment from 'moment';
|
|
|
|
|
|
|
|
const allUnits = [
|
|
|
|
{ name: 'years', suffix: 'year', inMoment: true, pluralizable: true },
|
|
|
|
{ name: 'months', suffix: 'month', inMoment: true, pluralizable: true },
|
|
|
|
{ name: 'days', suffix: 'day', inMoment: true, pluralizable: true },
|
2018-09-25 03:01:42 +00:00
|
|
|
{ name: 'hours', suffix: 'h', longSuffix: 'hour', inMoment: true, pluralizable: false },
|
|
|
|
{ name: 'minutes', suffix: 'm', longSuffix: 'minute', inMoment: true, pluralizable: false },
|
|
|
|
{ name: 'seconds', suffix: 's', longSuffix: 'second', inMoment: true, pluralizable: false },
|
2018-05-30 08:03:32 +00:00
|
|
|
{ name: 'milliseconds', suffix: 'ms', inMoment: true, pluralizable: false },
|
|
|
|
{ name: 'microseconds', suffix: 'µs', inMoment: false, pluralizable: false },
|
|
|
|
{ name: 'nanoseconds', suffix: 'ns', inMoment: false, pluralizable: false },
|
|
|
|
];
|
|
|
|
|
2018-09-25 03:01:42 +00:00
|
|
|
const pluralizeUnits = (amount, unit, longForm) => {
|
|
|
|
let suffix;
|
|
|
|
if (longForm && unit.longSuffix) {
|
|
|
|
suffix = amount === 1 ? unit.longSuffix : unit.longSuffix.pluralize();
|
|
|
|
} else {
|
|
|
|
suffix = amount === 1 || !unit.pluralizable ? unit.suffix : unit.suffix.pluralize();
|
|
|
|
}
|
|
|
|
const addSpace = unit.pluralizable || (longForm && unit.longSuffix);
|
|
|
|
return `${amount}${addSpace ? ' ' : ''}${suffix}`;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default function formatDuration(duration = 0, units = 'ns', longForm = false) {
|
2018-05-30 08:03:32 +00:00
|
|
|
const durationParts = {};
|
|
|
|
|
2018-05-30 21:30:45 +00:00
|
|
|
// Moment only handles up to millisecond precision.
|
|
|
|
// Microseconds and nanoseconds need to be handled first,
|
|
|
|
// then Moment can take over for all larger units.
|
2018-05-30 08:03:32 +00:00
|
|
|
if (units === 'ns') {
|
|
|
|
durationParts.nanoseconds = duration % 1000;
|
|
|
|
durationParts.microseconds = Math.floor((duration % 1000000) / 1000);
|
|
|
|
duration = Math.floor(duration / 1000000);
|
|
|
|
} else if (units === 'mms') {
|
|
|
|
durationParts.microseconds = duration % 1000;
|
|
|
|
duration = Math.floor(duration / 1000);
|
|
|
|
}
|
|
|
|
|
2018-05-30 21:30:45 +00:00
|
|
|
let momentUnits = units;
|
|
|
|
if (units === 'ns' || units === 'mms') {
|
|
|
|
momentUnits = 'ms';
|
|
|
|
}
|
|
|
|
const momentDuration = moment.duration(duration, momentUnits);
|
2018-05-30 08:03:32 +00:00
|
|
|
|
2018-05-30 21:30:45 +00:00
|
|
|
// Get the count of each time unit that Moment handles
|
2018-05-30 08:03:32 +00:00
|
|
|
allUnits
|
|
|
|
.filterBy('inMoment')
|
|
|
|
.mapBy('name')
|
|
|
|
.forEach(unit => {
|
|
|
|
durationParts[unit] = momentDuration[unit]();
|
|
|
|
});
|
|
|
|
|
2018-05-30 21:30:45 +00:00
|
|
|
// Format each time time bucket as a string
|
|
|
|
// e.g., { years: 5, seconds: 30 } -> [ '5 years', '30s' ]
|
2018-05-30 08:03:32 +00:00
|
|
|
const displayParts = allUnits.reduce((parts, unitType) => {
|
|
|
|
if (durationParts[unitType.name]) {
|
|
|
|
const count = durationParts[unitType.name];
|
2018-09-25 03:01:42 +00:00
|
|
|
parts.push(pluralizeUnits(count, unitType, longForm));
|
2018-05-30 08:03:32 +00:00
|
|
|
}
|
|
|
|
return parts;
|
|
|
|
}, []);
|
|
|
|
|
2018-05-30 21:30:45 +00:00
|
|
|
if (displayParts.length) {
|
|
|
|
return displayParts.join(' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
// When the duration is 0, show 0 in terms of `units`
|
2018-09-25 03:01:42 +00:00
|
|
|
return pluralizeUnits(0, allUnits.findBy('suffix', units), longForm);
|
2018-05-30 08:03:32 +00:00
|
|
|
}
|