/* *********************************************************
** FORMNUM1.JS - JS Number/Date/Time Formatting Library 1.0
** ========================================================
** This file contains the formatNum() function and all its
** supporting code. You use formatNum() to convert a number
** or Date object into a custom-formatted string, which you 
** can then document.write() to a Web page. For example, you
** could format the date 1/1/2001 as:
**   "1/1/01", "1-1-01", "1.1.01", "1/1/2001", "1-1-2001", "1.1.2001", 
**   "January 1, 2001", "1. January 2001", "January 1st, 2001",
**   "January First, Two Thousand One", "Monday, January the
**   First, Two Thousand One", etc.
** See the formatNum() header below for usage instructions. 
** And please be so kind as to maintain this header. :-) 
**
** For tons of examples of formatNum() in action, see the 
** October, 2000 formatNum() ScriptHead column:
** www.zdnet.com/devhead/stories/articles/0,4413,2170375,00.html
**
** Author      Ver  Date     Comments
** ======      ===  ====     ========
** Rick Scott  1.0  10/1/00  Grand debut
**
** Copyright 2000, Rick Scott, all rights reserved.
********************************************************* */


/* global vars ****************************************** */

var Tagstr = "";  // current ^...^ tag of formatNum() formatstr arg

var Months = new Array(  // month names
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
);

var Days = new Array(  // day names
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday"
);

var MIN_INT = -2147483648;  // JS min/max integer values
var MAX_INT = 2147483647;   // betcha didn't know this!?
// you can use exponential notation (e.g., 6.02e+23) to represent nums 
// much lower/higher than these; but that comes next month in v2.0 ...

var cardnums = new Array(   // it's easier this way, trust me ... ;-) 
  "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", 
  "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", 
  "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", 
  "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", 
  "twenty-seven", "twenty-eight", "twenty-nine", "thirty", "thirty-one", 
  "thirty-two", "thirty-three", "thirty-four", "thirty-five", "thirty-six", 
  "thirty-seven", "thirty-eight", "thirty-nine", "forty", "forty-one", 
  "forty-two", "forty-three", "forty-four", "forty-five", "forty-six", 
  "forty-seven", "forty-eight", "forty-nine", "fifty", "fifty-one", "fifty-two", 
  "fifty-three", "fifty-four", "fifty-five", "fifty-six", "fifty-seven", 
  "fifty-eight", "fifty-nine", "sixty", "sixty-one", "sixty-two", "sixty-three", 
  "sixty-four", "sixty-five", "sixty-six", "sixty-seven", "sixty-eight", 
  "sixty-nine", "seventy", "seventy-one", "seventy-two", "seventy-three", 
  "seventy-four", "seventy-five", "seventy-six", "seventy-seven", "seventy-eight",
  "seventy-nine", "eighty", "eighty-one", "eighty-two", "eighty-three", 
  "eighty-four", "eighty-five", "eighty-six", "eighty-seven", "eighty-eight", 
  "eighty-nine", "ninety", "ninety-one", "ninety-two", "ninety-three", "ninety-four",
  "ninety-five", "ninety-six", "ninety-seven", "ninety-eight", "ninety-nine"
);

var placevalues = new Array(  // for cardinalizing/ordinalizing numbers
  "", 
  " thousand ", 
  " million ", 
  " billion ",
  " trillion "  // it'll never go this high, but what the heck ... 
);

var lower = "lower";  // to specify case of formatted number string
var UPPER = "UPPER";
var Mixed = "Mixed";


