
/* Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/


Date.dayNames = ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'];
Date.abbrDayNames = ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'];
Date.monthNames = ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'];
Date.abbrMonthNames = ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'];
Date.firstDayOfWeek = 1;
Date.format = 'dd mmmm 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;
    };

    // utility method
    var _zeroPad = function(num) {
        var s = '0' + num;
        return s.substring(s.length - 2)
        //return ('0'+num).substring(-2); // doesn't work on IE :(
    };

})();