/* JSDate
** Copyright (c) 1999 Christopher D. Doemel
**
** Version 1.1.1, August 1999

**
** Month (M)
** Format Code   Returns the month as
** -----------   ----------------------------------------------------------
** M             A number without a leading 0 (zero) for single-digit
**               months. For example, July is "7".
** MM            A number with a leading 0 (zero) for single-digit months.
**               For example, July is "07".
** MMM           A three-letter abbreviation.  For example, July is "Jul".
** MMMM          The full name of the month.
**
** Day (d)
** Format Code   Returns the day as
** -----------   ----------------------------------------------------------
** d             A number without a leading 0 (zero) for single-digit days.
** dth           A number with a trailing ordinal (e.g., 1st, 2nd, etc.).
**               Yes, it is indeed an awkward format code.
** dd            A number with a leading 0 (zero) for single-digit days.
**               For example, the sixth day of the month is displayed as
**               "06".
** ddd           A three-letter abbreviation. For example, Tuesday is
**               displayed as "Tue".
** dddd          The full name of the day of the week.
**
** Year (y)
** Format Code   Returns the year as
** -----------   ----------------------------------------------------------
** yy            Two digits with a leading 0 (zero) for years 01 through
**               09. For example, 1995 is displayed as "95", and 2006 is
**               displayed as "06".
** yyyy          Four digits.
**
** Hours (h)
** A lower-case "h" bases time on the 12-hour clock.  An uppercase "H" bases
** time on the 24-hour, or military, clock; for example, 5 P.M. is displayed
** as "17".
**
** Format Code   Returns the hour
** -----------   ----------------------------------------------------------
** h or H        Without a leading 0 (zero) for single-digit hours. For
**               example, the hour of 9 A.M. is displayed as "9".
** hh or HH      With a leading 0 (zero) for single-digit hours. For
**               example, the hour of 9 A.M. is displayed as "09".
**
** Minutes (m)
** Format Code   Returns minutes
** -----------   ----------------------------------------------------------
** m             Without a leading 0 for single-digit minutes. For example,
**               "m" displays "2".
** mm            With a leading 0 (zero) for single-digit minutes. For
**               example, "mm" displays "02".
**
** Seconds (s)
** Format Code   Returns seconds
** -----------   ----------------------------------------------------------
** s             Without a leading 0 for single-digit seconds. For example,
**               "s" displays "2".
** ss            With a leading 0 (zero) for single-digit seconds. For
**               example, "ss" displays "02".
**
** Meridiem
** Format Code   Returns
** -----------   ----------------------------------------------------------
** AM/PM		 Upper-case. For example, "h AM/PM" displays "9 AM" or
**               "5 PM".
** am/pm         Lower-case. For example, "h am/pm" displays "9 am" or
**               "5 pm".
** A/P           Abbreviated upper-case. For example, "h A/P" displays
**               "9 A" or "5 P".
** a/p           Abbreviated lower-case. For example, "h a/p" displays
**               "9 a" or "5 p".
**
** If you want to include literal text, enclose it in single quotation
** marks -- otherwise it will be interpreted as a date code.  For instance,
** "'Today is' MMMM d." displays "Today is March 16."
**
** Punctuation marks are OK.  To display the time, for instance, you
** can use "h:mm AM/PM" which would display "8:03 PM".
*/

