function gxdate( SDate, XSFmt)
{
	this.mapCTODFormatToPattern = function(nFormat)
	{
		switch (nFormat)
		{
			case 0:	return "Y4MD";
			case 1:	return "YMD";
			case 2:	return "MDY";
			case 3:	return "DMY";
			case 4:	return "MDY4";
			case 5:	return "DMY4";
			case 6:	return "Y4MD";
		}
		return "Y4MD";
	}

	this.getStringWithFmt = function( sDateFormat)
	{
		var sDate = sDateFormat;
		var sDay = gxrpadwc( this.Value.getDate().toString(), 2, '0');
		var sMonth = gxrpadwc( (this.Value.getMonth() + 1).toString(), 2, '0');
		var sYear = gxrpadwc( this.Value.getFullYear().toString(), 4, '0');
		var Pos = this.FormatPos(sDateFormat);
		sDate = sDate.replace('D', sDay + ((Pos.DPos < 3) ? '/':''));
		sDate = sDate.replace('M', sMonth + ((Pos.MPos < 3) ? '/':''));
		if (sDateFormat.indexOf("Y4") == -1)
		{
			sYear = sYear.slice( 2,4);
			sDate = sDate.replace('Y', sYear + ((Pos.YPos < 3) ? '/':''));
		}
		else
			sDate = sDate.replace('Y4', sYear + ((Pos.YPos < 3) ? '/':''));
		return sDate;		
	}

	this.getString = function()
	{
		if (this.Value - new Date( 0, 0, 0, 0, 0, 0, 0) == 0)
			return '  /  /  ';
		return this.getStringWithFmt( gxdate.SFmt);
	}
	
	this.gxdtoc = function( nDateFormat, sSeparator)
	{
		var sDate = this.getStringWithFmt( this.mapCTODFormatToPattern( nDateFormat));
		return sDate.replace( '/', sSeparator);
	}

	this.getUrlVal = function()
	{
		var sDate = gxdate.SFmt;
		var sDay = gxrpadwc( this.Value.getDate().toString(), 2, '0');
		var sMonth = gxrpadwc( (this.Value.getMonth() + 1).toString(), 2, '0');
		var sYear = gxrpadwc( this.Value.getFullYear().toString(), 4, '0');
		var sHour = this.HasTimePart?gxrpadwc(this.Value.getHours().toString(),2,'0'):'';
		var sMin = 	this.HasTimePart?gxrpadwc(this.Value.getMinutes().toString(),2,'0'):'';
		var sSec = this.HasTimePart?gxrpadwc(this.Value.getSeconds().toString(),2,'0'):'';
		return sYear + sMonth + sDay + sHour + sMin + sSec;
	}
	
	this.FormatPos = function( SFmt)
	{
		if ( SFmt == "ANSI")
		{
			YPos = 3;
			MPos = 2;
			DPos = 1;
		}
		else
		{
			Y4Pos = SFmt.indexOf("Y4");
			YPos = (Y4Pos == -1) ? SFmt.indexOf("Y") + 1 : Y4Pos + 1;
			MPos = SFmt.indexOf("M");
			if (Y4Pos != 0) MPos++;
			DPos = SFmt.indexOf("D");
			if (Y4Pos != 0) DPos++;
		}
		return {YPos:YPos,MPos:MPos,DPos:DPos};
	}		

	this.assign_date = function( DateValue)
	{
		if ( DateValue instanceof gxdate)
			this.Value = DateValue.Value;
		else
			this.Value = DateValue;
	}
	
	this.assign_string = function( SDate, SFmt, IgnoreTime, ThrowExc)
	{
		ANSIDateExp = /([0-9]{1,4})\/?-?([0-9]{1,2})\/?-?([0-9]{2,4})\s?([0-9]{2})?:?([0-9]{2})?:?([0-9]{2})?:?([0-9]{2})?\s?(AM|PM)?/i;
		DateParts = ANSIDateExp.exec(SDate);
		var Pos = this.FormatPos(SFmt);		
		YY = 0;	MM = 0;	DD = 0;	Ho = 0; Mi = 0; Se = 0; Ce = 0;
		try
		{
			if ((Pos.DPos + Pos.MPos + Pos.YPos == 6) && (DateParts != null) && (DateParts.length >= 3))
			{
				if (DateParts[Pos.YPos] != null)
					YY = parseInt( DateParts[Pos.YPos], 10);
				if (isNaN( YY)) throw "InvalidDate";
				if (YY < gxdate.FYearOfCentury)
					YY += 2000;
				else if (YY < 100)
					YY += 1900;
				else if (YY < 1000)
					YY += 1000;
				if (DateParts[Pos.MPos] != null)
					MM = parseInt( DateParts[Pos.MPos],10) - 1;
				if (isNaN( MM) || (MM < 0) || (MM > 11)) throw "InvalidDate";
				if (DateParts[Pos.DPos] != null)
					DD = parseInt( DateParts[Pos.DPos], 10);
				if (isNaN( DD) || (DD < 0) || (DD > monthMaxDays(MM, YY))) throw "InvalidDate";
			}
			this.HasTimePart = false;
			var TimeOffSet = 0;
			if (DateParts == null)
			{
				ANSIDateExp = /([0-9]{2}):?([0-9]{2}):?([0-9]{2})?:?([0-9]{2})?\s?(AM|PM)?/i;
				DateParts = ANSIDateExp.exec(SDate);
				if ( DateParts != null)
				{
					TimeOffSet = 1;
					//Has time part
					this.HasTimePart = true;
				}
			}
			else
			{
				if ( DateParts.length > 3)
				{
					TimeOffSet = 4;
					//Has time part
					this.HasTimePart = true;
				}
			}
			if (this.HasTimePart && !IgnoreTime)
			{
				if (DateParts[TimeOffSet] != null)
					Ho = parseInt( DateParts[TimeOffSet], 10);
				if (isNaN( Ho)) throw "InvalidHour";
				if ((SDate.indexOf("PM") != -1 || SDate.indexOf("pm") != -1) && ( Ho < 12))
					Ho += 12;
				if (DateParts[TimeOffSet + 1] != null)
					Mi = parseInt( DateParts[TimeOffSet + 1], 10);
				if (isNaN( Mi)) Mi = 0;
				if (DateParts[TimeOffSet + 2] != null)
					Se = parseInt( DateParts[TimeOffSet + 2], 10);
				if (isNaN( Se)) Se = 0;
				if (DateParts[TimeOffSet + 3] != null)
					Ce = parseInt( DateParts[TimeOffSet + 3], 10);
				if (isNaN( Ce)) Ce = 0;
			}
		}
		catch (E)
		{
			if (ThrowExc)
			{
				throw E;
			}
			else
			{
				if (E == "InvalidDate")
				{
					YY = 0;	MM = 0;	DD = 0;	Ho = 0; Mi = 0; Se = 0; Ce = 0;
				}
				if (E == "InvalidHour")
				{
					Ho = 0; Mi = 0; Se = 0; Ce = 0;
				}
			}
		}
		this.Value = new Date(YY, MM, DD, Ho, Mi, Se, Ce);
	}

	this.compare = function( DateValue)
	{
		if ( typeof(DateValue) == "string")
			return this.compare_string( DateValue);
		return this.compare_date( DateValue);
	}

	this.compare_string = function( SDate)
	{
		DateValue = new gxdate( SDate);
		return this.compare_date( DateValue.Value);
	}
	
	this.compare_date = function( DateValue)
	{
		var Val;
		if ( DateValue instanceof gxdate)
			Val = DateValue.Value;
		else
			Val = DateValue;
		return this.Value - Val;
	}
	
	var SFmt = XSFmt || gxdate.SFmt;
	if ( typeof(SDate) == "string")
		this.assign_string( SDate, SFmt);
	else
		this.assign_date( SDate);		
	var FYearOfCentury = gxdate.FYearOfCentury || 40;
}

