
	if(Object.isUndefined(SWZ)){
		var SWZ = {};
	}
	
	
	SWZ.DateTime = {};
	
	
	//SWZ.DateTime.Base
	SWZ.DateTime.Base = Class.create({
		initialize:function(options){
			this.options = {
				daysOfTheWeekS	: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
				daysOfTheWeekL	: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
				monthNamesS		: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
				monthNamesL		: ['January','February','March','April','May','June','July','August','September','October','November','December'],
				ordinal			: ['','st','nd','rd','th','th','th','th','th','th','th','th','th','th','th','th','th','th','th','th','th','st','nd','rd','th','th','th','th','th','th','th','st'],
				base			: 'swz'
			};			
			Object.extend(this.options,options || {});
		},
		
		sqlToJSDate:function(date){

			//get the component parts
			sqlDate		= String(date);
			sqlYear		= Number(sqlDate.substring(0,4));
			sqlMonth	= Number(sqlDate.substring(5,7));
			sqlDay		= Number(sqlDate.substring(8,10));
			
			//create the js date object
			js_Date = new Date();
			js_Date.setFullYear(sqlYear,sqlMonth-1,sqlDay);
	
			//return the date
			return js_Date
		},
		
		format:function(datetime,format){
			
			//	'FORMAT TYPES
			var ft = {};
			ft.a = (datetime.getHours() < 12) ? String('am') : String('pm');																//am or pm
			ft.A = (datetime.getHours() < 12) ? String('AM') : String('PM');																//AM or PM
			ft.d = (String(datetime.getDate()).length < 2) ? '0' + String(datetime.getDate()) : String(datetime.getDate());					//Day of the month with a leading zero (01-31)
			ft.D = String(this.options.daysOfTheWeekS[datetime.getDay()]);																	//Three characters that represents the day of the week (Mon-Sun)
			ft.F = String(this.options.monthNamesL[datetime.getMonth()]);																	//Full month name
			ft.g = (Number(datetime.getHours()) > 12) ? String(datetime.getHours() - 12) : String(datetime.getHours());						//The hour in 12-hour format without a leading zero (1-12)
			ft.G = String(datetime.getHours());																								//The hour in 24-hour format without a leading zero (0-23)
			ft.h = (String(ft.g).length < 2) ? '0' + String(ft.g) : String(ft.g);															//The hour in 12-hour format with a leading zero (01-12)
			ft.H = (String(ft.G).length < 2) ? '0' + String(ft.G) : String(ft.G);															//The hour in 24-hour format with a leading zero (00-23)
			ft.i = (String(datetime.getMinutes()).length < 2) ? '0' + String(datetime.getMinutes()) : String(datetime.getMinutes());		//The minutes with a leading zero (00-59)
			ft.j = String(datetime.getDate());																								//Day of the month without a leading zero (1-31)
			ft.l = String(this.options.daysOfTheWeekL[datetime.getDay()]);																	//The full name of the day (Monday-Sunday)
			//L = 																															//1 if the year is a leap year, otherwise 0
			ft.m = (String(datetime.getMonth() + 1).length < 2) ? '0' + String(datetime.getMonth() + 1) : String(datetime.getMonth() + 1); 	//The month as a number, with a leading zero (01-12)
			ft.M = String(this.options.monthNamesS[datetime.getMonth()]);																	//Abbreviated month name
			ft.n = String(datetime.getMonth() + 1);																							//The month as a number without a leading zero (1-12)
			ft.s = (String(datetime.getSeconds()).length < 2) ? '0' + String(datetime.getSeconds()) : String(datetime.getSeconds());		//The seconds with a leading zero (00-59)
			ft.S = String(this.options.ordinal[datetime.getDate()]);																		//The English ordinal suffix for the day of the month (st, nd, rd or th)
			ft.t = String(new Date(datetime.getUTCFullYear(),datetime.getMonth()+1,0).getDate());													//The number of days in the given month (28-31)
			ft.w = String(datetime.getDay());																								//The day of the week as a number (0-6, 0=Sunday)
			//W = 																															//ISO-8601 week number of year, weeks starting on Monday
			ft.Y = String(datetime.getUTCFullYear());																						//The year as a 4-digit number (e.g. 2003)	
			ft.y = String(datetime.getUTCFullYear()).substring(2);																					//The year as a 2-digit number (e.g. 03)
			//z = 																															//The day of the year as a number (0-365)

														
			
			//Shortcuts
			ft.Q = ft.Y + '-' + ft.m + '-' + ft.d;
			ft.q = ft.H + '-' + ft.i + '-' + ft.s;
																												
			output = '';
			arr = format.toArray();
			arr.each(function(item){
				if(!Object.isUndefined($H(ft).get(item))){
					output += $H(ft).get(item)
				} else {
					output += item;
				}
			});

			return output			
		}

	})
	
	//SWZ.DateTime.Calendar
	SWZ.DateTime.Calendar = Class.create(SWZ.DateTime.Base,{
	
		//initialize($super,options)
		initialize:function($super,options){
		
			//create the options object
			this.options = {
				id				: '',
				initialDate		: '',
				startYear		: '',
				endYear			: '',
				yearsEitherSide : 5,
				yearRangeFixed	: false,
				shortcuts		: ['Today','Reset','Clear','Close'],
				earliestDate	: null,
				latestDate		: null,
				base			: 'swz',
				skin			: 'blue'
			}
			//extend with the options passed
			Object.extend(this.options,options || '');
			
			//append them to the superclass (swzDateTime.Base) options
			$super(this.options)
			
			//set it all up!
			this.setup();			
		},
		
		//setup:function()
		setup:function(){
			
			//check for a css file
			if(this.options.skin != ''){
			
				src = this.options.base + '/swz-datetime/skins/' + this.options.skin + '/swz-datetime.css';
			
				css = Builder.node('link',{href : src,type : 'text/css',rel : 'stylesheet'},'');
				$$('head')[0].appendChild(css);
			}
		
			//we need to get a date value to start
			//use the initial date if there is one, if not, create
			//a new date object and reset after we have the month and year.
			//in the same format to begin with.
			if(this.options.initialDate == ''){
				date = new Date();
			} else {
				date = new Date(this.options.initialDate.getUTCFullYear(),this.options.initialDate.getMonth(),this.options.initialDate.getDate());
			}
			
			/*** CONTROLS ***/
			controls = this.createControls(date);
			
			/*** DISPLAY ***/
			display = this.createDisplay();
			
			/*** SHORTCUTS ***/
			shortcuts = this.createShortcuts();

			/*** WRAPPER ***/
			wrapper = Builder.node('div',{className : 'wrapper'},[controls,display,shortcuts]);
			this.wrapper = wrapper;
			
			/*** CALENDAR ***/
			this.calendar = Builder.node('div',{className : 'calendar'},wrapper);

			/*** ADD ALL THE LISTENERS ***/
			this.addListeners();

			/*** APPEND TO THE BODY ***/
			this.addCalendar(this.calendar);

			//set the month and the year
			month.value = date.getMonth();
			year.value 	= date.getUTCFullYear();
			
			//set the date object to null, or to an actual date
			if(this.options.initialDate == ''){
				date = null;
			}

			//function to set the calendar!
			this.set(date);
			
		},
		
		//addCalendar(cal);
		addCalendar:function(cal){
			if($(this.options.id)){			
				$(this.options.id).appendChild(cal);
			} 
		},
		
		//addListeners();
		addListeners:function(){
		
			obj = this;
			this.arrDays.each(function(item,index){
				$(item).observe('mouseover',obj.mouseover.bind(obj,item));
				$(item).observe('mouseout',obj.mouseout.bind(obj,item));
				$(item).observe('click',obj.setDayUsingObj.bindAsEventListener(obj,item));
			});		
			
			$(previous).observe('click',this.changeMonth.bindAsEventListener(this,-1));
			$(month).observe('change',this.changeMonth.bindAsEventListener(this,0));
			$(year).observe('change',this.changeYear.bindAsEventListener(this,0));			
			$(next).observe('click',this.changeMonth.bindAsEventListener(this,1));
			
		},
				
		//changeYear(obj,amt);
		changeYear:function(obj,amt){
		
			month 	= $(this.month);
			year	= $(this.year);

			//check if we should change the years available
			if(this.options.yearRangeFixed == false){

				//get the currently selected value
				sel = year;
				val = sel.value;
			
				//get the last year to show
				endYear		= Number(val) + this.options.yearsEitherSide;
				for(i=0;i<sel.options.length;i++){
					sel.options[i].text = Number(endYear) - i
					sel.options[i].value = Number(endYear) - i
				}
				
				//select the year requested
				sel.selectedIndex = this.options.yearsEitherSide;
			}

			//display the calendar!
			this.displayCalendar(year.value,month.value);	
		
		},
		
		//changeMonth(obj,amt);
		changeMonth:function(obj,amt){
				
			month 	= $(this.month);
			year	= $(this.year);

			if(month.value == 0 && amt == -1){
			
				if(this.options.yearRangeFixed == true && year.selectedIndex ==0){
					alert('Sorry, we cannot go back further than this month. ');
				} else {
					year.value = Number(year.value) - 1;
					month.value = 11;
				}
				this.changeYear(this,0);
			} else if(month.value == 11 && amt == 1){
				if(this.options.yearRangeFixed == true && year.selectedIndex == (year.options.length-1)){
					alert('Sorry, we cannot go forward further than this month. ');
				} else {
					year.value = Number(year.value) + 1;
					month.value = 0;
				}
				this.changeYear(this,0);
			} else {
				month.value = Number(month.value) + amt;
			
				//display the calendar!
				this.displayCalendar(year.value,month.value);		
			}
		},
		
		//mouseover(obj);
		mouseover:function(obj){
			className = String(obj.className).replace(/Over/,'');
			className = className + 'Over';
			obj.className = className;
		},
		
		//mouseout(obj);
		mouseout:function(obj){
			className = String(obj.className).replace(/Over/,'');
			obj.className = className;		
		},
		
		//set()
		set:function(thisdate){
		
			//set this date!
			if(thisdate == null){
			
				//make sure the date is null
				date = null;
				
				//create a temp date with the month and year
				temp = new Date()
				
				//set the calendar to the temp date month and year
				this.displayCalendar(temp.getUTCFullYear(),temp.getMonth());			
				
				this.setDayUsingObj(this,null);
				
			} else {
				//pass the date
				date = thisdate;

				//set the calendar to the correct year and month!
				this.displayCalendar(date.getUTCFullYear(),date.getMonth());
				
				//figure out what arrDay object holds the correct day...
				startDay 	= new Date(date.getUTCFullYear(),date.getMonth(),1).getDay();
				daysInMonth = new Date(date.getUTCFullYear(),date.getMonth() + 1,0).getDate();
				
				//find the object
				for(i = startDay; i < daysInMonth + startDay; i++){				
					if(Number(arrDays[i].innerHTML) == date.getDate()){				
						obj = arrDays[i];
					}
				}
				
				//set the date
				this.setDayUsingObj(this,obj);
			}
				
		},
		
		//setDayUsingObj(a,obj);
		setDayUsingObj:function(a,obj){
		
			month = $(this.month);
			year = $(this.year);
			
			if(obj != null){
			
				//create the month adjustment
				cn = String(obj.className)
				if(cn.indexOf('previous') >= 0){
					monthAdjust = -1;
				} else if(cn.indexOf('next') >= 0){
					monthAdjust = 1;
				} else {
					monthAdjust = 0;
				}
			
				if(this.options.yearRangeFixed == true && month.value == 0 && year.selectedIndex == 0 && monthAdjust < 0){
					alert('Sorry, we cannot go back further than this month. ');
				} else if(this.options.yearRangeFixed == true && month.value == 11 && year.selectedIndex == (year.options.length -1) && monthAdjust > 0){
					alert('Sorry, we cannot go forward further than this month. ');	
				} else {
					
					//reset donotsetdate
					donotsetdate = false;
				
					//check we're not going before the earliest date
					if(this.options.earliestDate != null){
						if(new Date(year.value,Number(month.value) + monthAdjust,obj.innerHTML) < this.options.earliestDate){
							alert('The earliest date you can select is ' + this.format(this.options.earliestDate,'l jS F Y') + '.    \n\nPlease select another date.  ');
							donotsetdate = true;
						}
					}			
					
					//check we're not going past the latest date
					if(this.options.latestDate != null){
						if(new Date(year.value,Number(month.value) + monthAdjust,obj.innerHTML) > this.options.latestDate){
							alert('The latest date you can select is ' + this.format(this.options.latestDate,'l jS F Y') + '.    \n\nPlease select another date.  ');
							donotsetdate = true;
						}
					}		
					
					//check we can still set the date
					if(donotsetdate == false){	
					
						//make the date object!
						if(date == null){
							date = new Date(year.value,Number(month.value) + monthAdjust,obj.innerHTML);
						} else {
							date.setFullYear(year.value);
							date.setMonth(Number(month.value) + monthAdjust);
							date.setDate(Number(obj.innerHTML));
						}
						
						this.date = date;
						
						this.displayCalendar(date.getUTCFullYear(),date.getMonth());			
					}
				}
			}
		},
		
		//displayCalendar(y,m);
		displayCalendar:function(y,m){
		
			month = $(this.month);
			year = $(this.year);
		
			month.value = m;
			year.value 	= y;

			//set today as a new date object
			today				= new Date();
			
			//create this month based on the year and month
			thisMonth			= new Date(y,m,1);
			startDay 			= thisMonth.getDay();			
			daysInThisMonth		= new Date(y,Number(m)+1,0).getDate();
			
			//create the previous month
			previousMonth		= new Date(y,Number(m)-1,1);			
			daysInPreviousMonth = new Date(y,m,0).getDate();			

			//create the next month
			nextMonth			= new Date(y,Number(m)+1,1);
			
			//go through arrDays and set the innerHTML and the className
			thisObj = this
			$R(0,41).each(function(item){
				//the div holding the number
				obj = $(thisObj.arrDays[item]);
				
				//the day value for the div
				val = Number(item - startDay) + 1;
				
				//set the values for the days
				if(val <= 0){
				
					//set the value of the div
					obj.innerHTML = daysInPreviousMonth + val;
					
					//check for today
					if(today.getUTCFullYear() == previousMonth.getUTCFullYear() && today.getMonth() == previousMonth.getMonth() && today.getDate() == val){
						obj.className = 'day previousToday';				
					} else {					
						obj.className = 'day previousMonth';
					}
					
					//check if this is the selected day
					if(date != null){
						if(date.getUTCFullYear() == previousMonth.getUTCFullYear() && date.getMonth() == previousMonth.getMonth() && date.getDate() == Number(obj.innerHTML)){
							obj.className += 'X'
						}
					}
					
				} else if(val > daysInThisMonth){
				
					//set the value of the div
					obj.innerHTML = val - daysInThisMonth;

					//check for today
					if(today.getUTCFullYear() == nextMonth.getUTCFullYear() && today.getMonth() == nextMonth.getMonth() && today.getDate() == val){
						obj.className = 'day nextToday';				
					} else {					
						obj.className = 'day nextMonth';
					}
					
					//check if this is the selected day
					if(date != null){
						if(date.getUTCFullYear() == nextMonth.getUTCFullYear() && date.getMonth() == nextMonth.getMonth() && date.getDate() == (val - daysInThisMonth)){
							obj.className += 'X'
						}
					}

				} else {

					//set the value of the div
					obj.innerHTML = val;

					//check for today
					if(today.getUTCFullYear() == thisMonth.getUTCFullYear() && today.getMonth() == thisMonth.getMonth() && today.getDate() == val){
						obj.className = 'day thisToday';				
					} else {					
						obj.className = 'day thisMonth';
					}
					
					//check if this is the selected day
					if(date != null){
						if(date.getUTCFullYear() == thisMonth.getUTCFullYear() && date.getMonth() == thisMonth.getMonth() && date.getDate() == val){
							obj.className += 'X'
						}
					}
						
				}
			});
			
		},

		//createShortcuts();
		createShortcuts:function(){

			//create the object to return
			obj = Builder.node('div',{className : 'shortcuts'},'');
			
			//create a new array for the objects

			arrShortcuts = new Array();
			
			for(i=0;i<this.options.shortcuts.length;i++){
			
				arrShortcuts[i] = Builder.node('div',{className : 'shortcut'},this.options.shortcuts[i]);			
				obj.appendChild(arrShortcuts[i]);			
			}
						
			//return the object
			return obj
		},
		
		//createDisplay();
		createDisplay:function(){
		
		
			//create the header boxes
			dayNames = Builder.node('div',{className : 'dayNames'},'');
			arrDayNames = this.options.daysOfTheWeekS
			$R(0,6).each(function(item){
				dayNames.appendChild(	Builder.node('div',{className : 'day'},arrDayNames[item])	);
			});
			
			//create the diary days
			allDays = Builder.node('div',{className : 'allDays'},'');
			arrDays = new Array();
			$R(0,41).each(function(item){
				arrDays[item] = Builder.node('div',{className : 'day'},'');
				allDays.appendChild(arrDays[item]);
			});
			this.arrDays = arrDays;
						
			//create the object to return
			obj = Builder.node('div',{className : 'display'},[dayNames,allDays]);
			
			//return the object
			return obj
		},
		
		//createControls(date);
		createControls:function(date){
			//create the previous button
			previous = this.createPreviousButton();			

			//create the month select
			month = this.createMonthSelect(date.getUTCMonth());
			this.month = month
			
			//create the year select
			year = this.createYearSelect(date.getUTCFullYear());
			this.year = year
			
			//create monthyear holder
			monthyear = Builder.node('div',{className : 'monthyear'},[month,year]);			
			
			//create the next button
			next = this.createNextButton();
		
			//create the controls object
			obj = Builder.node('div',{className : 'controls'},[previous,monthyear,next]);
						
			//return the object
			return obj;
		},
		
		//createYearSelect(val);
		createYearSelect:function(val){
			
			//create the object
			obj = Builder.node('select',{className : 'year'},'');
			
			//get start and end!
			start 	= this.options.startYear;
			end		= this.options.endYear;
			
			//check we now have a start and end
			if(start == '' || end == ''){
				//set to this year - & + yearsEitherSide
				start = val - this.options.yearsEitherSide;
				end   = val + this.options.yearsEitherSide;
				
				//reset the start and end years
				this.options.startYear = start;
				this.options.endYear = end;
			}
			
			//create the options
			$R(start,end).each(function(item,index){
				obj.appendChild(	Builder.node('option',{value : item},item)	);
			});
			
			//return the object
			return obj		
		},
		
		
		//createMonthSelect();
		createMonthSelect:function(){
		
			//create the select
			obj = Builder.node('select',{className : 'month'},'');
			
			//add all the options
			arrMonths = this.options.monthNamesL;
			$R(0,11).each(function(item){
				obj.appendChild(	Builder.node('option',{value : item},arrMonths[item])	);
			});
			
			//return the object
			return obj
		},

		
		//createNextButton();
		createNextButton:function(){
		
			//create the object
			obj = Builder.node('div',{className : 'next'},'>');
			
			//return the object
			return obj
		},
		
		
		//createPreviousButton();
		createPreviousButton:function(){
		
			//create the object
			obj = Builder.node('div',{className : 'previous'},'<');
			
			//return the object
			return obj
		}
		
	});	
	
	
	
	SWZ.DateTime.SlideCal = Class.create(SWZ.DateTime.Calendar,{
	
		//initialize($super,options)
		initialize:function($super,options){

			this.options = {
				displayElement 	: '',
				displayFormat 	: 'l jS F Y',
				displayDefault	: '',
				hiddenElement	: '',
				hiddenFormat	: '',
				hiddenDefault	: '',
				offsetLeft		: -5,
				offsetTop		: -1,
				shortcuts		: ['Today','Reset','Clear','Close'],
				toggleCount		: 0
			};
			//extend with the options passed
			Object.extend(this.options,options || '');
			
			//check there's at least a display element
			if(this.options.displayElement == ''){
				alert('You must set the value for displayElement');
			} else {
				//append them to the superclass (swzDateTime.Base) options
				$super(this.options)
			}
		},
		
		//setup()
		setup:function($super){
			//call the setup from calendar
			$super();
		},
		
		//addCalendar(cal)
		addCalendar:function(cal){
						
			//INLINE - insert into the document
			new Insertion.After($(this.options.displayElement),$(cal).hide());
			
			//set the position of the calendar
			//to the top left of the display element
			$(cal).setStyle({
				position : 'absolute',
				top		 : ($(this.options.displayElement).cumulativeOffset().top + $(this.options.displayElement).getDimensions().height + this.options.offsetTop) + 'px',
				left	 : ($(this.options.displayElement).cumulativeOffset().left + this.options.offsetLeft) + 'px'
			});
			
		},
		
		//addListeners($super)
		addListeners:function($super){
			
			//call the superclass function first...
			$super()
		
			//create a var for the display element
			displayElement = $(this.options.displayElement);
			
			//check if it's an input or a div
			if(String(displayElement.nodeName).toUpperCase() == 'INPUT'){
				displayElement.observe('focus',this.toggleCalendar.bindAsEventListener(this));	
			} else {
				displayElement.observe('click',this.toggleCalendar.bindAsEventListener(this));	
			}
			
			//add a listener for the shortcut
			$(arrShortcuts[0]).observe('click',this.scToday.bindAsEventListener(this));
			$(arrShortcuts[1]).observe('click',this.scReset.bindAsEventListener(this));
			$(arrShortcuts[2]).observe('click',this.scClear.bindAsEventListener(this));			
			$(arrShortcuts[3]).observe('click',this.scClose.bindAsEventListener(this));			

		},
		
		//scToday:function(){
		scToday:function(){
			this.set(new Date());
		},
		
		//scReset:function(){
		scReset:function(){
		
			if(this.options.initialDate == ''){		
				this.set(null);
			} else {
				this.set(this.options.initialDate);
			}
		},
		
		//scClear:function(){
		scClear:function(){
			this.set(null);
		},
		
		//scClose:function(){
		scClose:function(){
			Effect.toggle(this.calendar,'slide',{});
		},
		
		//toggleCalendar()
		toggleCalendar:function(){
			if(this.options.toggleCount > 0){
				Effect.toggle(this.calendar,'slide',{});
			}			
			this.options.toggleCount++;
		},		
		
		//setDayUsingObj($super,a,obj)
		setDayUsingObj:function($super,a,obj){
		
			//call the superclass function first...
			$super(a,obj)
				
			//create a var for the display element
			displayElement  = $(this.options.displayElement);
			hiddenElement	= $(this.options.hiddenElement);
						
			//check if it's an input or a div
			if(date == null){
				if(String(displayElement.nodeName).toUpperCase() == 'INPUT'){
					displayElement.value = this.options.displayDefault
				} else {
					displayElement.innerHTML = this.options.displayDefault
				}	
				
				if(hiddenElement){				
					if(String(hiddenElement.nodeName).toUpperCase() == 'INPUT'){
						hiddenElement.value = this.options.hiddenDefault
					} else {
						hiddenElement.innerHTML = this.options.hiddenDefault
					}		
				}
			
			} else {
				if(String(displayElement.nodeName).toUpperCase() == 'INPUT'){
					displayElement.value = this.format(this.date,this.options.displayFormat);
				} else {
					displayElement.innerHTML = this.format(this.date,this.options.displayFormat);
				}	
				
				if(hiddenElement){				
					if(String(hiddenElement.nodeName).toUpperCase() == 'INPUT'){
						hiddenElement.value = this.format(this.date,this.options.hiddenFormat);
					} else {
						hiddenElement.innerHTML = this.format(this.date,this.options.hiddenFormat);
					}		
				}
			} 		
			
			//show the calendar
			this.toggleCalendar();
		},
		
		//open()
		show:function(){
			if(this.calendar.style.display == 'none'){		
				Effect.SlideDown(this.calendar,{});
			}
		},
		
		
		//hide()
		hide:function(){
			if(this.calendar.style.display != 'none'){		
				Effect.SlideUp(this.calendar,{});
			}
		}
		
	});