function getFormattedDate(theFormat) {
    var i = 0;
    var lastChar = "";
    var fieldCode = "";
    var fieldResult = "";
    var theDate = new Date();
    
    /* Convert theFormat to a string, even if it is already a string.
    ** If I don't do this, a lot of the String methods don't work.
    */
    theFormat = new String(theFormat);
    
    // Handle meridiem codes -- you know, AM or PM stuff.
    if (theFormat.charAt(i) == "a" || theFormat.charAt(i) == "A") {
        if (theFormat.indexOf("am/pm") == 0) {
            fieldResult = lcMeridiem(theDate);
            i += 5;
        }
        else if (theFormat.indexOf("AM/PM") == 0) {
            fieldResult = ucMeridiem(theDate);
            i += 5;
        }
        else if (theFormat.indexOf("a/p") == 0) {
            fieldResult = lcAbbrMeridiem(theDate);
            i += 3;
        }
        else if (theFormat.indexOf("A/P") == 0) {
            fieldResult = ucAbbrMeridiem(theDate);
            i += 3;
        }
        else {
            fieldResult = theFormat.charAt(i);
            i++;
        }
    }
    // Handle the oddball ordinal date code
    else if (theFormat.indexOf("dth") == 0) {
       fieldResult = getOrdinalDate(theDate);
       i += 3;
    }
    // Handle literal text (text enclosed by single quotes).
    else if (theFormat.charAt(i) == "'") {
        while (++i <= theFormat.length && theFormat.charAt(i) != "'") {
            fieldResult += theFormat.charAt(i);
        }
        if (theFormat.charAt(i) == "'") { ++i };
    }
    else {
        // Collect the next field code by collecting repeating characters.
        while (i <= theFormat.length) {
            if (lastChar == "") {
                // First time through the loop; grab a char!
                lastChar = theFormat.charAt(i);
                fieldCode += lastChar;
                i++;
                continue;
            }
            if (lastChar == theFormat.charAt(i)) {
                // The char is the same; save it and move on
                fieldCode += lastChar;
                i++;
                continue;
            }
            if (lastChar != theFormat.charAt(i)) {
                // The char is different; time to parse the field!
                break;
            }
        }
        
        // Handle month formats
        if      (fieldCode == "M")    { fieldResult = getOneDigitMonth(theDate);  }
        else if (fieldCode == "MM")   { fieldResult = getTwoDigitMonth(theDate);  }
        else if (fieldCode == "MMM")  { fieldResult = getShortMonthName(theDate); }
        else if (fieldCode == "MMMM") { fieldResult = getLongMonthName(theDate);  }
        
        // Handle date formats
        else if (fieldCode == "d")    { fieldResult = getOneDigitDate(theDate); }
        else if (fieldCode == "dd")   { fieldResult = getTwoDigitDate(theDate); }
        else if (fieldCode == "ddd")  { fieldResult = getShortDayName(theDate); }
        else if (fieldCode == "dddd") { fieldResult = getLongDayName(theDate);  }
        
        // Handle year formats
        else if (fieldCode == "yy")   { fieldResult = getTwoDigitYear(theDate);  }
        else if (fieldCode == "yyyy") { fieldResult = getFourDigitYear(theDate); }
        
        // Handle hour formats
        else if (fieldCode == "h")    { fieldResult = getOneDigitHour(theDate);         }
        else if (fieldCode == "H")    { fieldResult = getOneDigitMilitaryHour(theDate); }
        else if (fieldCode == "hh")   { fieldResult = getTwoDigitHour(theDate);         }
        else if (fieldCode == "HH")   { fieldResult = getTwoDigitMilitaryHour(theDate); }
        
        // Handle minute formats
        else if (fieldCode == "m")    { fieldResult = getOneDigitMinutes(theDate); }
        else if (fieldCode == "mm")   { fieldResult = getTwoDigitMinutes(theDate); }
        
        // Handle second formats
        else if (fieldCode == "s")    { fieldResult = getOneDigitSeconds(theDate); }
        else if (fieldCode == "ss")   { fieldResult = getTwoDigitSeconds(theDate); }
        
        // Handle everything else
        else                          { fieldResult = fieldCode; };
    }
    
    // If we're not done parsing the format codes, call getFormattedDate() with the
    // remaining codes.
    if (i == theFormat.length) { return fieldResult; }
    else { return fieldResult + getFormattedDate(theFormat.substring(i,theFormat.length)); }
}

/* The getDate() and getTime() functions call getFormattedDate() with default
** formats -- this saves time when you just want a standard date or time.
*/

// Returns date, e.g. "December 9, 2001"
function getDate() { return getFormattedDate("MMMM d, yyyy"); }

// Returns time, e.g., "6:03 pm"
function getTime() { return getFormattedDate("h:mm am/pm"); }

/* The following routines construct various portions of the final
** date, and are typically called by the getFormattedDate()
** function -- but you could use them yourself by providing a
** date.  To get the current two-digit date, for example:
**
**    getTwoDigitDate(new Date());
**
** The current version of the script is hard-coded for English
** month and day names.  If you want to use a different language,
** modify the getShortMonthName(), getLongMonthName(),
** getShortDayName(), and getLongDayName(), and getOrdinalDate(),
** functions to use the appropriate month and day names.
*/

function getOneDigitMonth(theDate) {
    return theDate.getMonth() + 1;
}

function getTwoDigitMonth(theDate) {
    var theMonth = getOneDigitMonth(theDate);
    return (theMonth < 10 ? "0" + theMonth : theMonth);
}

function getShortMonthName(theDate) {
    var theMonth = getOneDigitMonth(theDate);
    if      (theMonth == 1)  { return "Jan"; }
    else if (theMonth == 2)  { return "Feb"; }
    else if (theMonth == 3)  { return "Mar"; }
    else if (theMonth == 4)  { return "Apr"; }
    else if (theMonth == 5)  { return "May"; }
    else if (theMonth == 6)  { return "Jun"; }
    else if (theMonth == 7)  { return "Jul"; }
    else if (theMonth == 8)  { return "Aug"; }
    else if (theMonth == 9)  { return "Sep"; }
    else if (theMonth == 10) { return "Oct"; }
    else if (theMonth == 11) { return "Nov"; }
    else                     { return "Dec"; }
}

