/*
    Purpose: To fully round out a Date objects capabilites
    Author: Jerry Middlemiss <jerry@richat.com>
    Created: 02/01/2004
    Dependancies:
        None  Just include this file with a src= tag and you are good to go.
    
    Comments:
        There is a bunch of reasons for finally making this.  There are so many date related things 
        that keep coming back to haunt me, so I finally decided to build the stuff right into the 
        date object and save everyone a lot of hassle.
        
        TODO
        I really need to make the functions below anonymous
    
    Warnings:
        - USE getFullYear, not getYear.  It has been depreciated, and browsers like mozilla return the WRONG value
        - most of my functions deal with my getDisplay month function NOT getMonth.  This is because 
          you cannot create the correct month for a new date using the built in getMonth function... LAME?
        - As much as I *hate* using .prototype to add stuff it is the only way to use it.  Some day I'll redo this
          so that it is Date.prototyp.fomFunc = Function () { blahblahblahbl }; but till then you need to be careful.  
          The functions defined here will be GLOBALLY VISIBLE.  You cannot use them independantly, but you will have 
          issues trying to name a function or var the same name as one of these functions.  Be warned.
*/


/*
    STYLE - the default used to create date objects.
*/
Date.prototype.STYLE = "/";
Date.prototype.getStyle = getStyle;
function getStyle()
{   return this.STYLE;    }

/*
    Simple date validation
    isDate() - date DOES NOT FAIL if you pass it a bad date.  It creates a date object that you can't use.  
               (cept to set again I guess)  This tells you directly if this object has been set correctly.
    isNumMonth() - is it a # between 1 and 12
    isNumDay() - is it a num between 1 and the # of days in that month?
    isNumYear() - is it a 4 digit year (yeah, not complete but this is for BUISSNESS use.  Sue me)
    isNumDate() - shortcut to check all 3 above at once.
*/
Date.prototype.isDate = isDate;
Date.prototype.isNumDay = isNumDay;
Date.prototype.isNumMonth = isNumMonth;
Date.prototype.isNumYear = isNumYear;
Date.prototype.isNumDate = isNumDate;
function isDate()
{   return ((this.getMonth() > -1) && (this.getDate() > -1) && (this.getYear() > -1)) ? true : false;    }
function isNumDay(theMonth,theDay,theYear)
{
    var tempDate = new Date((theMonth + "/1/" + theYear));
    return (parseInt(theDay) > 0 && parseInt(theDay) <= tempDate.getDaysInMonth()) ? true : false;
}
function isNumMonth(theMonth)
{   return ((theMonth.length == 1 || theMonth.length == 2) && parseInt(theMonth) > 0 && parseInt(theMonth) < 13) ? true : false;    }
function isNumYear(theYear)
{   return (theYear.length == 4 && parseInt(theYear) > 1000) ? true : false;    }
function isNumDate(theMonth,theDay,theYear)
{   return (this.isNumYear(theYear) && this.isNumMonth(theMonth) && this.isNumDay(theMonth,theDay,theYear)) ? true : false;    }


/*
    When you just want to show the simple MM/DD/YYYY (america based I know - redo it if you don't like it :P)
    showDate(theStyle) - returns the date in a string.
        theStyle - what to put between month, day, and year.  Default is "/".
*/
Date.prototype.showDate = showDate;
function showDate(theStyle)
{
    var style = (theStyle) ? theStyle : this.STYLE;
    return (this.getDisplayMonth() + style + this.getDate() + style + this.getFullYear());
}


/*
    Some constants that probably don't need to be here, but they are for convinence.
    Probably stems from my desire for absolutely NO magic numbers in my code, no matter 
    how unchanging.  As if they are going to give us 8 days a week or something...
    getMonthsInYear() - return the number of months in a year
    getDaysInWeek() - return the number of days in a week
    getDaysInYear() - return the number of days in a year
    getDaysInMonth() - complicated little ditty that returns the number of days in that current month
*/
Date.prototype.MONTHS_IN_YEAR = 12;
Date.prototype.DAYS_IN_WEEK = 7;
Date.prototype.DAYS_IN_YEAR = 365;
Date.prototype.getMonthsInYear = getMonthsInYear;
Date.prototype.getDaysInWeek = getDaysInWeek;
Date.prototype.getDaysInYear = getDaysInYear;
Date.prototype.getDaysInMonth = getDaysInMonth;
function getMonthsInYear()
{   return this.MONTHS_IN_YEAR;    }
function getDaysInWeek()
{   return this.DAYS_IN_WEEK;    }
function getDaysInYear()
{   return this.DAYS_IN_YEAR;    }
function getDaysInMonth()
{   return (this.getMonth() == 3 || this.getMonth() == 5 || this.getMonth() == 8 || this.getMonth() == 10) ? 30 : (this.getMonth() == 1 && (this.getFullYear() % 4) == 0 && !((this.getFullYear() % 100) == 0 && (this.getFullYear() % 400) != 0)) ? 29 : (this.getMonth() == 1) ? 28 : 31;    }


