Skip to content

Instantly share code, notes, and snippets.

@DinoChiesa
Last active July 18, 2016 18:20
Show Gist options
  • Save DinoChiesa/8352d4b48c8925cee544f45068701e12 to your computer and use it in GitHub Desktop.
Save DinoChiesa/8352d4b48c8925cee544f45068701e12 to your computer and use it in GitHub Desktop.
// humanizeDuration.js
// ------------------------------------------------------------------
//
// derived from https://github.com/EvanHahn/HumanizeDuration.js
//
// created: Mon Jul 18 11:13:09 2016
// last saved: <2016-July-18 11:15:53>
;(function (){
var dictionary = {
y: function (c) { return 'year' + (c !== 1 ? 's' : ''); },
mo: function (c) { return 'month' + (c !== 1 ? 's' : ''); },
w: function (c) { return 'week' + (c !== 1 ? 's' : ''); },
d: function (c) { return 'day' + (c !== 1 ? 's' : ''); },
h: function (c) { return 'hour' + (c !== 1 ? 's' : ''); },
m: function (c) { return 'minute' + (c !== 1 ? 's' : ''); },
s: function (c) { return 'second' + (c !== 1 ? 's' : ''); },
ms: function (c) { return 'millisecond' + (c !== 1 ? 's' : ''); },
decimal: '.'
};
// You can create a humanizer, which returns a function with default
// parameters.
function humanizer (passedOptions) {
var result = function humanizer (ms, humanizerOptions) {
var options = extend({}, result, humanizerOptions || {});
return doHumanization(ms, options);
};
return extend(result, {
language: 'en',
delimiter: ', ',
spacer: ' ',
conjunction: '',
serialComma: true,
units: ['y', 'mo', 'w', 'd', 'h', 'm', 's'],
languages: {},
round: false,
unitMeasures: {
y: 31557600000,
mo: 2629800000,
w: 604800000,
d: 86400000,
h: 3600000,
m: 60000,
s: 1000,
ms: 1
}
}, passedOptions);
}
// doHumanization does the bulk of the work.
function doHumanization (ms, options) {
var i, len, piece;
// Make sure we have a positive number.
// Has the nice sideffect of turning Number objects into primitives.
ms = Math.abs(ms);
var pieces = [];
// Start at the top and keep removing units, bit by bit.
var unitName, unitMS, unitCount;
for (i = 0, len = options.units.length; i < len; i++) {
unitName = options.units[i];
unitMS = options.unitMeasures[unitName];
// What's the number of full units we can fit?
if (i + 1 === len) {
unitCount = ms / unitMS;
} else {
unitCount = Math.floor(ms / unitMS);
}
// Add the string.
pieces.push({
unitCount: unitCount,
unitName: unitName
});
// Remove what we just figured out.
ms -= unitCount * unitMS;
}
var firstOccupiedUnitIndex = 0;
for (i = 0; i < pieces.length; i++) {
if (pieces[i].unitCount) {
firstOccupiedUnitIndex = i;
break;
}
}
if (options.round) {
var ratioToLargerUnit, previousPiece;
for (i = pieces.length - 1; i >= 0; i--) {
piece = pieces[i];
piece.unitCount = Math.round(piece.unitCount);
if (i === 0) { break; }
previousPiece = pieces[i - 1];
ratioToLargerUnit = options.unitMeasures[previousPiece.unitName] / options.unitMeasures[piece.unitName];
if ((piece.unitCount % ratioToLargerUnit) === 0 || (options.largest && ((options.largest - 1) < (i - firstOccupiedUnitIndex)))) {
previousPiece.unitCount += piece.unitCount / ratioToLargerUnit;
piece.unitCount = 0;
}
}
}
var result = [];
for (i = 0, pieces.length; i < len; i++) {
piece = pieces[i];
if (piece.unitCount) {
result.push(render(piece.unitCount, piece.unitName, dictionary, options));
}
if (result.length === options.largest) { break; }
}
if (result.length) {
if (!options.conjunction || result.length === 1) {
return result.join(options.delimiter);
} else if (result.length === 2) {
return result.join(options.conjunction);
} else if (result.length > 2) {
return result.slice(0, -1).join(options.delimiter) + (options.serialComma ? ',' : '') + options.conjunction + result.slice(-1);
}
} else {
return render(0, options.units[options.units.length - 1], dictionary, options);
}
}
function render (count, type, dictionary, options) {
var decimal;
if (options.decimal === void 0) {
decimal = dictionary.decimal;
} else {
decimal = options.decimal;
}
var countStr = count.toString().replace('.', decimal);
var dictionaryValue = dictionary[type];
var word;
if (typeof dictionaryValue === 'function') {
word = dictionaryValue(count);
} else {
word = dictionaryValue;
}
return countStr + options.spacer + word;
}
function extend (destination) {
var source;
for (var i = 1; i < arguments.length; i++) {
source = arguments[i];
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
destination[prop] = source[prop];
}
}
}
return destination;
}
var durationHumanizer = humanizer;
if (typeof module !== 'undefined' && module.exports) {
module.exports = durationHumanizer;
}
else {
var rootScope = (function(){ return this; }).call(null);
rootScope.durationHumanizer = durationHumanizer;
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment