	var datePickerDivID = "datepicker";
	var iFrameDivID = "datepickeriframe";
	var dayArrayShort = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
	var dayArrayMed = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	var dayArrayLong = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	var monthArrayShort = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	var monthArrayMed = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec');
	var monthArrayLong = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	var thisMonth = "This Month"
	var closeCalendar = "Close" 
	//Estas variables definen el formato de la fecha
	//Si se quiere usar un formato diferente, hay que cambiar las vairables defaultDateSeparator y defaultDateFormat
	//ya sea aqui o en tu pagina HTML.

	var defaultDateSeparator = "/"; //valores comunes serian "/" o "."
	var defaultDateFormat = "mdy";  //valores validos: "mdy", "dmy", and "ymd"
	var dateSeparator = defaultDateSeparator;
	var dateFormat = defaultDateFormat;

	/**
	Esta es la funcion principal, se la puede llamar desde el evento onClick de un boton.
	Normalment, existira algo como esto en tu pagina HTML:
	Start Date: <input name="StartDate">
	<input type=button value="select" onclick="displayDatePicker('StartDate');">

	Esto provocará que el datepicker se muestre debajo del campo StartDate y cualquier fecha 
	que se elija se actualizará el valor del campo. Si prefieres que el Datepicker se muestre
	debajo del boton, usa el siguiente codigo:
	<input type=button value="select" onclick="displayDatePicker('StartDate', this);">

	So, pretty much, the first argument (dateFieldName) is a string representing the
	name of the field that will be modified if the user picks a date, and the second
	argument (displayBelowThisObject) is optional and represents an actual node
	on the HTML document that the datepicker should be displayed below.

	Así que, el primer argumento (dateFieldName) es una cadena que representa el nombre del campo 
	que se modificará si el usuario elige una fecha, y el segundo argumento (displayBelowThisObject) 
	es opcional y representa el nodo actual del documento HTML bajo el que el datepicker debe mostrarse. 

	En la versión 1,1 de este código, se añaden las variables dtFormat y dtSep, lo que le permitirá 
	utilizar un formato de fecha o de separación de la fecha para una determinada llamada a esta función. 
	Normalmente, sólo se va a configurar estos valores por defecto a nivel global con las variables 
	defaultDateSeparator y defaultDateFormat, pero se puede añadirlo a la lista de parámetros opcionales. 
	Un ejemplo de uso es:
	
	<input type=button value="select" onclick="displayDatePicker('StartDate', false, 'dmy', '.');">

	Esto mostrará el datepicker debajo del campo StartDate (porque el parametro DisplayBelowThisObject
	es falso), y actualizar el campo StartDate con el valor elegido del datepicker utilizando un formato 
	de fecha de dd.mm.yyyy
	*/
	
	function displayDatePicker(dateFieldName, displayBelowThisObject, dtFormat, dtSep)
	{
		var targetDateField = document.getElementsByName (dateFieldName).item(0);
		//Si no se especifica el nodo bajo el cual se muestra el datepicker, se lo muestra debajo
		//del campo de fecha que estamos actualizando
		if (!displayBelowThisObject)
		  displayBelowThisObject = targetDateField;
		//Si fue dado un caracter de separacion, actualiza la vaiable dateSeparator
		if (dtSep)
		  dateSeparator = dtSep;
		else
		  dateSeparator = defaultDateSeparator;
		//Si fue dado un formato de fecha, actualiza la variable dateFormat
		if (dtFormat)
		  dateFormat = dtFormat;
		else
		  dateFormat = defaultDateFormat;
		var x = displayBelowThisObject.offsetLeft;
		var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ;
		//Se ocupa de los elementro dentro de las tablas
		var parent = displayBelowThisObject;
		while (parent.offsetParent) 
		{
		  parent = parent.offsetParent;
		  x += parent.offsetLeft;
		  y += parent.offsetTop ;
		}
		drawDatePicker(targetDateField, x, y);
	}

	/**
	Dibuja el objeto datepicker (Que no es más que una tabla con los elementos del calendario) 
	en las cordenadas x e y especificadas, utilizando el objeto targetDateField como etiqueta 
	de entrada, en la que se obtendra el valor de una fecha. 
	Esta función normalmente será convocada por la funcion displayDatePicker.
	*/
	function drawDatePicker(targetDateField, x, y)
	{
		var dt = getFieldDate(targetDateField.value);
		//La tabla del datepicker se dibuja dentro de un <div> con un ID definido por la variable
		//global datePickerDivID. Si este div aun no existe en el documento HTML se agrega uno.
		if (!document.getElementById(datePickerDivID)) 
		{
		  //No usa innerHTML para actualizar el body, debido a que esto puede causar que las variables
		  //globales que actualmente estan apuntando a objetos en la pagina tendrian referencias erroneas
		  //document.body.innerHTML += "<div id='" + datePickerDivID + "' class='dpDiv'></div>";
		  var newNode = document.createElement("div");
		  newNode.setAttribute("id", datePickerDivID);
		  newNode.setAttribute("class", "dpDiv");
		  newNode.setAttribute("style", "visibility: hidden;");
		  document.body.appendChild(newNode);
		}
		//Mueve el div datepicker a las cordenadas x,y adecuadas y cambia el visiblity
		var pickerDiv = document.getElementById(datePickerDivID);
		pickerDiv.style.position = "absolute";
		pickerDiv.style.left = x + "px";
		pickerDiv.style.top = y + "px";
		pickerDiv.style.visibility = (pickerDiv.style.visibility == "visible" ? "hidden" : "visible");
		pickerDiv.style.display = (pickerDiv.style.display == "block" ? "none" : "block");
		pickerDiv.style.zIndex = 10000;
		//Dibuja la tabla del datepicker
		refreshDatePicker(targetDateField.name, dt.getFullYear(), dt.getMonth(), dt.getDate());
	}

	/**
	Esta es la funcion que actualmente dibuja el calendario datepicker.
	*/
	function refreshDatePicker(dateFieldName, year, month, day)
	{
		//Si no se pasan argumentos, usa la fecha actual; en otro caso, mes, y año son requeridos
		//(Si un dia es pasado, este sera resaltado luego)
		var thisDay = new Date(); 
		if ((month >= 0) && (year > 0)) 
		{
		  thisDay = new Date(year, month, 1);
		} else {
		  day = thisDay.getDate();
		  thisDay.setDate(1);
		}
		//El calendario sera dibujado como una tabla
		//Se puede personalizar los elementos de la tabla con una hoja de estilos CSS global o 
		//codificando estilos y formatos de elementos a continuacion
		var crlf = "\r\n";
		var TABLE = "<table cols=7 class='dpTable'>" + crlf;
		var xTABLE = "</table>" + crlf;
		var TR = "<tr class='dpTR'>";
		var TR_title = "<tr class='dpTitleTR'>";
		var TR_days = "<tr class='dpDayTR'>";
		var TR_todaybutton = "<tr class='dpTodayButtonTR'>";
		var xTR = "</tr>" + crlf;
		var TD = "<td class='dpTD' onMouseOut='this.className=\"dpTD\";' onMouseOver=' this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
		var TD_title = "<td colspan=5 class='dpTitleTD'>";
		var TD_buttons = "<td class='dpButtonTD'>";
		var TD_todaybutton = "<td colspan=7 class='dpTodayButtonTD'>";
		var TD_days = "<td class='dpDayTD'>";
		var TD_selected = "<td class='dpDayHighlightTD' onMouseOut='this.className=\"dpDayHighlightTD\";' onMouseOver='this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
		var xTD = "</td>" + crlf;
		var DIV_title = "<div class='dpTitleText'>";
		var DIV_selected = "<div class='dpDayHighlight'>";
		var xDIV = "</div>";
		//Inicia la generacion del codigo para la tabla del calendario
		var html = TABLE;
		//Esta es la barra de titulo, la cual muestra el mes y el boton para regresar al mes anterior
		//o para ir al siguiente mes
		html += TR_title;
		html += TD_buttons + getButtonCode(dateFieldName, thisDay, -1, "&lt;") + xTD;
		html += TD_title + DIV_title + monthArrayLong[ thisDay.getMonth()] + " " + thisDay.getFullYear() + xDIV + xTD;
		html += TD_buttons + getButtonCode(dateFieldName, thisDay, 1, "&gt;") + xTD;
		html += xTR;
		//Esta es la fila que indica en que dia de la semana estamos
		html += TR_days;
		for(i = 0; i < dayArrayShort.length; i++)
		  html += TD_days + dayArrayShort[i] + xTD;
		html += xTR;
 		//Ahora se muestra la tabla con los dias del mes
		html += TR;
		//Primero, espacios en blanco
		for (i = 0; i < thisDay.getDay(); i++)
		  html += TD + "&nbsp;" + xTD;
		//Ahora, los dias del mes
		do 
		{
		  dayNum = thisDay.getDate();
		  TD_onclick = " onclick=\"updateDateField('" + dateFieldName + "', '" + getDateString(thisDay) + "');\">";
		  if (dayNum == day)
		    html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD;
		  else
		    html += TD + TD_onclick + dayNum + xTD;
		  //Si este es Sabado, comienza una nueva fila
		  if (thisDay.getDay() == 6)
		    html += xTR + TR;
		  //Incrementa el dia
		  thisDay.setDate(thisDay.getDate() + 1);
		} while (thisDay.getDate() > 1)
		//Llenar de espacios en blanco
		if (thisDay.getDay() > 0) 
		{
		  for (i = 6; i > thisDay.getDay(); i--)
		    html += TD + "&nbsp;" + xTD;
		}
		html += xTR;
		//Agrega un boton para permitir al usuario facilmente escoger el dia de hoy, o cerrar el calendario
		var today = new Date();
		var todayString = "Today is " + dayArrayMed[today.getDay()] + ", " + monthArrayMed[ today.getMonth()] + " " + today.getDate();
		html += TR_todaybutton + TD_todaybutton;
		html += "<button class='dpTodayButton' onClick='refreshDatePicker(\"" + dateFieldName + "\");'>" + thisMonth + "</button> ";
		html += "<button class='dpTodayButton' onClick='updateDateField(\"" + dateFieldName + "\");'>" + closeCalendar + "</button>";
		html += xTD + xTR;
		//Finalmente cierra la tabla
		html += xTABLE;
		document.getElementById(datePickerDivID).innerHTML = html;
		//Agrega un "iFrame shim" que permite mostrar al datepicker por encima de las listas de seleccion
		adjustiFrame();
	}

	/**
	Funcion conveniente para escribir el código de los botones que nos traen de vuelta o hacia adelante de un mes.
	*/
	function getButtonCode(dateFieldName, dateVal, adjust, label)
	{
		var newMonth = (dateVal.getMonth () + adjust) % 12;
		var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
		if (newMonth < 0) 
		{
		  newMonth += 12;
		  newYear += -1;
		}
		return "<button class='dpButton' onClick='refreshDatePicker(\"" + dateFieldName + "\", " + newYear + ", " + newMonth + ");'>" + label + "</button>";
	}

	/**
	Convierte un objeto JavaScript Date a string, basado en las variables dateFormat and dateSeparator
	*/
	function getDateString(dateVal)
	{
		var dayString = "00" + dateVal.getDate();
		var monthString = "00" + (dateVal.getMonth()+1);
		dayString = dayString.substring(dayString.length - 2);
		monthString = monthString.substring(monthString.length - 2);
		switch (dateFormat) 
		{
		  case "dmy" :
		    return dayString + dateSeparator + monthString + dateSeparator + dateVal.getFullYear();
		  case "ymd" :
		    return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString;
		  case "mdy" :
		  default :
		    return monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear();
		}
	}

	/**
	Convierte un string en un objeto JavaScript Date
	*/
	function getFieldDate(dateString)
	{
		var dateVal;
		var dArray;
		var d, m, y;
		try 
		{
		  dArray = splitDateString(dateString);
		  if (dArray) 
		  {
		    switch (dateFormat) 
		    {
		      case "dmy" :
		        d = parseInt(dArray[0], 10);
		        m = parseInt(dArray[1], 10) - 1;
		        y = parseInt(dArray[2], 10);
		        break;
		      case "ymd" :
		        d = parseInt(dArray[2], 10);
		        m = parseInt(dArray[1], 10) - 1;
		        y = parseInt(dArray[0], 10);
		        break;
		      case "mdy" :
		      default :
		        d = parseInt(dArray[1], 10);
		        m = parseInt(dArray[0], 10) - 1;
		        y = parseInt(dArray[2], 10);
		        break;
		    }
		    dateVal = new Date(y, m, d);
		  } 
		  else if (dateString) 
		  {
		    dateVal = new Date(dateString);
		  } 
		  else 
		  {
		    dateVal = new Date();
		  }
		} 
		catch(e) 
		{
		  dateVal = new Date();
		}
		return dateVal;
	}

	/**
	Intenta dividir una cadena de una fecha en un array de elementos, usando separadores de la fecha comunes. 
	Si la fecha está dividida, se devuelve un array, de lo contrario, se regresa falso.
	*/
	function splitDateString(dateString)
	{
		var dArray;
		if (dateString.indexOf("/") >= 0)
		  dArray = dateString.split("/");
		else if (dateString.indexOf(".") >= 0)
		  dArray = dateString.split(".");
		else if (dateString.indexOf("-") >= 0)
		  dArray = dateString.split("-");
		else if (dateString.indexOf("\\") >= 0)
		  dArray = dateString.split("\\");
		else
		  dArray = false;
		return dArray;
	}

	/**
	Actualiza el campo dateFieldName con el valor dateString con el que se ha pasado, y oculta
	el datepicker. En caso de que no se pasa dateString, cierra el datepicker sin cambiar el 
	valor del campo. 
	Además, si el desarrollador de la página ha definido una función llamada datePickerClosed
	en cualquier parte de la página o en una biblioteca importada, vamos a tratar de ejecutar 
	esa función con la actualización del campo como un parámetro. Esto puede ser usado para cosas 
	como validación de datos, configuración de valores por defecto de los campos relacionados, 
	etc. Por ejemplo, puede tener una función como ésta para validar un campo de fecha de inicio:

	function datePickerClosed(dateField)
	{
		var dateObj = getFieldDate(dateField.value);
		var today = new Date();
		today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
		if (dateField.name == "StartDate") 
		{
		  if (dateObj < today) {
		    //Si la fecha es anterior a la actual, alerta al usuario y muestra de nuevo el datepicker
		    alert("Please enter a date that is today or later");
		    dateField.value = "";
		    document.getElementById(datePickerDivID).style.visibility = "visible";
		    adjustiFrame();
		  } 
		  else 
		  {
		    //Si la fecha es correcta, configura el campo EndDate a 7 dias despues de StartDate
		    dateObj.setTime(dateObj.getTime() + (7 * 24 * 60 * 60 * 1000));
		    var endDateField = document.getElementsByName ("EndDate").item(0);
		    endDateField.value = getDateString(dateObj);
		  }
		}
	}
	*/

	function updateDateField(dateFieldName, dateString)
	{
		var targetDateField = document.getElementsByName (dateFieldName).item(0);
		if (dateString)
		  targetDateField.value = dateString;
		var pickerDiv = document.getElementById(datePickerDivID);
		pickerDiv.style.visibility = "hidden";
		pickerDiv.style.display = "none";
		adjustiFrame();
		targetDateField.focus();
		//Despues de cerrar el datepicker, opcionalmente se ejecuta una funcion definida por el usuario llamada
		//datePickerClosed, pasando como parametro el campo que fue actualizado
		//(Notese que esto solo se ejecutara si el usuario actualmente selecciona una fecha del datepicker)
		if ((dateString) && (typeof(datePickerClosed) == "function"))
		  datePickerClosed(targetDateField);
	}

	/**
	Usa un "iFrame shim" para ocuparse de los problemas cuando el datepicker aparece detrás de la lista de 
	selección de elementos, si están por debajo del datepicker. El problema y la solución se describen en:
	http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx
	http://dotnetjunkies.com/WebLog/jking/archive/2003/10/30/2975.aspx
	*/
	function adjustiFrame(pickerDiv, iFrameDiv)
	{
		//Opera no es para algo como esto, asi que si se usa Opera, mejor no lo intente
		var is_opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
		if (is_opera)
		  return;
		//Pone un bloque try/catch alrededor de todo, por si acaso
		try 
		{
		  if (!document.getElementById(iFrameDivID)) 
		  {
		    //No se usa innerHTML para acualizar el body, debido a que puede causar que las variables globales
		    //que actualmente estan apuntando a objetos en la pagina, tengan referencias erroneas
		    //document.body.innerHTML += "<iframe id='" + iFrameDivID + "' src='javascript:false;' scrolling='no' frameborder='0'>";
		    var newNode = document.createElement("iFrame");
		    newNode.setAttribute("id", iFrameDivID);
		    newNode.setAttribute("src", "javascript:false;");
		    newNode.setAttribute("scrolling", "no");
		    newNode.setAttribute ("frameborder", "0");
		    document.body.appendChild(newNode);
		  }
		  if (!pickerDiv)
		    pickerDiv = document.getElementById(datePickerDivID);
		  if (!iFrameDiv)
		    iFrameDiv = document.getElementById(iFrameDivID);
		  try 
		  {
		    iFrameDiv.style.position = "absolute";
		    iFrameDiv.style.width = pickerDiv.offsetWidth;
		    iFrameDiv.style.height = pickerDiv.offsetHeight ;
		    iFrameDiv.style.top = pickerDiv.style.top;
		    iFrameDiv.style.left = pickerDiv.style.left;
		    iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1;
		    iFrameDiv.style.visibility = pickerDiv.style.visibility ;
		    iFrameDiv.style.display = pickerDiv.style.display;
		  } 
		  catch(e) 
		  {
		  }
		}
		catch (ee) 
		{
		} 
	}