Набор классов для преобразования всяких циферок во что-то вроде:
Цитата:
|
> 56 миллиардов 402 миллиона 250 тысяч
> 500 рублей 51 копейка
> много денег
> 1 год 2 месяца 5 дней 20 часов 21 минута 44 секунды
> вчера
|
и т. д.
В ОО вид переделывал второпях, так что возможно, где то криво.
Сперва класс для наследования от него, сам по себе он бесполезен:
function AbstractInterval() {
throw new TypeError();
}
AbstractInterval.prototype = {
initialize: function(start, end) {
this.interval = arguments.length > 1 ? Math.abs(end - start) : +start;
if (!(this instanceof AbstractInterval) || isNaN(this.interval)) {
throw new TypeError();
}
},
formatPart: function(num, index) {
return num + ' ' + this.verbalStages[index][AbstractInterval.pluralIndex(num)];
},
toVerbal: function(partsCount) {
var interval = this.interval, stages = this.stages, verbalStages = this.verbalStages;
if (isNaN(partsCount)) {
partsCount = stages.length;
}
var parts = [], i = stages.length;
while (i) {
if (interval >= stages[--i]) {
var num = Math[!--partsCount || !i ? 'round' : 'floor'](interval / stages[i]);
parts.push(this.formatPart(num, i));
if (!partsCount || !(interval -= stages[i] * num)) {
break;
}
}
}
return parts;
},
toVerbalString: function(partsCount, partsDelim) {
return this.toVerbal(partsCount).join(partsDelim == null ? ' ' : partsDelim);
}
};
AbstractInterval.pluralIndex = function(num) {
var mod10 = num % 10, mod100 = num % 100;
return mod100 >= 5 && mod100 <= 20 ? 2 : mod10 == 1 ? 0 : mod10 >= 2 && mod10 <= 4 ? 1 : 2;
};
// для старых браузеров
if (!('create' in Object)) {
Object.create = function(obj) {
function F() {}
F.prototype = obj;
return new F();
};
}
Теперь создаем всякие полезные классы. Для просто чисел:
function Diff() {
this.initialize.apply(this, arguments);
}
// наследуем от AbstractInterval
Diff.prototype = Object.create(AbstractInterval.prototype);
Diff.prototype.stages = [1, 10, 100, 1000, 1e6, 1e9];
Diff.prototype.verbalStages = [
['единица', 'единицы', 'единиц'],
['десяток', 'десятка', 'десятков'],
['сотня', 'сотни', 'сотен'],
['тысяча', 'тысячи', 'тысяч'],
['миллион', 'миллиона', 'миллионов'],
['миллиард', 'миллиарда', 'миллиардов']
];
var diff = new Diff(56402250000);
console.log(diff.toVerbalString());// 56 миллиардов 402 миллиона 250 тысяч
Для дат:
function DateDiff() {
this.initialize.apply(this, arguments);
}
DateDiff.prototype = Object.create(AbstractInterval.prototype);
DateDiff.prototype.stages = [1, 1000, 60000, 36e5, 864e5, 6048e5, 2592e6, 31536e6];
DateDiff.prototype.verbalStages = [
['миллисекунда', 'миллисекунды', 'миллисекунд'],
['секунда', 'секунды', 'секунд'],
['минута', 'минуты', 'минут'],
['час', 'часа', 'часов'],
['день', 'дня', 'дней'],
['неделя', 'недели', 'недель'],
['месяц', 'месяца', 'месяцев'],
['год', 'года', 'лет']
];
// посмотрим сколько осталось до конца света :)
var dd = new DateDiff(new Date(), new Date('2012/12/21'));
console.log('Мы все умрем через ' + dd.toVerbalString());// Мы все умрем через 1 год 1 месяц 4 недели 1 день 4 часа 22 минуты 26 секунд 450 миллисекунд
Можно указать сколько максимум частей выводить:
var dd = new DateDiff(new Date(), new Date('2012/12/21'));
console.log(dd.toVerbalString(2));// 1 год 2 месяца
1 месяц превратился в 2, потому что скрипт не просто отрезает лишние части, а смотрит, что в них, и правильно округляет.
Можно указать свой разделитель частей (через запятую):
var dd = new DateDiff(new Date(), new Date('2012/12/21'));
console.log(dd.toVerbalString(5, ', '));// 1 год, 1 месяц, 4 недели, 1 день, 4 часа
Можно изменять обработку частей:
DateDiff.prototype.formatPart = function(num, index) {
if (num == 2) {
return 'пару ' + this.verbalStages[index][2];
}
return num + ' ' + this.verbalStages[index][AbstractInterval.pluralIndex(num)];
};
var dd = new DateDiff(2000);
console.log(dd.toVerbalString(1));// пару секунд