/* formatNum() ****************************************** */
// usage: formatNum(num, formatstr)
//   num - any valid numeric value or date object
//   formatstr - str containing normal text and/or html tags 
//     and/or any of these formatNum() tags:
//   number formatting tags (examples: 1234.5678, -9)
//     ^#[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - "1234", "-9"
//         ^#ordtxt^ converts to ordinal text - 
//           "one thousand two hundred thirty-fourth", "minus ninth"
//           ^#Ordtxt^ and ^#ORDTXT^ capitalize differently
//         ^#ordnum^ converts to an ordinal number - "1234th", "-9th"
//           ^#ORDNUM" capitalizes differently
//         ^#card^ converts to a cardinal number - 
//           "one thousand two hundred thirty four", "minus nine"
//           ^#Card^ and "#CARD" capitalize differently
//     ^#.[card|Card|CARD]^ - 1234.5678, -9
//     ^#.N[card|Card|CARD]^ - N is 1-8, ex: ^#.2^ - 1234.56, -9.00
//     ^#,###[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 1,234, -9
//     ^#,###.[card|Card|CARD]^ - 1,234.5678, -9
//     ^#,###.N[card|Card|CARD]^ - N is 1-8, ex: ^#.6^ - 1,234.567800, -9.000000
//   date formatting tags (example: 1/1/2001)
//     ^m[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 1
//     ^0m^ - 01
//     ^mon^ - jan
//     ^Mon^ - Jan
//     ^month^ - january
//     ^Month^ - January
//     ^d[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 1
//     ^0d^ - 01
//     ^dy^ - mon
//     ^Dy^ - Mon
//     ^day^ - monday
//     ^Day^ - Monday
//     ^y[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 1
//     ^0y^ - 01
//     ^yyyy[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 2001
//   time formatting tags (examples: 9:08:09 a.m., 9:17:18 p.m.)
//     ^h[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 9, 9
//     ^0h^ - 09, 09
//     ^h12[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 9, 9
//     ^0h12^ - 09, 09
//     ^h24[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 9, 21
//     ^0h24^ - 09, 21
//     ^mi[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 8, 17
//     ^0mi^ - 08, 17
//     ^s[ordtxt|Ordtxt|ORDTXT|ordnum|ORDNUM|card|Card|CARD]^ - 9, 18
//     ^0s^ - 09, 18
//     ^am/pm^, ^AM/PM^, ^a.m./p.m.^, ^A.M./P.M.^
//       - am, pm, AM, PM, a.m., p.m., A.M., P.M.
/* ****************************************************** */

function formatNum(num, formatstr) {

  // first, verify correctness of num and formatstr arguments
  //   you might want to remove these alert() statements ... 
  if (arguments.length != 2) {  // both arguments required
    alert("Error: Wrong number of arguments to formatNum().");
    return;
  }
  if (typeof num != "number" && typeof num != "object") {
    alert("Error: First argument to formatNum() must be a number or Date object.--" + num + "type of=" + typeof num);
    return;
  }
  if (typeof num == "number" && (num < MIN_INT || num > MAX_INT)) { 
    alert("Error: JS cannot process numbers < " + MIN_INT + " or > " + MAX_INT + ".");
    return;
  }
  if (typeof formatstr != "string") {
    alert("Error: Second argument to formatNum() must be a string.");
    return;
  }
  if (typeof num == "number" && formatstr == "^#,###.2^") num = (Math.round(num*100))/100;
  
  // okay, num and formatstr args are fine, let's process, baybey! 
  var returnstr = "";
  for (var index=0; index<formatstr.length; index++) {
    if (formatstr.charAt(index) == "^") {
      index = getTagstr(num, formatstr, index);  // returns index of closing tag ^ 
      returnstr += Tagstr;
    }
    else {
      returnstr += formatstr.charAt(index);
    }
  }
  return returnstr;  
}


/* get_ordtxt() ***************************************** */

function get_ordtxt(str, tag) {  // rets correct case of ordinalized text str
  if (typeof str == "string" && str.indexOf(",") != -1)
    str = stripcommas(str);
  if (tag.indexOf("ordtxt") != -1)
    str = ordinalizeToTxt(str, "lower")
  else if (tag.indexOf("ORDTXT") != -1)
    str = ordinalizeToTxt(str, "UPPER")
  else if (tag.indexOf("Ordtxt") != -1)
    str = ordinalizeToTxt(str, "Mixed")
  return str;
}


/* get_ordnum() ***************************************** */

function get_ordnum(str, tag) {  // rets correct case of ordinalized num str
  if (typeof str == "string" && str.indexOf(",") != -1)
    str = stripcommas(str);
  if (tag.indexOf("ordnum") != -1)
    str = ordinalizeToNum(str, "lower")
  else if (tag.indexOf("ORDNUM") != -1)
    str = ordinalizeToNum(str, "UPPER")
  return str;
}


/* get_ordcard() **************************************** */

function get_card(str, tag) {  // rets correct case of cardinalized text str
  if (typeof str == "string" && str.indexOf(",") != -1)
    str = stripcommas(str);
  if (tag.indexOf("card") != -1)
    str = cardinalize(str, "lower")
  else if (tag.indexOf("CARD") != -1)
    str = cardinalize(str, "UPPER")
  else if (tag.indexOf("Card") != -1)
    str = cardinalize(str, "Mixed")
  return str;
}


/* getTagstr() **************************************** */
/* assigns a value to the global var Tagstr *********** */
/*   and returns index of closing tag ^ delimiter ***** */

