var containerDivID;
var marketContainerdivID;
var titleContainerdivID;
var timeZoneContainerdivID;
var timeZoneOffset = new Date().getTimezoneOffset();
var get_holidays_path = "/cgi/wl/fxmarkethours/get_market_holidays.pl";
var timerHandle;
var h_margin;
var v_margin;
var display_GMToffset = 2*60; 

//-----------------------------------------------
var marketArray = new Array(
		new Hash({
			"id":"sydney",
			"title": "Sydney",

			"GMTopenTime" : 22*60+0,
			"GMTcloseTime" : 7*60+0,
			"timeZoneOffset" : -10*60,
			"observeDST" : 1,
			"currencyName" : "AUD",
			"holidays" : "",

			"isHoliday": false,
			"status":"Opens in 3h 23m"
		}),
		new Hash({
			"id":"tokyo",
			"title": "Tokyo",

			"GMTopenTime" : 0*60+0,
			"GMTcloseTime" : 9*60+0,
			"timeZoneOffset" : -9*60,
			"observeDST" : 0,
			"currencyName" : "JPY",
			"holidays" : "",

			"isHoliday": false,
			"status":"Closes in 1h 26m"
		}),
		new Hash({
			"id":"london",
			"title": "London",

			"GMTopenTime" : 8*60+0,
			"GMTcloseTime" : 17*60+0,
			"timeZoneOffset" : 0,
			"observeDST" : 1,
			"currencyName" : "GBP",
			"holidays" : "",

			"isHoliday": false,
			"status":"Opens in 23h"
		}),
		new Hash({
			"id":"new_york",
			"title": "New York",

			"GMTopenTime" : 13*60+0,
			"GMTcloseTime" : 22*60+0,
			"timeZoneOffset" : 5*60,
			"observeDST" : 2,
			"currencyName" : "USD",
			"holidays" : "",

			"isHoliday": false,
			"status":"Opens 12am Dec 12"
		})
);
	
var timeZoneArray = new Array (
		new TimeZone(10*60, "Hawaii-Aleutian Standard Time", "(GMT-10) HST"),
		new TimeZone( 9*60, "Alaska Standard Time, Hawaii-Aleutian Daylight Time", "(GMT-9) AKST,HADT"),
		new TimeZone( 8*60, "Pacific Standard Time, Alaska Daylight Time", "(GMT-8) PST,AKDT"),
		new TimeZone( 7*60, "Mountain Standard Time, Pacific Daylight Time", "(GMT-7) MST,PDT"),
		new TimeZone( 6*60, "Central Standard Time, Mountain Daylight Time", "(GMT-6) CST,MDT"),
		new TimeZone( 5*60, "Eastern Standard Time, Central Daylight Time", "(GMT-5) EST,CDT"),
		new TimeZone( 4*60, "Atlantic Standard Time, Eastern Daylight Time", "(GMT-4) AST,EDT"),
		new TimeZone( 3*60+30, "Newfoundland Standard Time", "(GMT-3:30) NST"),
		new TimeZone( 3*60, "Atlantic Daylight Time", "(GMT-3) ADT"),
		new TimeZone( 2*60+30, "Newfoundland Daylight Time", "(GMT-2:30) NDT"),
		new TimeZone( 2*60, "", "(GMT-2)"),
		new TimeZone( 1*60, "", "(GMT-1)"),
		new TimeZone( 0, "Greenwich Mean Time, Western European Time", "GMT,WET"),
		new TimeZone(-1*60, "British Summer Time, Central European Time, Western European Daylight Time", "(GMT+1) BST,CET,WEDT"),
		new TimeZone(-2*60, "Eastern European/South African Standard Time, Central European Daylight Time",
				"(GMT+2) EET,SAST,CEDT"),
		new TimeZone(-3*60, "Moscow Time, Eastern European Daylight Time", "(GMT+3) MSK,EEDT"),
		new TimeZone(-4*60, "", "(GMT+4)"),
		new TimeZone(-5*60, "", "(GMT+5)"),
		new TimeZone(-(5*60+30), "Indian Standard Time", "(GMT+5:30) IST"),
		new TimeZone(-6*60, "", "(GMT+6)"),
		new TimeZone(-7*60, "Christmas Island Time", "(GMT+7) CXT"),
		new TimeZone(-8*60, "Singapore/Hong Kong/Chinese/Australian Western Standard Time", "(GMT+8) SGT,HKT,AWST"),
		new TimeZone(-9*60, "Japan/Korea Standard Time", "(GMT+9) JST,KST"),
		new TimeZone(-(9*60+30), "Australian Central Standard Time", "(GMT+9:30) ACST"),
		new TimeZone(-10*60, "Australian Eastern Standard Time", "(GMT+10) AEST"),
		new TimeZone(-(10*60+30), "Australian Central Daylight Time", "(GMT+10:30) ACDT"),
		new TimeZone(-11*60,"Australian Eastern Daylight Time", "(GMT+11) AEDT"),
		new TimeZone(-12*60, "New Zealand Standard Time", "(GMT+12) NZST")
);

