lib/public/javascripts/humanize_duration.js
// HumanizeDuration.js - http://git.io/j0HgmQ
(function() {
var UNITS = {
year: 31557600000,
month: 2629800000,
week: 604800000,
day: 86400000,
hour: 3600000,
minute: 60000,
second: 1000,
millisecond: 1
};
var languages = {
ca: {
year: function(c) { return "any" + ((c !== 1) ? "s" : ""); },
month: function(c) { return "mes" + ((c !== 1) ? "os" : ""); },
week: function(c) { return "setman" + ((c !== 1) ? "es" :"a"); },
day: function(c) { return "di" + ((c !== 1) ? "es" :"a"); },
hour: function(c) { return "hor" + ((c !== 1) ? "es" :"a"); },
minute: function(c) { return "minut" + ((c !== 1) ? "s" : ""); },
second: function(c) { return "segon" + ((c !== 1) ? "s" : ""); },
millisecond: function(c) { return "milisegon" + ((c !== 1) ? "s" : "" ); }
},
da: {
year: "år",
month: function(c) { return "måned" + ((c !== 1) ? "er" : ""); },
week: function(c) { return "uge" + ((c !== 1) ? "r" : ""); },
day: function(c) { return "dag" + ((c !== 1) ? "e" : ""); },
hour: function(c) { return "time" + ((c !== 1) ? "r" : ""); },
minute: function(c) { return "minut" + ((c !== 1) ? "ter" : ""); },
second: function(c) { return "sekund" + ((c !== 1) ? "er" : ""); },
millisecond: function(c) { return "millisekund" + ((c !== 1) ? "er" : ""); }
},
de: {
year: function(c) { return "jahr" + ((c !== 1) ? "e" : ""); },
month: function(c) { return "monat" + ((c !== 1) ? "e" : ""); },
week: function(c) { return "woche" + ((c !== 1) ? "n" : ""); },
day: function(c) { return "tag" + ((c !== 1) ? "e" : ""); },
hour: function(c) { return "stunde" + ((c !== 1) ? "n" : ""); },
minute: function(c) { return "minute" + ((c !== 1) ? "n" : ""); },
second: function(c) { return "sekunde" + ((c !== 1) ? "n" : ""); },
millisecond: function(c) { return "millisekunde" + ((c !== 1) ? "n" : ""); }
},
en: {
year: function(c) { return "year" + ((c !== 1) ? "s" : ""); },
month: function(c) { return "month" + ((c !== 1) ? "s" : ""); },
week: function(c) { return "week" + ((c !== 1) ? "s" : ""); },
day: function(c) { return "day" + ((c !== 1) ? "s" : ""); },
hour: function(c) { return "hour" + ((c !== 1) ? "s" : ""); },
minute: function(c) { return "minute" + ((c !== 1) ? "s" : ""); },
second: function(c) { return "second" + ((c !== 1) ? "s" : ""); },
millisecond: function(c) { return "millisecond" + ((c !== 1) ? "s" : ""); }
},
nl: {
year: "jaar",
month: function(c) { return (c === 1) ? "maand" : "maanden"; },
week: function(c) { return (c === 1) ? "week" : "weken"; },
day: function(c) { return (c === 1) ? "dag" : "dagen"; },
hour: "uur",
minute: function(c) { return (c === 1) ? "minuut" : "minuten"; },
second: function(c) { return (c === 1) ? "seconde" : "seconden"; },
millisecond: function(c) { return (c === 1) ? "milliseconde" : "milliseconden"; }
},
es: {
year: function(c) { return "año" + ((c !== 1) ? "s" : ""); },
month: function(c) { return "mes" + ((c !== 1) ? "es" : ""); },
week: function(c) { return "semana" + ((c !== 1) ? "s" : ""); },
day: function(c) { return "día" + ((c !== 1) ? "s" : ""); },
hour: function(c) { return "hora" + ((c !== 1) ? "s" : ""); },
minute: function(c) { return "minuto" + ((c !== 1) ? "s" : ""); },
second: function(c) { return "segundo" + ((c !== 1) ? "s" : ""); },
millisecond: function(c) { return "milisegundo" + ((c !== 1) ? "s" : "" ); }
},
fr: {
year: function(c) { return "an" + ((c !== 1) ? "s" : ""); },
month: "mois",
week: function(c) { return "semaine" + ((c !== 1) ? "s" : ""); },
day: function(c) { return "jour" + ((c !== 1) ? "s" : ""); },
hour: function(c) { return "heure" + ((c !== 1) ? "s" : ""); },
minute: function(c) { return "minute" + ((c !== 1) ? "s" : ""); },
second: function(c) { return "seconde" + ((c !== 1) ? "s" : ""); },
millisecond: function(c) { return "milliseconde" + ((c !== 1) ? "s" : ""); }
},
ja: {
year: "年",
month: "月",
week: "週",
day: "日",
hour: "時間",
minute: "分",
second: "秒",
millisecond: "ミリ秒"
},
ko: {
year: "년",
month: "개월",
week: "주일",
day: "일",
hour: "시간",
minute: "분",
second: "초",
millisecond: "밀리 초"
},
nob: {
year: "år",
month: function(c) { return "måned" + ((c !== 1) ? "er" : ""); },
week: function(c) { return "uke" + ((c !== 1) ? "r" : ""); },
day: function(c) { return "dag" + ((c !== 1) ? "er" : ""); },
hour: function(c) { return "time" + ((c !== 1) ? "r" : ""); },
minute: function(c) { return "minutt" + ((c !== 1) ? "er" : ""); },
second: function(c) { return "sekund" + ((c !== 1) ? "er" : ""); },
millisecond: function(c) { return "millisekund" + ((c !== 1) ? "er" : ""); }
},
pl: {
year: function(c) { return ["rok", "roku", "lata", "lat"][getPolishForm(c)]; },
month: function(c) { return ["miesiąc", "miesiąca", "miesiące", "miesięcy"][getPolishForm(c)]; },
week: function(c) { return ["tydzień", "tygodnia", "tygodnie", "tygodni"][getPolishForm(c)]; },
day: function(c) { return ["dzień", "dnia", "dni", "dni"][getPolishForm(c)]; },
hour: function(c) { return ["godzina", "godziny", "godziny", "godzin"][getPolishForm(c)]; },
minute: function(c) { return ["minuta", "minuty", "minuty", "minut"][getPolishForm(c)]; },
second: function(c) { return ["sekunda", "sekundy", "sekundy", "sekund"][getPolishForm(c)]; },
millisecond: function(c) { return ["milisekunda", "milisekundy", "milisekundy", "milisekund"][getPolishForm(c)]; }
},
pt: {
year: function(c) { return "ano" + ((c !== 1) ? "s" : ""); },
month: function(c) { return (c !== 1) ? "meses" : "mês"; },
week: function(c) { return "semana" + ((c !== 1) ? "s" : ""); },
day: function(c) { return "dia" + ((c !== 1) ? "s" : ""); },
hour: function(c) { return "hora" + ((c !== 1) ? "s" : ""); },
minute: function(c) { return "minuto" + ((c !== 1) ? "s" : ""); },
second: function(c) { return "segundo" + ((c !== 1) ? "s" : ""); },
millisecond: function(c) { return "milissegundo" + ((c !== 1) ? "s" : ""); }
},
ru: {
year: function(c) { return ["лет", "год", "года"][getRussianForm(c)]; },
month: function(c) { return ["месяцев", "месяц", "месяца"][getRussianForm(c)]; },
week: function(c) { return ["недель", "неделя", "недели"][getRussianForm(c)]; },
day: function(c) { return ["дней", "день", "дня"][getRussianForm(c)]; },
hour: function(c) { return ["часов", "час", "часа"][getRussianForm(c)]; },
minute: function(c) { return ["минут", "минута", "минуты"][getRussianForm(c)]; },
second: function(c) { return ["секунд", "секунда", "секунды"][getRussianForm(c)]; },
millisecond: function(c) { return ["миллисекунд", "миллисекунда", "миллисекунды"][getRussianForm(c)]; }
},
sv: {
year: "år",
month: function(c) { return "månad" + ((c !== 1) ? "er" : ""); },
week: function(c) { return "veck" + ((c !== 1) ? "or" : "a"); },
day: function(c) { return "dag" + ((c !== 1) ? "ar" : ""); },
hour: function(c) { return "timm" + ((c !== 1) ? "ar" : "e"); },
minute: function(c) { return "minut" + ((c !== 1) ? "er" : ""); },
second: function(c) { return "sekund" + ((c !== 1) ? "er" : ""); },
millisecond: function(c) { return "millisekund" + ((c !== 1) ? "er" : ""); }
},
tr: {
year: "yıl",
month: "ay",
week: "hafta",
day: "gün",
hour: "saat",
minute: "dakika",
second: "saniye",
millisecond: "milisaniye"
},
"zh-CN": {
year: "年",
month: "个月",
week: "周",
day: "天",
hour: "小时",
minute: "分钟",
second: "秒",
millisecond: "毫秒"
},
"zh-TW": {
year: "年",
month: "個月",
week: "周",
day: "天",
hour: "小時",
minute: "分鐘",
second: "秒",
millisecond: "毫秒"
},
};
// You can create a humanizer, which returns a function with defaults
// parameters.
function humanizer(passedOptions) {
var result = function humanizer(ms, passedOptions) {
var options = extend({}, result, passedOptions || {});
return doHumanization(ms, options);
};
extend(result, {
language: "en",
delimiter: ", ",
units: ["year", "month", "week", "day", "hour", "minute", "second"],
languages: {}
}, passedOptions);
return result;
}
// The main function is just a wrapper around a default humanizer.
var defaultHumanizer = humanizer({});
function humanizeDuration(ms, passedOptions) {
return defaultHumanizer(ms, passedOptions);
}
// doHumanization does the bulk of the work.
function doHumanization(ms, options) {
// Make sure we have a positive number.
// Has the nice sideffect of turning Number objects into primitives.
ms = Math.abs(ms);
if (ms === 0) {
return "0";
}
var dictionary = options.languages[options.language] || languages[options.language];
if (!dictionary) {
throw new Error("No language " + dictionary + ".");
}
var result = [];
// Start at the top and keep removing units, bit by bit.
var unitName, unitMS, unitCount, mightBeHalfUnit;
for (var i = 0, len = options.units.length; i < len; i ++) {
unitName = options.units[i];
if (unitName[unitName.length - 1] === "s") { // strip plurals
unitName = unitName.substring(0, unitName.length - 1);
}
unitMS = UNITS[unitName];
// If it's a half-unit interval, we're done.
if (result.length === 0) {
mightBeHalfUnit = (ms / unitMS) * 2;
if (mightBeHalfUnit === Math.floor(mightBeHalfUnit)) {
return render(mightBeHalfUnit / 2, unitName, dictionary);
}
}
// 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.
if (unitCount) {
result.push(render(unitCount, unitName, dictionary));
}
// Remove what we just figured out.
ms -= unitCount * unitMS;
}
return result.join(options.delimiter);
}
humanizeDuration.humanizer = humanizer;
if (typeof module !== "undefined") {
module.exports = humanizeDuration;
} else {
this.humanizeDuration = humanizeDuration;
}
function render(count, type, dictionary) {
var dictionaryValue = dictionary[type];
var word;
if (typeof dictionaryValue === "function") {
word = dictionaryValue(count);
} else {
word = dictionaryValue;
}
return count + " " + word;
}
function extend(destination) {
var source;
for (var i = 1; i < arguments.length; i ++) {
source = arguments[i];
for (var prop in source) {
destination[prop] = source[prop];
}
}
return destination;
}
// Internal helper function for Polish language.
function getPolishForm(c) {
if (c === 1) {
return 0;
} else if (Math.floor(c) !== c) {
return 1;
} else if (2 <= c % 10 && c % 10 <= 4 && !(10 < c % 100 && c % 100 < 20)) {
return 2;
} else {
return 3;
}
}
// Internal helper function for Russian language.
function getRussianForm(c) {
if (Math.floor(c) !== c) {
return 2;
} else if (c === 0 || (c >= 5 && c <= 20) || (c % 10 >= 5 && c % 10 <= 9) || (c % 10 === 0) ) {
return 0;
} else if (c === 1 || c % 10 === 1) {
return 1;
} else if (c > 1) {
return 2;
} else {
return 0;
}
}
})();