function getTagstr(num, formatstr, index) {

  var tag = ""
  Tagstr = "";
  index++;  // advance to next char after opening tag ^ delimiter
  while (formatstr.charAt(index) != "^")
    tag += formatstr.charAt(index++);

  switch (tag) {  // and away we go ... ! 

    // number cases

    case "#":
    case "#ordtxt": case "#Ordtxt": case "#ORDTXT":
    case "#ordnum": case "#ORDNUM":
    case "#card": case "#Card": case "#CARD":
      Tagstr = "" + parseInt(num);
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "#.":
    case "#.card": case "#.Card": case "#.CARD":
      Tagstr = "" + num;
      if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one point two)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "#.1":
    case "#.1card": case "#.1Card": case "#.1CARD":
    case "#.2":
    case "#.2card": case "#.2Card": case "#.2CARD":
    case "#.3":
    case "#.3card": case "#.3Card": case "#.3CARD":
    case "#.4":
    case "#.4card": case "#.4Card": case "#.4CARD":
    case "#.5":
    case "#.5card": case "#.5Card": case "#.5CARD":
    case "#.6":
    case "#.6card": case "#.6Card": case "#.6CARD":
    case "#.7":
    case "#.7card": case "#.7Card": case "#.7CARD":
    case "#.8":
    case "#.8card": case "#.8Card": case "#.8CARD":
      var decnums = parseInt(tag.substring(2,3));  // get specified # dec nums
      var num = "" + num;  // convert num to string
      var numparts = num.split(".");  // numparts[0] = int, numparts[1] = dec
      if (numparts.length < 2)
        numparts[1] = "";
      if (numparts[1].length < decnums)
        for (var i=numparts[1].length; i<decnums; i++)
          numparts[1] += "0";
      else if (numparts[1].length > decnums)
        numparts[1] = numparts[1].substring(0, decnums);
      Tagstr = numparts[0] + "." + numparts[1];
      if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one point two)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "#,###":
    case "#,###ordtxt": case "#,###Ordtxt": case "#,###ORDTXT":
    case "#,###ordnum": case "#,###ORDNUM":
    case "#,###card": case "#,###Card": case "#,###CARD":
      Tagstr = "" + parseInt(num);
      var numunits = splitIntoThrees(Tagstr);  // split into threes
      Tagstr = "";
      for (var i=numunits.length-1; i>=0; i--)   // then insert commas
        Tagstr += numunits[i] + ((i > 0) ? "," : "");
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "#,###.":
    case "#,###.card": case "#,###.Card": case "#,###.CARD":
      num = "" + num;  // turn num into a string
      var numparts = num.split(".");  // then split into int + dec parts
      Tagstr = "" + parseInt(numparts[0]);
      numunits = splitIntoThrees(Tagstr);     // split into threes
      Tagstr = "";
      for (var i=numunits.length-1; i>=0; i--)  // then insert commas
        Tagstr += numunits[i] + ((i > 0) ? "," : "");
      if (numparts.length > 1)
        Tagstr += "." + numparts[1];
      if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one point two)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "#,###.1":
    case "#,###.1card": case "#,###.1Card": case "#,###.1CARD":
    case "#,###.2":
    case "#,###.2card": case "#,###.2Card": case "#,###.2CARD":
    case "#,###.3":
    case "#,###.3card": case "#,###.3Card": case "#,###.3CARD":
    case "#,###.4":
    case "#,###.4card": case "#,###.4Card": case "#,###.4CARD":
    case "#,###.5":
    case "#,###.5card": case "#,###.5Card": case "#,###.5CARD":
    case "#,###.6":
    case "#,###.6card": case "#,###.6Card": case "#,###.6CARD":
    case "#,###.7":
    case "#,###.7card": case "#,###.7Card": case "#,###.7CARD":
    case "#,###.8":
    case "#,###.8card": case "#,###.8Card": case "#,###.8CARD":
      if (tag == "currency")
        tag = "#,###.2";
      var decnums = parseInt(tag.substring(6,7));  // get specified # dec nums
      var num = "" + num;  // convert num to string
      var numparts = num.split(".");  // numparts[0] = int, numparts[1] = dec
      if (numparts.length < 2)
        numparts[1] = "";
      if (numparts[1].length < decnums)
        for (var i=numparts[1].length; i<decnums; i++)
          numparts[1] += "0";
      else if (numparts[1].length > decnums)
        numparts[1] = numparts[1].substring(0, decnums);
      Tagstr = numparts[0] + "." + numparts[1];
      // at this point, Tagstr = #.N
      // now we need #,###.N -- to do this, we need to convert # to #,###
      var numparts = Tagstr.split(".");  // split Tagstr into int + dec parts
      Tagstr = "" + parseInt(numparts[0]);
      numunits = splitIntoThrees(Tagstr);     // split into threes
      Tagstr = "";
      for (var i=numunits.length-1; i>=0; i--)  // then insert commas
        Tagstr += numunits[i] + ((i > 0) ? "," : "");
      if (numparts.length > 1)
        Tagstr += "." + numparts[1];
      if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one point two)
        Tagstr = get_card(Tagstr, tag);
      break;

    // date cases

    case "m":
    case "mordtxt": case "mOrdtxt": case "mORDTXT":
    case "mordnum": case "mORDNUM": 
    case "mcard": case "mCard": case "mCARD":
      Tagstr = "" + (num.getMonth() + 1);
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0m":
      if (num.getMonth() + 1 < 10)
        Tagstr = "0" + (num.getMonth() + 1);
      else
        Tagstr = "" + (num.getMonth() + 1);
      break

    case "mon":
      Tagstr = Months[num.getMonth()].substring(0,3).toLowerCase();
      break;

    case "Mon":
      Tagstr = Months[num.getMonth()].substring(0,3);
      break;

    case "month":
      Tagstr = Months[num.getMonth()].toLowerCase();
      break;

    case "Month":
      Tagstr = Months[num.getMonth()];
      break;

    case "d":
    case "dordtxt": case "dOrdtxt": case "dORDTXT":
    case "dordnum": case "dORDNUM": 
    case "dcard": case "dCard": case "dCARD":
      Tagstr = "" + num.getDate();
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0d":
      if (num.getDate() < 10)
        Tagstr = "0" + num.getDate();
      else
        Tagstr = "" + num.getDate();
      break

    case "dy":
      Tagstr = Days[num.getDay()].substring(0,3).toLowerCase();
      break;

    case "Dy":
      Tagstr = Days[num.getDay()].substring(0,3);
      break;

    case "day":
      Tagstr = Days[num.getDay()].toLowerCase();
      break;

    case "Day":
      Tagstr = Days[num.getDay()];
      break;

    case "y":
    case "yordtxt": case "yOrdtxt": case "yORDTXT":
    case "yordnum": case "yORDNUM": 
    case "ycard": case "yCard": case "yCARD":
      Tagstr = ("" + getyyyyYear(num)).substring(2,4);
      if (Tagstr.charAt(0) == "0")
        Tagstr = Tagstr.substring(1,2)
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0y":
      Tagstr = ("" + getyyyyYear(num)).substring(2,4);
      break;

    case "yyyy":
    case "yyyyordtxt": case "yyyyOrdtxt": case "yyyyORDTXT":
    case "yyyyordnum": case "yyyyORDNUM": 
    case "yyyycard": case "yyyyCard": case "yyyyCARD":
      Tagstr = "" + getyyyyYear(num);
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    // time cases

    case "h":
    case "hordtxt": case "hOrdtxt": case "hORDTXT":
    case "hordnum": case "hORDNUM": 
    case "hcard": case "hCard": case "hCARD":
    case "h12":
    case "h12ordtxt": case "h12Ordtxt": case "h12ORDTXT":
    case "h12ordnum": case "h12ORDNUM": 
    case "h12card": case "h12Card": case "h12CARD":
      Tagstr = num.getHours() % 12;
      if (Tagstr == 0)
        Tagstr = "" + 12;
      else
        Tagstr = "" + Tagstr;
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0h":
    case "0h12":
      Tagstr = num.getHours() % 12;
      if (Tagstr == 0)
        Tagstr = "" + 12;
      else if (Tagstr < 10)
        Tagstr = "0" + Tagstr;
      else
        Tagstr = "" + Tagstr;
      break;

    case "h24":
    case "h24ordtxt": case "h24Ordtxt": case "h24ORDTXT":
    case "h24ordnum": case "h24ORDNUM": 
    case "h24card": case "h24Card": case "h24CARD":
      Tagstr = num.getHours();
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0h24":
      Tagstr = num.getHours();
      if (Tagstr < 10)
        Tagstr = "0" + Tagstr;
      else
        Tagstr = "" + Tagstr;
      break;

    case "mi":
    case "miordtxt": case "miOrdtxt": case "miORDTXT":
    case "miordnum": case "miORDNUM": 
    case "micard": case "miCard": case "miCARD":
      Tagstr = num.getMinutes();
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0mi":
      Tagstr = num.getMinutes();
      if (Tagstr < 10)
        Tagstr = "0" + Tagstr;
      else
        Tagstr = "" + Tagstr;
      break;

    case "s":
    case "sordtxt": case "sOrdtxt": case "sORDTXT":
    case "sordnum": case "sORDNUM": 
    case "scard": case "sCard": case "sCARD":
      Tagstr = num.getSeconds();
      if (tag.toLowerCase().indexOf("ordtxt") != -1)  // ordinal text (first)
        Tagstr = get_ordtxt(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("ordnum") != -1)  // ordinal num (1st)
        Tagstr = get_ordnum(Tagstr, tag);
      else if (tag.toLowerCase().indexOf("card") != -1)  // cardinal text (one)
        Tagstr = get_card(Tagstr, tag);
      break;

    case "0s":
      Tagstr = num.getSeconds();
      if (Tagstr < 10)
        Tagstr = "0" + Tagstr;
      else
        Tagstr = "" + Tagstr;
      break;

    case "am/pm": case "AM/PM":
    case "a.m./p.m.": case "A.M./P.M.":
      var strarray = new Array();
      if (num.getHours() < 12) {
        strarray = tag.split("/");
        Tagstr = strarray[0];
      }
      else {
        strarray = tag.split("/");
        Tagstr = strarray[1];
      }
      break;
  }  
  return index;
}