function gxnow()
{
	return new Date();
}

function gxlength( String)
{
	return String.length;	
}

function gxtoupper( String)
{
	return String.toUpperCase();	
}

function gxtolower( String)
{
	return String.toLowerCase();	
}

function gxtoday()
{
	day = new gxdate('');
	day.assign_date(new Date());
	return day;
}

function gxctot(SDate, SFmt)
{
	return new gxdate(SDate, SFmt);
}

function gxctod(SDate, SFmt)
{
	day = new gxdate(SDate, SFmt);
	day.Value.setHours( 0, 0, 0, 0);
	return day;
}

function gxymdtod( Y, M, D)
{
	day = new gxdate(D + '/' + M + '/' + Y, 'ANSI');
	day.Value.setHours( 0, 0, 0, 0);
	return day;
}

function gxymdhmstot( Y, M, D, H, Mi, S)
{
	day = new gxdate(D + '/' + M + '/' + Y + ' ' + H + ':' + Mi + ':' + S, 'ANSI');
	return day;
}


function gxgethour(SDate)
{
	return (new gxdate(SDate)).Value.getHours();
}

function gxgetminute(SDate)
{
	return (new gxdate(SDate)).Value.getMinutes();
}

function gxgetsecond(SDate)
{
	return (new gxdate(SDate)).Value.getSeconds();
}

function gxgetday(SDate)
{
	return (new gxdate(SDate)).Value.getDate();	
}

function gxgetmonth(SDate)
{
	return (new gxdate(SDate)).Value.getMonth() + 1;	
}

function gxgetyear(SDate)
{
	return (new gxdate(SDate)).Value.getFullYear();	
}

function gxsetDateFormat( SFmt)
{
	gxdate.SFmt = new String(SFmt);
}

function gxsetFirstYearCentury( FYear)
{
	gxdate.FYearOfCentury = FYear;
}

function gxparseFloat( S, ThSep, DecPoint)
{
	if ( typeof(S) == "number")
		return S;	
	var N = S.replace( ThSep, '');
	N = N.replace( DecPoint, '.');
	return parseFloat( N);	
}

function gxInvalidFunc(StringCode)
{
	throw "gxInvalidFunc: " + StringCode;	
}


function gxrpadwc( val, len, padc)
{
	var xlen = val.length;
	var diff = len - xlen;
	if (diff < 1)
		return val;
	var xval='';
	for (var i=0;i<diff;i++)
		xval += padc;
	xval += val;
	return xval;
}

function gxDateAddDays( sdate, inc)
{
	return gxDateAddMill( sdate, gxDaytoMillisec( inc));
}


function gxDateAddSec( sdate, inc)
{
	return gxDateAddMill( sdate, gxSectoMillisec( inc));
}

function gxDateAddMill( sdate, inc)
{
	var xdate = gxdateparm( sdate);
	date = xdate.Value;
	var mill = date.getMilliseconds();
	date.setMilliseconds( mill + inc);
	return xdate.getString();
}


function gxDateSecDiff( date1, date2)
{
	var val = gxMillisecToSec( gxDateMilliDiff( date1, date2));
	return val;
}

function gxDateDaysDiff( date1, date2)
{
	var val = gxMillisecToDay( gxDateMilliDiff( date1, date2));
	return val;
}

function gxDateMilliDiff( date1, date2)
{
	var xdate1 = gxdateparm( date1);
	var xdate2 = gxdateparm( date2);
	var date1 = xdate1.Value.valueOf();
	var date2 = xdate2.Value.valueOf();
	return date1 - date2;
}

function gxDaytoMillisec( Days)
{
	return Days * 24 * 60 * 60 * 1000;
}

function gxSectoMillisec( Sec)
{
	return Sec * 1000;
}

function gxMillisecToDay( Mill)
{
	return Mill / 24 /60 / 60 / 1000;
}

function gxMillisecToSec( Mill)
{
	return Mill / 1000;
}

function gxdateparm( sdate)
{
	if ( typeof(sdate) == "string")
		return new gxdate( sdate);
	return sdate;	
}

function gxurlvaluedate( Control, sFmt)
{
	var value = typeof( Control) == 'string' ? Control:Control.value;
	var date = new gxdate( value, sFmt);
	return date.Value.getFullYear().toString() 
			+ gxrpadwc((date.Value.getMonth() + 1).toString(),2,'0') 
			+ gxrpadwc(date.Value.getDate().toString(),2,'0');
}

function gxurlvaluedatetime( Control, sFmt)
{
	var value = typeof( Control) == 'string' ? Control:Control.value;
	var date = new gxdate( value, sFmt);
	return 	date.Value.getFullYear().toString() + 
			gxrpadwc((date.Value.getMonth() + 1).toString(),2,'0') + 
			gxrpadwc(date.Value.getDate().toString(),2,'0') +
			gxrpadwc(date.Value.getHours().toString(),2,'0') +
			gxrpadwc(date.Value.getMinutes().toString(),2,'0') +
			gxrpadwc(date.Value.getSeconds().toString(),2,'0');
}

function gxurlvaluedecimal( Control, ThSep, DecPoint)
{
	var value = typeof( Control) == 'string' ? Control:Control.value;
	value = gxparseFloat( value, ThSep, DecPoint);
	return value.toString();
}

function gxdtoc( SDate, nDateFormat, sSeparator)
{
	var Date = new gxdate( SDate);
	return Date.gxdtoc( nDateFormat, sSeparator);
}

function gxurlvalue( Control)
{
	return encodeURIComponent( typeof( Control) == 'string' ? Control:Control.value);
}

function gxltrim( str)
{
	return str.replace(/^ */, '');
}

function gxrtrim( str)
{
	return str.replace(/ *$/, '');
}

function gxtrim( str)
{
	return 	gxrtrim( gxltrim(str));
}

function gxstr( num)
{
	return num.toString();
}

function gxsubstr( str, from, len)
{
	str.toString().substring( from - 1, from - 1 + len);
}

function rgb( r, g, b)
{
	return gxrgb( r,g,b);
}

function gxrgb( r, g, b)
{
	return (r * 256 * 256) + g * 256 + b;
}