function getLongMonthName(theDate) {
    var theMonth = getOneDigitMonth(theDate);
    if      (theMonth == 1)  { return "January";   }
    else if (theMonth == 2)  { return "February";  }
    else if (theMonth == 3)  { return "March";     }
    else if (theMonth == 4)  { return "April";     }
    else if (theMonth == 5)  { return "May";       }
    else if (theMonth == 6)  { return "June";      }
    else if (theMonth == 7)  { return "July";      }
    else if (theMonth == 8)  { return "August";    }
    else if (theMonth == 9)  { return "September"; }
    else if (theMonth == 10) { return "October";   }
    else if (theMonth == 11) { return "November";  }
    else                     { return "December";  }
}

function getOneDigitDate(theDate) {
    return theDate.getDate();
}

function getOrdinalDate(theDate) {
    var theDay = getOneDigitDate(theDate);
    if ((theDay == 1) || (theDay == 21) || (theDay == 31)) {
        return theDay + "st";
    }
    else if ((theDay == 2) || (theDay == 22)) {
        return theDay + "nd";
    }
    else if ((theDay == 3) || (theDay == 23)) {
        return theDay + "rd";
    }
    else { return theDay + "th"; }
}

function getTwoDigitDate(theDate) {
    var theDay = getOneDigitDate(theDate);
    return (theDay < 10 ? "0" + theDay : theDay);
}

function getShortDayName(theDate) {
    var theDay = theDate.getDay();
    if      (theDay == 0) { return "Sun"; }
    else if (theDay == 1) { return "Mon"; }
    else if (theDay == 2) { return "Tue"; }
    else if (theDay == 3) { return "Wed"; }
    else if (theDay == 4) { return "Thu"; }
    else if (theDay == 5) { return "Fri"; }
    else                 { return "Sat"; }
}

function getLongDayName(theDate) {
    var theDay = theDate.getDay();
    if      (theDay == 0) { return "Sunday";    }
    else if (theDay == 1) { return "Monday";    }
    else if (theDay == 2) { return "Tuesday";   }
    else if (theDay == 3) { return "Wednesday"; }
    else if (theDay == 4) { return "Thursday";  }
    else if (theDay == 5) { return "Friday";    }
    else                 { return "Saturday";  }
}

function getFourDigitYear(theDate) {
    var theYear = theDate.getYear();
    if (theYear < 1000) { theYear += 1900; }
    return theYear;
}

function getTwoDigitYear(theDate) {
    var theYear = getFourDigitYear(theDate);
    var strYear = new String(theYear);
    return strYear.substring(2,4);
}

function getOneDigitHour(theDate) {
    var theHour = theDate.getHours() % 12;
    if (theHour == 0) { theHour = 12; }
    return theHour;
}

function getTwoDigitHour(theDate) {
    var theHour = getOneDigitHour(theDate);
    return (theHour < 10 ? "0" + theHour : theHour);
}

function getOneDigitMilitaryHour(theDate) {
    return theDate.getHours();
}

function getTwoDigitMilitaryHour(theDate) {
    var theHour = getOneDigitMilitaryHour(theDate);
    return (theHour < 10 ? "0" + theHour : theHour);
}

function getOneDigitMinutes(theDate) {
    return theDate.getMinutes();
}

function getTwoDigitMinutes(theDate) {
    var theMinutes = getOneDigitMinutes(theDate);
    return (theMinutes < 10 ? "0" + theMinutes : theMinutes);
}

function getOneDigitSeconds(theDate) {
    return theDate.getSeconds();
}

function getTwoDigitSeconds(theDate) {
    var theSeconds = getOneDigitSeconds(theDate);
    return (theSeconds < 10 ? "0" + theSeconds : theSeconds);
}

function lcMeridiem(theDate) {
    var theHour = getOneDigitMilitaryHour(theDate);
    return (theHour < 12 ? "am" : "pm");
}

function lcAbbrMeridiem(theDate) {
    var theHour = getOneDigitMilitaryHour(theDate);
    return (theHour < 12 ? "a" : "p");
}

function ucMeridiem(theDate) {
    var theHour = getOneDigitMilitaryHour(theDate);
    return (theHour < 12 ? "AM" : "PM");
}

function ucAbbrMeridiem(theDate) {
    var theHour = getOneDigitMilitaryHour(theDate);
    return (theHour < 12 ? "A" : "P");
}
