Date.dayNames = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'];
Date.abbrDayNames = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'];
Date.monthNames = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
Date.abbrMonthNames = ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сент', 'Окт', 'Ноя', 'Дек'];
Date.firstDayOfWeek = 1;
Date.format = 'dd-mm-yyyy';
Date.fullYearStart = '20';

(function() {
function add(name, method) {
if( !Date.prototype[name] ) {
Date.prototype[name] = method;
}
};
add("isLeapYear", function() {
var y = this.getFullYear();
return (y%4==0 && y%100!=0) || y%400==0;
});
add("isWeekend", function() {
return this.getDay()==0 || this.getDay()==6;
});
add("isWeekDay", function() {
return !this.isWeekend();
});

add("getDaysInMonth", function() {
return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
});
add("getDayName", function(abbreviated) {
return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
});
add("getMonthName", function(abbreviated) {
return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
});
add("getDayOfYear", function() {
var tmpdtm = new Date("1/1/" + this.getFullYear());
return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
});
add("getWeekOfYear", function() {
return Math.ceil(this.getDayOfYear() / 7);
});
add("setDayOfYear", function(day) {
this.setMonth(0);
this.setDate(day);
return this;
});
add("addYears", function(num) {
this.setFullYear(this.getFullYear() + num);
return this;
});
add("addMonths", function(num) {
var tmpdtm = this.getDate();

this.setMonth(this.getMonth() + num);

if (tmpdtm > this.getDate())
this.addDays(-this.getDate());

return this;
});
add("addDays", function(num) {
//this.setDate(this.getDate() + num);
this.setTime(this.getTime() + (num*86400000) );
return this;
});
add("addHours", function(num) {
this.setHours(this.getHours() + num);
return this;
});
add("addMinutes", function(num) {
this.setMinutes(this.getMinutes() + num);
return this;
});
add("addSeconds", function(num) {
this.setSeconds(this.getSeconds() + num);
return this;
});
add("zeroTime", function() {
this.setMilliseconds(0);
this.setSeconds(0);
this.setMinutes(0);
this.setHours(0);
return this;
});
add("asString", function(format) {
var r = format || Date.format;
if (r.split('mm').length>1) { // ugly workaround to make sure we don't replace the m's in e.g. noveMber
r = r.split('mmmm').join(this.getMonthName(false))
.split('mmm').join(this.getMonthName(true))
.split('mm').join(_zeroPad(this.getMonth()+1))
} else {
r = r.split('m').join(this.getMonth()+1);
}
r = r.split('yyyy').join(this.getFullYear())
.split('yy').join((this.getFullYear() + '').substring(2))
.split('dd').join(_zeroPad(this.getDate()))
.split('d').join(this.getDate());
return r;
});

Date.fromString = function(s)
{
var f = Date.format;

var d = new Date('01/01/1970');

if (s == '') return d;

s = s.toLowerCase();
var matcher = '';
var order = [];
var r = /(dd?d?|mm?m?|yy?yy?)+([^(m|d|y)])?/g;
var results;
while ((results = r.exec(f)) != null)
{
switch (results[1]) {
case 'd':
case 'dd':
case 'm':
case 'mm':
case 'yy':
case 'yyyy':
matcher += '(\\d+\\d?\\d?\\d?)+';
order.push(results[1].substr(0, 1));
break;
case 'mmm':
matcher += '([a-z]{3})';
order.push('M');
break;
}
if (results[2]) {
matcher += results[2];
}

}
var dm = new RegExp(matcher);
var result = s.match(dm);
for (var i=0; i<order.length; i++) {
var res = result[i+1];
switch(order[i]) {
case 'd':
d.setDate(res);
break;
case 'm':
d.setMonth(Number(res)-1);
break;
case 'M':
for (var j=0; j<Date.abbrMonthNames.length; j++) {
if (Date.abbrMonthNames[j].toLowerCase() == res) break;
}
d.setMonth(j);
break;
case 'y':
d.setYear(res);
break;
}
}

return d;
};

var _zeroPad = function(num) {
var s = '0'+num;
return s.substring(s.length-2)
};

})();