/* ordinalizeToNum() ************************************ */

function ordinalizeToNum(num, strcase) {  // return "1st", "2ND", etc.
  var val = Math.abs(num) % 100;  // get last two (or one) digit(s) of num
  var retstr = "";
  num = "" + num;  // convert num to a string
  if (val <= 20 && val >= 10)
    retstr = num + "th";
  else if (num.charAt(num.length-1) == "1")
    retstr = num + "st";
  else if (num.charAt(num.length-1) == "2")
    retstr = num + "nd";
  else if (num.charAt(num.length-1) == "3")
    retstr = num + "rd";
  else
    retstr = num + "th";

  if (arguments.length < 2 || strcase == "lower")
    return retstr.toLowerCase();
  else if (strcase == "UPPER")
    return retstr.toUpperCase();
  else if (strcase == "Mixed")
    return capitalizeStr(retstr);
}


/* ordinalizeToTxt() ************************************ */

function ordinalizeToTxt(num, strcase) {  // return "first", "Second", "THIRD", etc.
  var numstr = "";
  var val = Math.abs(num);
  numstr = cardinalize(val);
  var numstrarray = numstr.split(" ");
  var lastnumstr = numstrarray[numstrarray.length-1];
  var lastnumstrarray = lastnumstr.split("-");
  lastnumstr = lastnumstrarray[lastnumstrarray.length-1];
  switch (lastnumstr) { 
    case "zero":
      lastnumstr = "zeroeth";  // ppl: programmer's poetic license?
      break;
    case "one":
      lastnumstr = "first";
      break;
    case "two":
      lastnumstr = "second";
      break;
    case "three":
      lastnumstr = "third";
      break;
    case "five":
      lastnumstr = "fifth";
      break;
    case "eight":
      lastnumstr = "eighth";
      break;
    case "nine":
      lastnumstr = "ninth";
      break;
    case "twelve":
      lastnumstr = "twelfth";
      break;
    case "twenty":
      lastnumstr = "twentieth";
      break;
    case "thirty":
      lastnumstr = "thirtieth";
      break;
    case "forty":
      lastnumstr = "fortieth";
      break;
    case "fifty":
      lastnumstr = "fiftieth";
      break;
    case "sixty":
      lastnumstr = "sixtieth";
      break;
    case "seventy":
      lastnumstr = "seventieth";
      break;
    case "eighty":
      lastnumstr = "eightieth";
      break;
    case "ninety":
      lastnumstr = "ninetieth";
      break;
    default:
      lastnumstr = lastnumstr + "th";
      break;
  }
  var retstr = "";
  for (var i=0; i<numstrarray.length-1; i++)
    retstr += numstrarray[i] + " ";
  for (var i=0; i<lastnumstrarray.length-1; i++)
    retstr += lastnumstrarray[i] + "-";

  if (arguments.length < 2 || strcase == "lower") {
    if (num < 0)
      return ("minus " + retstr + lastnumstr).toLowerCase();
    else
      return (retstr + lastnumstr).toLowerCase();
  }
  else if (strcase == "UPPER") {
    if (num < 0)
      return ("minus " + retstr + lastnumstr).toUpperCase();
    else
      return (retstr + lastnumstr).toUpperCase();
  }
  else if (strcase == "Mixed") {
    if (num < 0)
      return capitalizeStr("minus " + retstr + lastnumstr);
    else
      return capitalizeStr(retstr + lastnumstr);
  }
}