/*
    This has always struck me a lame.  Months and day of week are in an array that is 0 based and yet days are not?
    LAME.  All or none baby.
    getDisplayMonth() - returns the correct num for month (jan = 1, etc)
    getDisplayDay() - returns the correct num for day of week (sun = 1, etc)
    getMonthDate() - returns a 0 based day for month.  To simplify for loops and such.  And just to be anal about 
                    making all the number arrays in the date object BOTH 0 and 1 based arrays.
*/
Date.prototype.getDisplayMonth = getDisplayMonth;
Date.prototype.getDisplayDay = getDisplayDay;
Date.prototype.getMonthDate = getMonthDate;
function getDisplayMonth()
{   return (this.getMonth() > -1) ? (this.getMonth() + 1) : false;    }
function getDisplayDay()
{   return (this.getDay() > -1) ? (this.getDay() + 1) : false;    }
function getMonthDate()
{   return (this.getDate() > -1) ? (this.getDate() - 1) : false;    }


/*
    These functions relate to string values for dates and days
    TODO: some kind of internationalization scheme.  maybe once 
          onload setting the array by using a loop through the 
          first 7 days of a month we know starts on a sunday? 
          and 12 months of the year?
    getMonthShortText() - returns the abbr month
    getMonthsShort() - return the abbr string array of months
    getMonthFullText() - returns the full month name
    getMonthsFull() - return the full string array of months
    getDayShortText() - returns the abbr day
    getDaysShort() - return the abbr string array of day
    getDayFullText() - returns the full day name
    getDaysFull() - return the full string array of day
*/
Date.prototype.MONTH_FULL_NAMES = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
Date.prototype.MONTH_SHORT_NAMES = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec");
Date.prototype.DAY_FULL_NAMES = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
Date.prototype.DAY_SHORT_NAMES = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
Date.prototype.getMonthFullText = getMonthFullText;
Date.prototype.getMonthShortText = getMonthShortText;
Date.prototype.getDayFullText = getDayFullText;
Date.prototype.getDayShortText = getDayShortText;
Date.prototype.getMonthsShort = getMonthsShort;
Date.prototype.getMonthsFull = getMonthsFull;
Date.prototype.getDaysFull = getDaysFull;
Date.prototype.getDaysShort = getDaysShort;
function getMonthShortText()
{   return (this.getMonth() > -1) ? this.MONTH_SHORT_NAMES[this.getMonth()] : false;    }
function getMonthFullText()
{   return (this.getMonth() > -1) ? this.MONTH_FULL_NAMES[this.getMonth()] : false;    }
function getDayFullText()
{   return (this.getDay() > -1) ? this.DAY_FULL_NAMES[this.getDay()] : false;    }
function getDayShortText()
{   return (this.getDay() > -1) ? this.DAY_SHORT_NAMES[this.getDay()] : false;    }
function getMonthsShort()
{   return this.MONTH_SHORT_NAMES;    }
function getMonthsFull()
{   return this.MONTH_FULL_NAMES;    }
function getDaysFull()
{   return this.DAY_FULL_NAMES;    }
function getDaysShort()
{   return this.DAY_SHORT_NAMES;    }


/*
    These functions get future / past days and months.  All wrap around to beginning when needed.
    getNextMonth() - returns the next month from this.  wraps to jan
    getPrevMonth() - returns the prev month from this.  wraps to dec
    getNextYear() - returns the next year
    getPrevYear() - returns the prev year
    getNextDay() - returns the next month from this.  wraps to 1
    getPrevDay() - returns the prev month from this.  wraps to # of days in prev month
*/
Date.prototype.getNextMonth = getNextMonth;
Date.prototype.getPrevMonth = getPrevMonth;
Date.prototype.getNextYear = getNextYear;
Date.prototype.getPrevYear = getPrevYear;
Date.prototype.getNextDay = getNextDay;
Date.prototype.getPrevDay = getPrevDay;
function getNextMonth()
{   return (this.getDisplayMonth() == false) ? false : (this.getDisplayMonth() == 12) ? 1 : this.getDisplayMonth() + 1;    }
function getPrevMonth()
{   return (this.getDisplayMonth() == false) ? false : (this.getDisplayMonth() == 1) ? 12 : this.getDisplayMonth() - 1;    }
function getNextYear()
{   return (this.getFullYear() < 0) ? false : this.getFullYear() + 1;    }
function getPrevYear()
{   return (this.getFullYear() < 0) ? false : this.getFullYear() - 1;    }
function getNextDay()
{   return (this.getDate() < 0) ? false : (this.getDate() + 1 > this.getDaysInMonth()) ? 1 : this.getDate() + 1;    }
function getPrevDay()
{
    var tempDay = new Date((this.getPrevMonth() + "/1/" + this.getFullYear()));
    return (this.getDate() < 0) ? false : (this.getDate() == 1) ? tempDay.getDaysInMonth() : this.getDate() - 1;
}


