/*	Javascript to display world times	*/

// CONSTANT VARIABLES IN MINUTES
var hourInMins = 60;
var halfHourInMins = 30;

// INITIALISE NEEDED VARIABLES
var date, hours, minutes, gmtHourOffset, gmtMinOffset, gmtHours, gmtMins = 0;
var tick = 0;	// For updating the clock
date = new Date();
var year = date.getYear();

function setTimeArray()
{
	//-------- SET THE MULTI-DIMENSIONAL TIME ARRAY ------------------\\
	var timeData = new Array()

	// ARRAY FORMAT:
	// timeData[n] = new Array("Place name",GMT Offset (Hours),GMT Offset (Mins),Daylight Savings Time (Hours), 
	//							new Date(Year,Month,Maximum date in the month),  // Date to store DST start date 
	//							new Date(Year,Month,Maximum date in the month),  // Date to store DST end date
		timeData[0] = new Array('SanFrancisco',-8,0,1,	// SAN FRANCISCO: -8hr 0min GMT Offset, 1hr DST
							new Date(year,3-1,NthDay(2,1,3,year)), 	// DST starts on the 2nd Sunday of March
							new Date(year,11-1,NthDay(1,1,11,year))   	// DST ends on the 1st Sunday of November
							);
		timeData[1] = new Array('Minneapolis',-6,0,1,	// MINNEAPOLIS: -6hr 0min GMT Offset, 1hr DST
							new Date(year,3-1,NthDay(2,1,3,year)), 	// DST starts on the 2nd Sunday of March
							new Date(year,11-1,NthDay(1,1,11,year))   	// DST ends on the 1st Sunday of November
							);
		timeData[2] = new Array('Boston',-5,0,1,	// BOSTON: -5hr 0min GMT Offset, 1hr DST
							new Date(year,3-1,NthDay(2,1,3,year)), 	// DST starts on the 2nd Sunday of March
							new Date(year,11-1,NthDay(1,1,11,year))   	// DST ends on the 1st Sunday of November
							);
		timeData[3] = new Array('London',0,0,1,			// LONDON: 0hr 0min GMT Offset, 1hr DST
							new Date(year,3-1,NthDay(-1,1,3,year)),	// DST starts on the last Sunday of March
							new Date(year,10-1,NthDay(-1,1,10,year))	// DST ends on the last Sunday of October
							);
		timeData[4] = new Array('Mumbai',5,30,0,		// MUMBAI: 5hr 30min GMT Offset, No DST
							new Date(0,0,0), 
							new Date(0,0,0) 
							);	
	return timeData;
}

function NthDay(nth,weekday,month,year) 
{
	// CREATE A CALENDAR ARRAY (DAYS IN THE MONTHS)
	var feb = 0;
	if(year%4 > 0) feb = 29;
	else feb = 28; 	
	var calendar = new Array(31,feb,31,30,31,30,31,31,30,31,30,31);

    if (nth > 0) return (nth-1)*7 + 1 + (7 + weekday - DayOfWeek((nth-1)*7 + 1,month,year))%7;
    var days = calendar[month];
    return days - (DayOfWeek(days,month,year) - weekday + 7)%7;
}

function DayOfWeek(day,month,year) 
{
    var a = Math.floor((14 - month)/12);
    var y = year - a;
    var m = month + 12*a - 2;
    var d = (day + y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400) + Math.floor((31*m)/12)) % 7;
    return d+1;
}

function getMS(date) 
{
    return Date.UTC(date.getYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds())
}		

//-------- WORK OUT THE TIME ------------------\\
function calculateGMT()
{
	var timeData = setTimeArray();
	date = new Date();
	hours = date.getHours();
	minutes = date.getMinutes();
	gmtHourOffset = date.getTimezoneOffset()/hourInMins;
	
	if(!divisibleByHour(date.getTimezoneOffset())) // Work out whether the users GMT offset contains a half hour
	{
		gmtMinOffset = halfHourInMins;

		if(!exceedsHalfHour(minutes))	// Work out if the users minutes are less than half an hour
		{
			hours = hours - 1;	// Take off an hour and work out the minutes
			gmtMins = hourInMins - (gmtMinOffset - minutes);
		}	
		else gmtMins = minutes - halfHourInMins;
	}
	else gmtMins = minutes;
	
	gmtHours = hours + Math.floor(gmtHourOffset);
	
	for(i = 0; i < timeData.length; i++) // For each country
	{
		//Display the country's name and current local time
		if(timeData[i][0] == 'SanFrancisco') document.getElementById(timeData[i][0]).innerHTML = 'San Francisco: ' + getLocalTime(timeData[i]);
		else document.getElementById(timeData[i][0]).innerHTML = timeData[i][0] + ": " + getLocalTime(timeData[i]);
	}
	
	tick = setTimeout('calculateGMT()', 1000);	
}

function getLocalTime(country)
{
	var localHours = 0;
	var localMins = 0;
	var localTime = '';
	
	// First work out the local time without DST	
	if(country[2] > 0 && exceedsHalfHour(minutes)) // If there is an half hour offset and the minutes are greater than 30
	{
		localHours = 1;	// Add an hour and work out the minutes
		localMins = minutes - halfHourInMins;	
	}
	else localMins += gmtMins + country[2];	// Local minutes equal the offset mins + current GMT mins
	
	localHours += gmtHours + country[1]; // Local hours equal the offset hours + current GMT hours	
	if(country[3] > 0 && calculateDST(country)) localHours += country[3]; // If the country has DST and the date is in the DST period add the DST offset
	if(localHours >= 24) localHours -= 24;	//Work out if it's 12AM
	
	if(localMins < 10)
	{
		if(localHours < 10) localTime = '0' + localHours + ':0' + localMins;
		else localTime = localHours + ':0' + localMins;
	}
	else
	{
		if(localHours < 10) localTime = '0' + localHours + ':' + localMins;
		else localTime = localHours + ':' + localMins;
	}
	localTime = '<span class="timesBold">' + localTime + '</span>';
	
	return localTime;
} 	

function calculateDST(country)
{
	var todayMS = getMS(date);

	if(todayMS > country[4] && todayMS < country[5]) return true; // If the date is in the DST period return true
	else return false;
}																				

function divisibleByHour(value)
{
	if (value%60 == 0) return true;
	else return false; 
}

function exceedsHalfHour(value)
{
	if (value > halfHourInMins) return true;
	else return false;
}

function initialiseClock()
{
	tick = setTimeout('calculateGMT()', 500);
}