/* cardinalize() **************************************** */

function cardinalize(num, strcase) {  // return "one", "two", "three point four", etc.
  var retstr = "";
  var numstr = "" + num;  // convert num to string
  if (numstr.charAt(0) == "-")
    numstr = numstr.substring(1,numstr.length);
  var numparts = numstr.split(".");
  var numunits = splitIntoThrees(numparts[0]);  // split into threes
  // cardinalize numunits[] elements
  for (var i=0; i<numunits.length; i++) { 
    if (numunits[i].length < 2) {
      retstr = cardnums[convertStrToInt(numunits[i])] +
               placevalues[i] + retstr;
    }
    else if (numunits[i].length < 3) {
      retstr = ((cardnums[convertStrToInt(numunits[i])] != "zero") 
               ? cardnums[convertStrToInt(numunits[i])] 
               : "") +
               placevalues[i] + retstr;
    }
    else { 
      retstr = ((cardnums[convertStrToInt(numunits[i].substring(0,1))] != "zero") 
               ? (cardnums[convertStrToInt(numunits[i].substring(0,1))] + " hundred ") 
               : "") + 
               ((cardnums[convertStrToInt(numunits[i].substring(1,3))] != "zero") 
               ? cardnums[convertStrToInt(numunits[i].substring(1,3))] 
               : "") + 
               placevalues[i] + retstr;
    }
  }
  if (num < 0)
    retstr = "minus " + retstr;
  if (numparts.length == 2) {  // there's a decimal portion to num
    retstr += " point";
    for (var i=0; i<numparts[1].length; i++)
      retstr += " " + cardnums[numparts[1].charAt(i)];
  }
  if (arguments.length < 2 || strcase == "lower")
    retstr = retstr.toLowerCase();
  else if (strcase == "UPPER")
    retstr = retstr.toUpperCase();
  else if (strcase == "Mixed")
    retstr = capitalizeStr(retstr);

  for (var i=retstr.length-1; i>=0; i--)
    if (retstr.charAt(i) != " ")
      break;
  retstr = retstr.substring(0,i+1);
  return retstr;
}


