/*
 * @(#) Date.js
 *
 * Date Utilities class
 * Copyright (c) 2008, 2009, 2010 Peter Wall
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

var net;
if (!net)
    net = {};
else if (typeof net != 'object')
    throw new Error('net prefix exists but is not an object');
if (!net.pwall)
    net.pwall = {};
else if (typeof net.pwall != 'object')
    throw new Error('net.pwall prefix exists but is not an object');

/**
 * This package consists of functions and data for date processing.
 *
 * @author Peter Wall
 */
net.pwall.Date = {};

net.pwall.Date.monthLengths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

net.pwall.Date.monthNamesEnglish = [ 'January', 'February', 'March', 'April', 'May', 'June',
        'July', 'August', 'September', 'October', 'November', 'December' ];

net.pwall.Date.monthNamesFrench = [ 'janvier', 'f\u00E9vrier', 'mars', 'avril', 'mai', 'juin',
        'juillet', 'ao\u00FBt', 'septembre', 'octobre', 'novembre', 'd\u00E9cembre' ];

net.pwall.Date.monthNamesSpanish = [ 'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
        'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre' ];

net.pwall.Date.monthNamesGerman = [ 'Januar', 'Februar', 'M\u00E4rz', 'April', 'Mai', 'Juni',
        'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ];

net.pwall.Date.monthNamesRussian = [ '\u044F\u043D\u0432\u0430\u0440\u044C',
        '\u0444\u0435\u0432\u0440\u0430\u043B\u044C', '\u043C\u0430\u0440\u0442',
        '\u0430\u043F\u0440\u0435\u043B\u044C', '\u043C\u0430\u0439',
        '\u0438\u044E\u043D\u044C', '\u0438\u044E\u043B\u044C',
        '\u0430\u0432\u0433\u0443\u0441\u0442',
        '\u0441\u0435\u043D\u0442\u044F\u0431\u0440\u044C',
        '\u043E\u043A\u0442\u044F\u0431\u0440\u044C', '\u043D\u043E\u044F\u0431\u0440\u044C',
        '\u0434\u0435\u043A\u0430\u0431\u0440\u044C' ];

net.pwall.Date.monthNamesJapanese = [ '\u4E00\u6708', '\u4E8C\u6708', '\u4E09\u6708',
        '\u56DB\u6708', '\u4E94\u6708', '\u516D\u6708', '\u4E03\u6708', '\u516B\u6708',
        '\u4E5D\u6708', '\u5341\u6708', '\u5341\u4E00\u6708', '\u5341\u4E8C\u6708' ];

net.pwall.Date.monthNamesChinese = [ '1\u6708', '2\u6708', '3\u6708', '4\u6708', '5\u6708',
        '6\u6708', '7\u6708', '8\u6708', '9\u6708', '10\u6708', '11\u6708', '12\u6708' ];

net.pwall.Date.monthNamesVolapuk = [ 'yanul', 'febul', 'm\u00E4zul', 'prilul', 'mayul', 'yunul',
        'yulul', 'gustul', 'setul', 'tobul', 'novul', 'dekul' ];

net.pwall.Date.dayNamesEnglish = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
        'Friday', 'Saturday' ];

net.pwall.Date.dayNamesFrench = [ 'dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi',
        'vendredi', 'samedi' ];

net.pwall.Date.dayNamesSpanish = [ 'domingo', 'lunes', 'martes', 'mi\u00E9rcoles', 'jueves',
        'viernes', 's\u00E1bado' ];

net.pwall.Date.dayNamesGerman = [ 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
        'Freitag', 'Samstag' ];

net.pwall.Date.dayNamesRussian = [
        '\u0432\u043E\u0441\u043A\u0440\u0435\u0441\u0435\u043D\u044C\u0435',
        '\u043F\u043E\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u0438\u043A',
        '\u0432\u0442\u043E\u0440\u043D\u0438\u043A', '\u0441\u0440\u0435\u0434\u0430',
        '\u0447\u0435\u0442\u0432\u0435\u0440\u0433',
        '\u043F\u044F\u0442\u043D\u0438\u0446\u0430',
        '\u0441\u0443\u0431\u0431\u043E\u0442\u0430' ];

net.pwall.Date.dayNamesJapanese = [ '\u65E5\u66DC\u65E5', '\u6708\u66DC\u65E5',
        '\u706B\u66DC\u65E5', '\u6C34\u66DC\u65E5', '\u6728\u66DC\u65E5', '\u91D1\u66DC\u65E5',
        '\u571F\u66DC\u65E5' ];

net.pwall.Date.dayNamesChinese = [ '\u661F\u671F\u5929', '\u661F\u671F\u4E00',
        '\u661F\u671F\u4E8C', '\u661F\u671F\u4E09', '\u661F\u671F\u56DB', '\u661F\u671F\u4E94',
        '\u661F\u671F\u516D' ];

net.pwall.Date.dayNamesVolapuk = [ 'sudel', 'mudel', 'tudel', 'vedel', 'd\u00F6del',
        'fridel', 'z\u00E4del' ];

net.pwall.Date.isLeapYear = function(y) {
    if ((y % 4) != 0)
        return false;
    if ((y % 100) != 0)
        return true;
    return (y % 400) == 0;
};

net.pwall.Date.monthLength = function(y, m) {
    return m == 1 && net.pwall.Date.isLeapYear(y) ? 29 : net.pwall.Date.monthLengths[m];
};

net.pwall.Date.addMonths = function(date, n) {
    var month = (date.getFullYear() * 12 + date.getMonth()) + n;
    var year = month / 12;
    month %= 12;
    var day = Math.min(date.getDate(), net.pwall.Date.monthLength(year, month));
    date.setFullYear(year, month, day);
};

net.pwall.Date.addDays = function(date, n) {
    date.setTime(date.getTime() + n * 24 * 60 * 60 * 1000);
};

net.pwall.Date.toISO8601Date = function(d) {
    var s = [ d.getFullYear(), '-', net.pwall.Date.twoDigit(d.getMonth() + 1), '-',
            net.pwall.Date.twoDigit(d.getDate()) ];
    return s.join('');
};

net.pwall.Date.toISO8601DateTime = function(d) {
    var dd = net.pwall.Date.twoDigit;
    var s = [ d.getFullYear(), '-', dd(d.getMonth() + 1), '-', dd(d.getDate()), 'T',
            dd(d.getHours()), ':', dd(d.getMinutes()), ':', dd(d.getSeconds()) ];
    var tzo = d.getTimezoneOffset();
    if (tzo == 0)
        s.push('Z');
    else {
        if (tzo > 0)
            s.push('-');
        else {
            s.push('+');
            tzo = -tzo;
        }
        s.push(dd(tzo / 60), ':', dd(tzo % 60));
    }
    return s.join('');
};

net.pwall.Date.toISO8601DateTimeUTC = function(d) {
    var dd = net.pwall.Date.twoDigit;
    var s = [ d.getUTCFullYear(), '-', dd(d.getUTCMonth() + 1), '-', dd(d.getUTCDate()), 'T',
            dd(d.getUTCHours()), ':', dd(d.getUTCMinutes()), ':', dd(d.getUTCSeconds()), 'Z' ];
    return s.join('');
};

net.pwall.Date.twoDigit = function(num) {
    return String((Math.floor(Math.abs(num)) % 100) + 100).substring(1);
};