/*
    Here we do some neat stuff with future / past dates.  These functions all 
    return new Date() objects themselves.  They also wrap depending.
    getNextDayDate() - returns the next days date.  1/15/2000 - 1/16/2000
    getPrevDayDate() - returns the prev days date.  1/15/2000 - 1/14/2000
    getNextMonthDate() - returns the next months date.  1/15/2004 - 2/15/2004
    getPrevMonthDate() - returns the prev months date.  1/15/2004 - 12/15/2003
    getNextYearDate() - returns the next years date. 1/15/2004 - 1/15/2005
    getPrevYearDate() - returns the prev years date. 1/15/2004 - 1/15/2003
*/
Date.prototype.getNextDayDate = getNextDayDate;
Date.prototype.getPrevDayDate = getPrevDayDate;
Date.prototype.getNextMonthDate = getNextMonthDate;
Date.prototype.getPrevMonthDate = getPrevMonthDate;
Date.prototype.getNextYearDate = getNextYearDate;
Date.prototype.getPrevYearDate = getPrevYearDate;
function getNextDayDate()
{
    var d = this.getNextDay();
    var m = (d == 1) ? this.getNextMonth() : this.getDisplayMonth();
    var y = (d == 1 && m == 1) ? this.getNextYear() : this.getFullYear();
    return new Date(m + this.STYLE + d + this.STYLE + y);
}
function getPrevDayDate()
{
    var d = this.getPrevDay();
    var m = (this.getDate() == 1) ? this.getPrevMonth() : this.getDisplayMonth();
    var y = (this.getDate() == 1 && m == 12) ? this.getPrevYear() : this.getFullYear();
    return new Date(m + this.STYLE + d + this.STYLE + y);
}
function getNextMonthDate()
{
    var m = this.getNextMonth();
    var d = 1;
    var y = (m == 1) ? this.getNextYear() : this.getFullYear();
    var temp = new Date(m + this.STYLE + d + this.STYLE + y);
    //alert(this + "\n" + m + this.STYLE + d + this.STYLE + y);
    if (this.getDate() < temp.getDaysInMonth())
    {   temp.setDate(this.getDate());    }
    //alert(this + "\n" + temp);
    return temp;
}
function getPrevMonthDate()
{
    var m = this.getPrevMonth();
    var d = 1;
    var y = (m == 12) ? this.getPrevYear() : this.getFullYear();
    var temp = new Date(m + this.STYLE + d + this.STYLE + y);
    if (this.getDate() < temp.getDaysInMonth())
    {   temp.setDate(this.getDate());    }
    //alert(this + "\n" + temp);
    return temp;
}
function getNextYearDate()
{
    var m = this.getDisplayMonth();
    var d = (m == 2 && this.getDate() == 29) ? 1 : this.getDate();
    var y = this.getNextYear();
    var temp = new Date(m + this.STYLE + d + this.STYLE + y);
    return temp;
}
function getPrevYearDate()
{
    var m = this.getDisplayMonth();
    var d = (m == 2 && this.getDate() == 29) ? 1 : this.getDate();
    var y = this.getPrevYear();
    var temp = new Date(m + this.STYLE + d + this.STYLE + y);
    return temp;
}


/*
    Here we do some stuff with date comparisons.
    isDateBefore(theDate) - returns boolean.  theDate is another date object.
    isDateAfter(theDate) - returns boolean.  theDate is another date object.
    isDateSame(theDate) - returns boolean.  theDate is another date object.
*/
Date.prototype.isDateBefore = isDateBefore;
Date.prototype.isDateAfter = isDateAfter;
Date.prototype.isDateSame = isDateSame;
function isDateBefore(theDate)
{   return (theDate && theDate.isDate && theDate.isDate() && this < theDate) ? true : false;    }
function isDateAfter(theDate)
{   return (theDate && theDate.isDate && theDate.isDate() && this > theDate) ? true : false;    }
function isDateSame(theDate)
{   return (theDate && theDate.isDate && theDate.isDate() && this == theDate) ? true : false;    }