/* getyyyyYear(date) ************************************ */

function getyyyyYear(date) { // get year in yyyy format
  var yyyyYear = date.getYear();
  if (yyyyYear < 1000)
    yyyyYear += 1900;
  return yyyyYear;
}


/* splitIntoThrees() ************************************ */

function splitIntoThrees(str) {  // split str into array of three-char elements
  var retarray = new Array();
  for (var i=str.length-1,j=1,k=0; i>=0; i--,j++) { 
   retarray[k] = str.charAt(i) + ((retarray[k] != null) ? retarray[k] : "");
   if (j % 3 == 0)
     k++;
  }
  return retarray;
}


/* capitalizeStr() ************************************** */

function capitalizeStr(str) {  // ret str with capitalized first letter of each word
  // i really gotta learn how to use regular expressions ... 
  var capitalizeNextLetter = true;
  var retstr = "";

  for (var i=0; i<str.length; i++) {
    if (capitalizeNextLetter && (str.charAt(i) != " ")) {
      retstr += str.substring(i,i+1).toUpperCase();
      capitalizeNextLetter = false;
    }
    else if (str.charAt(i) == " " || str.charAt(i) == "-") {
      retstr += str.substring(i,i+1);
      capitalizeNextLetter = true;
    }
    else {
      retstr += str.substring(i,i+1);
    }
  }
  return retstr;
}


/* convertStrToInt() *************************************** */
// - because parseInt() doesn't work with 0-padded strs!
//   e.g., parseInt("09") evaluates to 0, not to 9

function convertStrToInt(str) {
  for (var i=0; i<str.length; i++) 
    if (str.charAt(i) != "0")
      break;
  if (i == str.length)
    return 0;
  else
    return parseInt(str.substring(i, str.length));
}


/* stripcommas() **************************************** */

function stripcommas(str) {  // returns str without commas (,)
  var retstr = "";
  for (var i=0; i<str.length; i++) {
    if (str.charAt(i) != ",")
      retstr += str.substring(i, i+1);
  }
  return retstr;
}