//-----------------------------------------------
function TimeZone(offset,title,text) {
  this.offset = offset;
  this.title = title;
  this.text = text;
}

//-----------------------------------------------
function setupMarketHours(divID, pHash){
	//set display_GMToffset BEFORE drawing the layers
	marketArray.each(function(market) {
		if (market.get('id') == 'new_york') {
			var openTime = market.get('GMTcloseTime') - computeDST_diff(market.get('observeDST'));
			display_GMToffset = 24*60 - openTime;
		}
	});

	setDivProperty(divID,pHash);
	createComponentsDiv();
	initMarkets();
	updateStatus();
	//set timer for 20 sec
	timerHandle = setInterval("updateStatus();", 20*1000); 
}
//-----------------------------------------
//gets the list of bank holidays for each market and then calls updateStatus
function initMarkets() {
	var d = new Date();
	var day  = d.getDate();
	var month= d.getMonth()+1;
	var year = d.getFullYear();
	var fromDate = day + "." + month + "." + year;

	marketArray.each(function(market) {
		var currencyName = market.get('currencyName');
		new Ajax.Request(get_holidays_path, {
			method: 'get',
			parameters: {currencyName:currencyName, fromDate:fromDate},
			onSuccess: function(transport) {
				var xmlDoc = transport.responseXML.documentElement;
				//local holidays (except weekends) during which market is closed.
				market.set('holidays', xmlDoc.getElementsByTagName(currencyName)[0].childNodes[0].nodeValue );
				updateStatus();
			},
			onFailure: function(transport) {
				//alert("Could not acquire list of bank holidays for "+market.get('title'));
				//alert(transport.responseText);
			}
		});
	});
}
//-----------------------------------------
function setDivProperty(divID,pHash){
	container_div_width = pHash.get("width") ;
	container_div_height = pHash.get("height");
	container_div_top =  pHash.get("top");
	container_div_left =  pHash.get("left");
	h_margin = pHash.get("h_margin");
	v_margin = pHash.get("v_margin");
	hourLineHeight = pHash.get("hourLineHeight"); 
	containerDivID = divID;
	$(containerDivID).setStyle({width: container_div_width+ "px", height: container_div_height+ "px", left:container_div_left+"px",top:container_div_top+"px"}); 	
}
//------------------------------------------
function createComponentsDiv(){
	// create title component
	var title_divContainer_fmt = new Template("<div id= #{titleContainer_divID} class ='title'> </div>");
	titleContainerdivID = 'titleContainer';
	$(containerDivID).update(
		$(containerDivID).innerHTML + title_divContainer_fmt.evaluate({titleContainer_divID:titleContainerdivID})
	);
	
	$(titleContainerdivID).setStyle(
		{ width: (container_div_width - 2 * h_margin)+ "px", 
		  height: Math.floor(container_div_height/10 ) + "px" 
		  //border: "1px solid #FF0000" //for debugging only
		}
	);
	var top = v_margin;
	moveDiv(titleContainerdivID, h_margin, top); 
	
	// create market component
	var market_divContainer_fmt = new Template("<div id= #{marketContainer_divID} style='position:absolute;background-color:#FFFFFF' onmouseover='showLine();' onmouseout='hideLine();' onmousemove='moveLine(event);'> </div>");
	marketContainerdivID = 'marketContainer';
	$(containerDivID).update(
		$(containerDivID).innerHTML + market_divContainer_fmt.evaluate({marketContainer_divID:marketContainerdivID})
	);
	
	$(marketContainerdivID).setStyle(
		{ width: (container_div_width - 2 * h_margin)+ "px", 
		  height: Math.floor(4.3 * container_div_height/10 ) + "px" 
		  //border: "1px solid" 
		}
	);
	top += $(titleContainerdivID).getHeight()+ 4 * v_margin ; //!!to compensate for hourLineHeight and the textbox height
	moveDiv(marketContainerdivID, h_margin, top);
	createMarketsDiv();
	// create time zone component
	var timeZone_divContainer_fmt = new Template("<div id=#{timeZoneContainer_divID} class ='timeZone'></div>");	
	timeZoneContainerdivID = 'timeZoneContainer';
	$(containerDivID).update(
		$(containerDivID).innerHTML + timeZone_divContainer_fmt.evaluate({timeZoneContainer_divID :timeZoneContainerdivID})
	);
	$(timeZoneContainerdivID).setStyle(
		{ width: (container_div_width - 2 * h_margin) + "px", 
		  height: Math.floor(container_div_height/10) + "px"
		  //border: "1px solid" //for debugging only
		}
	);
	top +=  container_div_height/2 +  v_margin; //$(marketContainerdivID).getHeight()
	moveDiv(timeZoneContainerdivID, h_margin, top);
	createTimeZone();
}
//------------------------------------------
function createTimeZone(){
	$(timeZoneContainerdivID).update(
		$(timeZoneContainerdivID).innerHTML + "<label>Timezone: </label><select id ='time_zone' onChange='timeZoneOffset=this.options[selectedIndex].value; updateStatus();'></select>"
	);

	var time_zone_fmt = new Template("<option title = '#{tz_title}' value=#{tz_value} #{selected}>#{tz_text}</option>");

	timeZoneArray.each(function(timeZone){
		var title = timeZone.title;
		var timeZoneValue = timeZone.offset;
		var text = timeZone.text;
		var selected_string = (timeZoneValue == timeZoneOffset) ? "selected" : "";

		// build drop-down menu items		
		$('time_zone').update(
			$('time_zone').innerHTML + time_zone_fmt.evaluate({tz_title:title, tz_value: timeZoneValue, tz_text: text, selected:selected_string })
		);
	}); 	
}
//------------------------------------------
function createMarketsDiv(){
	var dimensions = $(marketContainerdivID).getDimensions();
	var div_width = dimensions.width;
	var div_height = dimensions.height;

	var market_div_fmt = new Template("<div id = '#{divID}' class = 'market' style = 'width:#{width}px; height:#{height}px;' onmouseover ='changeContent(\"#{innercell_divID}\", #{index}, 1);' onmouseout ='changeContent(\"#{innercell_divID}\",#{index}, 0);' ><div id = '#{innercell_divID}' class = 'marketCell' style = 'width:#{width}px; margin-top: -#{h_height}px;'>#{marketName}</div></div>");

	
	var market_div_h = Math.floor(0.8 * div_height/4); 

	var market_text_div_h = Math.floor(market_div_h / 4 ); 
	var spaceBetween = Math.floor(0.2 * div_height/5);
	var left = 0;
	var top = spaceBetween;
	
	marketArray.each(function(market, index){
		var market_id = market.get('id');
		var inner_cell_id = market_id + "_child";
		var mrk = market.get('title');
		//var tri_id = market_id+"_tri";
		var market_duration = (market.get('GMTcloseTime') - market.get('GMTopenTime') + 24*60)%(24*60);
		var market_div_w = Math.ceil(market_duration * div_width  / (24*60));

		// build each market_div		
		$(marketContainerdivID).update(
			$(marketContainerdivID).innerHTML + market_div_fmt.evaluate({divID:market_id, width:market_div_w, height:market_div_h,innercell_divID:inner_cell_id, h_height:market_text_div_h, marketName: mrk, index:index})
		);
				
		// move each market based on its openHour
		left = openHourPosition(market,div_width);
		moveDiv(market_id, left, top);
		top += spaceBetween;		
	  }); 	
	drawHourlines();
	drawtimeLine();
}
//------------------------------------------
function drawHourlines(){
	$(marketContainerdivID).update(
		$(marketContainerdivID).innerHTML + "<div id='hourDivContainerID' > </div>"
	);
	moveDiv('hourDivContainerID',0, 0);
	var dimensions = $(marketContainerdivID).getDimensions();
	var div_width = dimensions.width;	
	var hourWidth = div_width / 24;
	var div_height = dimensions.height;
	var top = -hourLineHeight + 3; //
	var left = hourWidth;
	var hour_div_fmt = new Template("<div id= #{h_divID} class='hourLine'> </div>");
	for(var i= 1; i < 24; i++){
		var divID = "div"+genRandomID();
		// create hour line
		$('hourDivContainerID').update(
			$('hourDivContainerID').innerHTML + hour_div_fmt.evaluate({h_divID:divID})
		);	
				
		moveDiv(divID, left, top);
		left += hourWidth;
	}	
}
//-------------------------------------------
function moveLine(event){ 
		
	var mousePos = getMousePos(event);
	var div_width = $(marketContainerdivID).getWidth();
	var containerPosition = $(containerDivID).positionedOffset();
	var containerLeft = containerPosition[0] + h_margin; //to find absolute position 
	//$(test).innerHTML = mousePos["x"]+" h_margin"+h_margin+" container_div_left: "+container_div_left+" containerLeft: "+containerLeft; 
	if ( mousePos["x"] >= containerLeft && mousePos["x"] <= containerLeft + div_width ) {	
		var top = -hourLineHeight;
		var left = mousePos["x"]-containerLeft;
		moveDiv('rollOverLine', left, top);
		var txt_dimensions = $('rollOverLinetextBox').getDimensions();
		var txt_left = Math.max(0, left + 5 - txt_dimensions.width); //left position shouldn't go beyond 0px
		var txt_top = top - txt_dimensions.height;			
		moveDiv('rollOverLinetextBox',txt_left,txt_top );
		var current_date = getCurrentDate();
		var timeLine_left = parseInt( $('timeLine').getStyle("left").sub('px','') );
		var distanceInMin = (timeLine_left - left) *24 * 60 / div_width; //mouse distance from timeline in minutes
		var rollOver_date = new Date();
		rollOver_date.setTime( current_date.getTime() - distanceInMin * 60 * 1000 );				
		rwDiv( 'rollOverLinetextBox', formatTimeToStr(rollOver_date) );
	}
}
//------------------------------------------
function hideLine(){
	hideDiv('rollOverLine');
	hideDiv('rollOverLinetextBox');
}
//-------------------------------------------
function showLine(){
	showDiv('rollOverLine');
	showDiv('rollOverLinetextBox');
}
//-------------------------------------------
function getMousePos(e) {
      var isOpera = (navigator.userAgent.indexOf('Opera') != -1);
      var isIE = (!isOpera && navigator.userAgent.indexOf('MSIE') != -1)

      var posx = 0;
      var posy = 0;
      if (!e) var e = window.event;

      if (e.pageX || e.pageY) {
        posx = e.pageX;
	posy = e.pageY;

      } else if (e.clientX || e.clientY) {
        posx = e.clientX;
	posy = e.clientY;
	if (isIE) {
	  posx += document.body.scrollLeft;
	  posy += document.body.scrollTop;
        }
      }

      var pos = new Array();
      pos["x"] = posx;
      pos["y"] = posy;
      //alert("mousePos: x="+posx+" y="+posy);
      return pos;
}
//-------------------------------------------
function changeContent(divID, index, flag){
	if (flag == 0 ){
		$(divID).update(marketArray[index].get('title'));	
	}else{
		$(divID).update(marketArray[index].get('status'));	
	}
}
//---------------------------------------------
function genRandomID(){
	var randomIDstring = "" + Math.ceil(Math.random()*1000000);
	return randomIDstring;
}
//----------------------------------------------
function openHourPosition(marketHash, div_width){
	var DST_diff = computeDST_diff(marketHash.get('observeDST'));
	var startTime = (marketHash.get("GMTopenTime") + display_GMToffset - DST_diff + 24*60)%(24*60);
	var openHourPos = Math.floor(div_width * startTime / (24 * 60)); 
	return openHourPos;
}
//----------------------------------------------
function drawtimeLine(){
	var div_height = $(marketContainerdivID).getHeight();
	var timeLineHeight = div_height + 2 * hourLineHeight;
	var rollOverLineHeight = div_height + hourLineHeight;
	$(marketContainerdivID).update(
		// build timeLine and textbox
		$(marketContainerdivID).innerHTML += "<div id = 'timeLine' class='timeLine' style='height:"+ timeLineHeight+"px;'></div><div id = 'textBox' class = 'textBox'>--</div>"
		
	);
	
	$(marketContainerdivID).update(
			$(marketContainerdivID).innerHTML += "<div id='rollOverLine' class='rollOverLine' style='height:"+rollOverLineHeight+"px;'></div><div id ='rollOverLinetextBox'  class = 'rollOvertextBox' >--</div>"
	);
	moveDiv('rollOverLine', 0, 0);
	moveDiv('rollOverLinetextBox', 0, 0);	
	hideDiv('rollOverLine');
	hideDiv('rollOverLinetextBox');
}
//----------------------------------------------
function formatTimeToStr(current_date){
	// the format will be hh:mm am/pm
	var hour = current_date.getHours();
	var suffix= (hour >= 12)?" pm":" am";
	if (hour > 12) { hour = hour % 12; }
	if (hour < 10) { hour = "0"+ hour;}
	
	var minute = current_date.getMinutes();
	if (minute < 10 ){ minute = "0"+minute; }
	var str = hour +":"+minute+suffix;
	return str;
}
//----------------------------------------------
function updateTime(current_date){
	var str = formatTimeToStr(current_date);
	rwDiv('textBox',str);
				
	// move timeline and time box based on local time 
	
	var dimensions = $(marketContainerdivID).getDimensions();
	var div_width = dimensions.width;	
	var div_height = dimensions.height;
	
	var local_date = new Date(); 
	var start_tm = (local_date.getUTCHours() * 60 + local_date.getUTCMinutes() + display_GMToffset )%(24*60);//the current display order of markets is based on a day in GMT+3 timezone hence we adjust location of timeline by 3 hours

	var left =  Math.floor(div_width * start_tm / (24 * 60));
	left = Math.min(left, div_width);	//so that the time line doesnt go beyond the market
	var top = -2 * hourLineHeight ; 
	moveDiv('timeLine',left,top);

	var txt_dimensions = $('textBox').getDimensions();
	var txt_left = Math.max(0, left + 5 - txt_dimensions.width);//left position shouldn't go beyond 0px
	var txt_top = top - txt_dimensions.height;	
	moveDiv('textBox',txt_left,txt_top );	

	//write Date title for titleContainerdivID e.g Dec 11, 2008 
	var month = new Array ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
	var d = current_date.getDate();
	var m = current_date.getMonth();
	var y = current_date.getFullYear();	
	var dateStr = month[m]+' ' + d + ', ' + y; 	
	$(titleContainerdivID).update( "Market Hours: "+ dateStr);
	
}
//--------------------------------------------
function getCurrentDate(){
	//set current time based on selected timezone
	var current_date = new Date();

	var time_tmp = current_date.getTimezoneOffset() - timeZoneOffset;
	var tmp = current_date.getTime() + time_tmp * 60 * 1000;
	current_date.setTime(tmp);
	//current_date.setMonth(11,24); // for debugging 
	return current_date;
}
//--------------------------------------------
function updateStatus() {

	var current_date = getCurrentDate();
	updateTime(current_date);

	//find current date and time in GMT+3
	var gmtp3_date = new Date();
	gmtp3_date.setTime(current_date.getTime() + timeZoneOffset*60*1000 + display_GMToffset*60*1000);

	marketArray.each(function(market) {
		//adjust market hours by converting GMT times to the timeZone time
		//current difference with standard time (in minutes)
		var DST_diff = computeDST_diff(market.get('observeDST'));

		var opTime = (market.get('GMTopenTime') - timeZoneOffset - DST_diff + 24*60)%(24*60);
		var closeTime = (market.get('GMTcloseTime') - timeZoneOffset - DST_diff + 24*60)%(24*60);

		//find market open/close time (minutes past midnight) in GMT+3
		var opTime3 = (market.get('GMTopenTime') + display_GMToffset - DST_diff + 24*60)%(24*60);
		var closeTime3 = (market.get('GMTcloseTime') + display_GMToffset - DST_diff + 24*60)%(24*60);

		var opday3 = new Date(gmtp3_date);
		opday3.setHours(0,0,0,0);
		opday3.setTime( opday3.getTime() + opTime3*60*1000 );//==> market open date in GMT+3

		var closeday3 = new Date(gmtp3_date);
		closeday3.setHours(0,0,0,0);
		var closeAdjustment3 = (closeTime3 > opTime3) ? 0 : 24*60*60*1000;
		closeday3.setTime( closeday3.getTime() + closeTime3*60*1000 + closeAdjustment3);

		//find open date of market in it's local timezeon
		var market_local_open = new Date();
		market_local_open.setTime( opday3.getTime() - display_GMToffset*60*1000 + DST_diff*60*1000 
                                           - market.get('timeZoneOffset')*60*1000 );
		//alert("local opentime for "+ market.get('title') + " is " + market_local_open);

		//see if market is closed due to holiday or weekend
		if ( isMarketClosed(market, market_local_open) ) {
			market.set('isHoliday', true);
		} else { market.set('isHoliday', false); }

		if ( market.get('isHoliday') == false && gmtp3_date >= opday3 && gmtp3_date <= closeday3 ) {
			var time_remained = Math.ceil((closeday3 - gmtp3_date)/(1000*60));
			var minutes = time_remained % 60;
    			var hours = (time_remained - minutes)/60;
			var status = "closes in "+hours + "h " + minutes + "m";
			market.set('status',status);
			var color = $('textBox').getStyle("color");
			$(market.get('id')).setStyle({backgroundColor: color});

		} else {
			//find the next open date of the market
			if ( gmtp3_date > closeday3 || isMarketClosed(market, market_local_open)) {
				do {
					market_local_open.setTime( market_local_open.getTime() + 24*60*60*1000 );
				} while ( isMarketClosed(market, market_local_open) );
			}

			//convert that open date to localtime zone
			var opday = new Date();
			opday.setTime ( market_local_open.getTime() + market.get('timeZoneOffset')*60*1000 - timeZoneOffset*60*1000 - DST_diff*60*1000 );
			var time_remained = Math.ceil((opday - current_date)/(1000*60));
			var minutes = time_remained % 60;
    			var hours = (time_remained - minutes)/60;
			var status;
			if (hours<24) { 
				status = "opens in "+hours + "h " + minutes + "m"; 
			} else {
				status = "opens "+datetimeToStr(opday);
			}
			market.set('status',status);
			$(market.get('id')).setStyle({backgroundColor: '#000000'});
		}

	});

}

