$.extend({
    defined: function ( arg ) {
        return arg ? true : false;
    },

    stringReplace: function ( arrSearch, arrReplace, subject ) {
        if (!$.isArray(arrSearch))  {arrSearch = [arrSearch];}
        if (!$.isArray(arrReplace)) {arrReplace = [arrReplace];}

        $.each(arrSearch, function (i, val) {
            if (!$.defined(arrReplace[i])) {arrReplace[i] = arrReplace[0];}
            subject = subject.toString().replace(new RegExp(arrSearch[i], 'g').escape(), arrReplace[i]);
        });
        return subject;
    },

    parseFloat: function ( val ) {
        if (new RegExp('^([-|+]*)?([\\d]*)$','').test(val)) {
            return val;}

        validate = new RegExp('^([-|+]*)([0-9.,\' ]*)','g').exec(val);
        val = validate[2];

        group_sign = new RegExp('[.,\' ]', 'g').exec(val);

        validate = new RegExp('^([-|+]*)([\\d' + group_sign + ',.]*)','g').exec(val);
        val = validate[2];

        switch (group_sign) {
            case '.':
                dec_sign = new RegExp('[,]', 'g').exec(val);
                if (!$.defined(dec_sign)) {dec_sign = group_sign; delete group_sign;}
                break;
            case ',':
                dec_sign = new RegExp('[.]', 'g').exec(val);
                if (!$.defined(dec_sign)) {dec_sign = group_sign; delete group_sign;}
                break;
            default: dec_sign = '.,';

        }

        result = new RegExp('^([-|+]*)([0-9' + group_sign + ']*)([' + dec_sign + ']+([0-9]*)){1}','g').exec(val);
        return parseFloat(result[1] + $.stringReplace(['.',',','\'',' '], '', result[2]) + '.' + result[4]);
    },

    numberFormat: function ( number, number_count, decimals, dec_point, thousands_sep ) {
        if (!$.defined(number))        { number=0; }
        if (!$.defined(number_count))  { number_count=''; }
        if (!$.defined(decimals))      { decimals=0; }
        if (!$.defined(dec_point))     { dec_point='.'; }
        if (!$.defined(thousands_sep)) { thousands_sep=' '; }

        number = Math.round(number * Math.pow(10, decimals));

        if (number_count) {
            max_number = Math.pow(10, number_count);
            if (number >= max_number) { number = (max_number - 1); }
        }

        number = number.toString().split('');

        while(number.length <= decimals) { number.unshift(0); }

        var number_length = number.length - decimals;
        if (decimals > 0) { number.splice(number_length, 0, dec_point); }

        while(number_length > 3) {
            number_length-=3;
            number.splice(number_length, 0, thousands_sep);
        }

        return number.join('');
    },

    sprintf: function ( string ) {
        if (arguments < 2) { return false; }

        var sprintf = [];
        var result = '';
        var arguments_read = 1;
        var string = string.toString();

        while (string) {
            if (result = new RegExp('^[^%]', '').exec(string)) { sprintf.push(result[0]); }
            else if (result = new RegExp('^[%]{2}', '').exec(string)) { sprintf.push('%'); }
            else if (result = /^[%](?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(string)) { //'
                if (!$.defined(result[1])) {result[1] = arguments_read++;}
                argument = arguments[result[1]];
                if (new RegExp('[^s]', '').test(result[7]) && (typeof(argument) != 'number')) { sprintf.push(0); }
                else {
                    switch (result[7]) {
                        case 'b':
                            argument = argument.toString(2);
                            break;
                        case 'c':
                            argument = String.fromCharCode(argument);
                            break;
                        case 'd':
                            argument = parseInt(argument);
                            break;
                        case 'e':
                            if (!$.defined(result[6])) {argument =  argument.toExponential();}
                            else {argument.toExponential(result[6]);}
                            break;
                        case 'f':
                            if (!$.defined(result[6])) {parseFloat(argument);}
                            else {parseFloat(argument).toFixed(result[6]);}
                            break;
                        case 'o':
                            argument = argument.toString(8);
                            break;
                        case 's':
                            if (!argument.toString() || !$.defined(result[6])) {argument = argument.toString();}
                            else {argument.toString().substring(0, result[6]);}
                            break;
                        case 'u':
                            argument = Math.abs(argument);
                            break;
                        case 'x':
                            argument = argument.toString(16);
                            break;
                        case 'X':
                            argument = argument.toString(16).toUpperCase();
                            break;
                    }

                    if (new RegExp('[def]','').test(result[7]) && result[2] && argument > 0) {argument = '+' + argument;}

                    if (!$.defined(result[3])) {char = ' ';}
                    else {char = result[3].charAt(0);}

                    var fill = '';
                    if ($.defined(result[5])) {
                        count = result[5] - argument.toString().length;
                        for (var i = 0; i < count; i++) {
                            fill += char;
                        }
                    }

                    if ($.defined(result[4])) {sprintf.push(argument + fill);} else {sprintf.push(fill + argument);}
                }
            } else {                return false;
            }
            string = string.substring(result[0].length);
        }
        return sprintf.join('');
    },

    dateFormat: function ( format, date ) {
        if (date == null)  {return null;}
        if (!$.defined(date))  {var date = new Date();}

        var char = '';
        var char_read = 0;
        var string = '';
        var special = false;

        format = format.toString().split('');
        for (read in format) {
            char = format[read];

            if (!special && char == "\\") { special = true; }
            else if (special) {
                special = false;
                string += char;}
            else {
                switch(char) {
                    case "a":
                        if (date.getHours() < 12) {string += "am";}
                        else {string += "pm";}
                        break;
                    case "A":
                        if (date.getHours() < 12) {string += "AM";}
                        else {string += "PM";}
                        break;
                    case "d":
                        string += $.sprintf('%02d', date.getDate());
                        break;
                    case "D":
                        string += Date.settings.dayNames[date.getDay()].substring(0, 3);
                        break;
                    case "j":
                        string += date.getDate();
                        break;
                    case "l":
                        string += days[date.getDay()];
                        break;
                    case "S":
                        switch (date.getDate()) {
                            case 1:
                            case 21:
                            case 31:
                                prefix = "st";
                                break;
                            case 2:
                            case 22:
                                prefix = "nd";
                                break;
                            case 3:
                            case 23:
                                prefix = "rd";
                                break;
                            default:
                                prefix = "th";
                                break;
                        }
                        string += prefix
                        break;
                    case "w":
                        string += date.getDay();
                        break;
                    case "z":
                        string += date.getDayOfYear();
                        break;
                    case "W":
                        string += date.getWeekOfYear();
                        break;
                    case "F":
                        string += Date.settings.monthNames[date.getMonth()];
                        break;
                    case "m":
                        string += $.sprintf('%02d', date.getMonth() + 1);
                        break;
                    case "M":
                        string += Date.settings.monthNames[date.getMonth()].substring(0, 3);
                        break;
                    case "n":
                        string += (date.getMonth() + 1);
                        break;
                    case "t":
                        string += date.getDaysInMonth()[date.getMonth()];
                        break;
                    case "L":
                        string += date.isLeapYear();
                        break;
                    case "Y":
                        string += date.getFullYear();
                        break;
                    case "y":
                        string += date.getFullYear().toString.substring(2, 4);
                        break;
                    case "g":
                        if (date.getHours()%12) { string += date.getHours()%12; }
                        else { string += 12; }
                        break;
                    case "G":
                        string += date.getHours();
                        break;
                    case "h":
                        if (date.getHours()%12) { string += $.sprintf('%02d', date.getHours()%12); }
                        else { string += 12; }
                        break;
                    case "H":
                        string += $.sprintf('%02d', date.getHours());
                        break;
                    case "i":
                        string += $.sprintf('%02d', date.getMinutes());
                        break;
                    case "s":
                        string += $.sprintf('%02d', date.getSeconds());
                        break;
                    case "O":
                        //string += date.getGMTOffset();
                        //break;
                    case "T":
                        //string += date.getTimezone();
                        //break;
                    case "Z":
                        //string += (date.getTimezoneOffset() * -60);
                        //break;
                    default:
                        string += char;
                }
            }
        }
        return string;
    },

    parseDate: function ( string, days_prefered ) {
        var d,m,y,h,i,s;
        var char = '';
        var char_read = 0;
        var date = new Date();
        var special = false;

        var generalFormat = ['Y-m-d','M d,Y','M d,Y','Y-M-d','d-M-Y','M d'];
        var monthFormat = ['m.d', 'm.d.y', 'm.d.Y', 'm/d', 'm/d/y', 'm-d-Y', 'm-d', 'm-d-y', 'm-d-Y'];
        var dayFormat = ['d.m', 'd.m.y', 'd.m.Y', 'd/m', 'd/m/y', 'd/m/Y', 'd-m', 'd-m-y', 'd-m-Y'];

        if ($.defined(days_prefered)) {
            var checklist = [generalFormat, dayFormat, monthFormat];}
        else {
            var checklist = [generalFormat, monthFormat, dayFormat];}

        for (format_list in checklist) {
            for (format in checklist[format_list]) {
                var expression = '';
                var expression_group = 0;
                var eval_code = '';

                format = checklist[format_list][format].toString().split('');
                for (read in format) {
                    char = format[read];

                    if (!special && char == "\\") {
                        special = true; }
                    else if (special) {
                        special = false;
                        expression += char;}
                    else {
                        expression_group++;
                        switch(char) {
                            case "a":
                                expression += '(AM|PM)';
                                eval_code += 'if ( result[' + expression_group + '] == \'am\' ) {'
                                           + '    if ( h == 12 ) { h = 0; }}'
                                           + 'else {'
                                           + '    if ( h < 12 ) { h += 12; }};';
                                break;
                            case "A":
                                expression += '(AM|PM)';
                                eval_code += 'if ( result[' + expression_group + '] == \'AM\' ) {'
                                           + '    if ( h == 12 ) { h = 0; }}'
                                           + 'else {'
                                           + '    if ( h < 12 ) { h += 12; }};';
                                break;
                            case "j":
                            case "d":
                                expression += '(\\d{1,2})';
                                eval_code += 'd = result[' + expression_group + '];';
                                break;
                            case "D":
                                expression_temp = [];
                                $.each(Date.settings.dayNames, function(i, val) {
                                    expression_temp[i] = val.substring(0, 3);
                                })
                                expression += '(' + expression_temp.join('|') + ')';
                                break;
                            case "l":
                                expression += '(' + Date.settings.dayNames.join('|') + ')';
                                break;
                            case "S":
                                expression += '(st|nd|rd|th)';
                                break;
                            case "w":
                                expression += '(\\d)';
                                break;
                            case "z":
                                expression += '(\\d{1,3})';
                                break;
                            case "W":
                                expression += '(\\d{1,2})';
                                break;
                            case "F":
                                expression += '(' + Date.monthNames.join('|') + ')';
                                eval_code = 'm = $.inArray(result[' + expression_group + '], Date.settings.monthNames);';
                                break;
                            case "n":
                            case "m":
                                expression += '(\\d{1,2})';
                                eval_code += 'm = result[' + expression_group + '];';
                                break;
                            case "M":
                                expression_temp = [];
                                $.each(Date.settings.monthNames, function(i, val) {
                                    expression_temp[i] = val.substring(0, 3);
                                })
                                expression += '(' + expression_temp.join('|') + ')';
                                eval_code += 'm = $.inArray(result[' + expression_group + '], [\'' + expression_temp.join('\',\'') + '\']); m++;';
                                break;
                            case "t":
                                expression += '(\\d{2})';
                                break;
                            case "L":
                                expression += '(0|1)';
                                break;
                            case "Y":
                                expression += '(\\d{4})';
                                eval_code += 'y = result[' + expression_group + '];';
                                break;
                            case "y":
                                expression += '(\\d{2})';
                                eval_code += 'y = result[' + expression_group + '];'
                                           + 'if (y > Date.settings.nextCentury) { '
                                           + '    y = (date.getFullYear() - 100).toString().substring(0,2) + y;} '
                                           + 'else { '
                                           + '    y = date.getFullYear().toString().substring(0,2) + y;} ';
                                break;

                            case "g":
                            case "G":
                            case "h":
                            case "H":
                                expression += '(\\d{2})';
                                eval_code = 'h = result[' + expression_group + '];';
                                break;
                            case "i":
                                expression += '(\\d{2})';
                                eval_code = 'i = result[' + expression_group + '];';
                                bbreak;
                            case "s":
                                expression += '(\\d{2})';
                                eval_code = 's = result[' + expression_group + '];';
                                break;
                            case "O":
                                //string += date.getGMTOffset();
                                //break;
                            case "T":
                                //string += date.getTimezone();
                                //break;
                            case "Z":
                                //string += (date.getTimezoneOffset() * -60);
                                //break;
                            default:
                                expression += '([' + char + '])';
                        }
                    }
                }

                if (result = new RegExp('^' + expression + '$','').exec(string)) {
                    eval(eval_code);

                    if(!$.defined(y) && $.defined(d) && $.defined(m)) {y = date.getFullYear();}
                    else if(!$.defined(y)) {y = 0;}
                    if(!$.defined(d)) {d = 1;}
                    if(!$.defined(m)) {m = 1;}
                    if(!$.defined(h)) {h = 0;}
                    if(!$.defined(i)) {i = 0;}
                    if(!$.defined(s)) {s = 0;}

                    return new Date(y, (m-1), d, h, i, s);
                }
            }
        }
        return null;
    }
});

RegExp.prototype.escape = function() {
    var pattern = new RegExp('([\/]+)(.*)([\/]+)(.*)', 'g');
    var result = pattern.exec(this.toString());

    return new RegExp(result[2].replace(/([.*+?^=<>!:${}()|[\]\/\\])/g, '\\$1'), result[4]);
}

Date.settings = {
    'mode':        3,
    'dayNames':    ['Sunday','Monday','Thursday','Wednesday','Thursday','Friday','Saturday'],
    'monthNames':  ['January','February','March','April','May','June','July','August','September','October','November','December'],
    'nextCentury': 50
}

Date.prototype.isLeapYear = function() {
    var year = this.getFullYear();
    return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
}

Date.prototype.getDayOfYear = function() {
    var num = 0;
    for (var i = 0; i < this.getMonth(); ++i) {
        num += [31,this.isLeapYear()?29:28,31,30,31,30,31,31,30,31,30,31][i];
    }
    return num + this.getDate() - 1;
}

Date.prototype.getWeekOfYear = function() {
    var week = 0;
    var first_day = 0;

    var now = this.getDayOfYear();
    var start = new Date(this.getFullYear(), 0, 1).getDay();

    switch(Date.settings.mode) {
        case 0:
            first_weekday = 0;
            first_day = (start == first_weekday) ? start : 7 - start + first_weekday;
            break;
        case 1:
            first_weekday = 1;
            first_day = (7 - (start - first_weekday) >= 3) ? start - 7 : (7 + first_weekday) - start;
            break;
        case 2:
            week = 52;
            first_weekday = 0;
            first_day = (start == first_weekday) ? start : 7 - start + first_weekday;
            break;
        case 3:
            week = 52;
            first_weekday = 1;
            first_day = (7 - (start - first_weekday) >= 3) ? start - 7 : (7 + first_weekday) - start;
            break;

        case 4:
            first_weekday = 0;
            first_day = (7 - (start - first_weekday) >= 3) ? start - 7 : (7 + first_weekday) - start;
            break;
        case 5:
            first_weekday = 1;
            first_day = (start == first_weekday) ? start : 7 - start + first_weekday;
            break;
        case 6:
            week = 52;
            first_weekday = 0;
            first_day = (7 - (start - first_weekday) >= 3) ? start - 7 : (7 + first_weekday) - start;
            break;
        case 7:
            week = 52;
            first_weekday = 1;
            first_day = (start == first_weekday) ? start : 7 - start + first_weekday;
            break;
    }

    var week_act = ((now - first_day) / 7);
    if (week_act >= 0) {return Math.round(week_act) + 1;}
    else {return week;}
}