//****************************************************//
function isMarketClosed(market, date) {
  //if market is closed, returns the holiday description, else returns nothing
  //(assuming all markets are closed on Saturdays and Sundays)
  if (date.getDay() == 0) {return 'Weekend(Sunday)';}
  if (date.getDay() == 6) {return 'Weekend(Saturday)';}

  var holidays = market.get('holidays');
  var dateStr = dateToStr(date);
  var ix = holidays.indexOf(dateStr);
  if (ix == -1) {
    return ''; //there is no local holiday for the specified market (it is not closed)
  } else {
    ix = holidays.indexOf("~",ix); //holiday's description begins with ~
    if (ix == -1) {
      //alert('Holiday description not found!');
      return 'unknown';
    }
    var end_ix = holidays.indexOf("~",ix+1); //the description ends with ~
    if (end_ix == -1) {
      //alert('Wrong format for holiday description!');
      return 'unknown';
    }
    //alert ( this.name + " is closed on " + date + " for: " + holidays.substring(ix+1,end_ix) );
    return holidays.substring(ix+1,end_ix);
  }
}

//****************************************************//
function computeDST_diff(observeDST) {
  //difference between current time and std time. If it is Daylight Saving Time (DST),
  //and the market observes it, the difference is 60 minutes otherwise 0.

  if (!observeDST) { return 0; } //when market dosen't observe DST

  var dst_start = new Date(); 
  var dst_end = new Date();

  if (observeDST == 2) { //US DST rules

    //compute 2nd Sunday of March (for NYC in 2007)
    dst_start.setMonth(2); // Set from month 0-11
    dst_start.setDate(1);
    var wday = dst_start.getDay();// what weekday is 31st?
    if ( wday == 0 /* as in sunday */) { wday = 7; }
    dst_start.setDate(15-wday); // subtract from the highest possible value of the second sunday (+1 because of array issues)

    //compute first Sunday of November
    dst_end.setMonth(10); // pick November
    dst_end.setDate(1);
    wday = dst_end.getDay();
    if ( wday == 0 /* as in sunday */) { wday = 7; }
    dst_end.setDate(8 - wday);

  } else { //EU DST rules
    //compute last Sunday of March
    dst_start.setMonth(2);
    dst_start.setDate(31);
    var wday = dst_start.getDay();// what weekday is 31st?
    dst_start.setDate(31-wday); // go back until last Sunday

    //compute last Sunday of October
    dst_end.setMonth(9);
    dst_end.setDate(31);
    wday = dst_end.getDay();
    dst_end.setDate(31-wday);
  }

  var current = new Date();
  if (current >= dst_start && current < dst_end) { return 60; } else { return 0; }
}
//****************************************************//
function datetimeToStr(mydate) { 
  // output example: "12am Dec 12"
  var month = new Array ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

  var d = mydate.getDate();
  var m = mydate.getMonth();
  var hours = mydate.getHours();
  var minutes = mydate.getMinutes();
  var PM_AM;

  if (hours>=12) {hours-=12;PM_AM = 'pm';}  else {PM_AM = 'am';}

  if (minutes == 0) { minutes = ''; }
  else if (minutes < 10) {minutes = ':0'+minutes;}
  else {minutes = ':'+minutes;}

  var dateStr = hours + minutes + PM_AM + ' ' + month[m] +' '+ d;  
  return dateStr;
}
//****************************************************//
//used for isMarketClosed
function dateToStr(mydate) { 
  // output example: "02.03.2006", used as input to market[x].isClosed
  var d = mydate.getDate();
  if (d < 10) { d = '0' + d;} //make a 2-digit day
  var m = mydate.getMonth()+1;
  if (m < 10) { m = '0' + m;} //make a 2-digit month
  
  var str = d +"."+ m +"."+ mydate.getFullYear();
  return str;
}

