/* updated 2009-04-01 */

var clockTimerID = null;
var dayNames = new Array ('',
	'Sunday','Monday', 'Tuesday','Wednesday', 'Thursday','Friday', 'Saturday');

function startClock()
{
	if (clockTimerID != null)
		clearTimeout(clockTimerID);

	update_clock_display();
}

function update_clock_display()
{
	var now = new Date();

	updateRomanDate(now, "http://en.wikipedia.org/wiki/Roman_calendar");
	updateMayaDate(now, "http://en.wikipedia.org/wiki/Mesoamerican_Long_Count_calendar");
	updateIsoDate(now, "http://www.cl.cam.ac.uk/~mgk25/iso-time.html");
	updateFrcDate(now, "http://en.wikipedia.org/wiki/French_republican_calendar");
	updateHebrewDate(now, "http://www.kaluach.org");
//	updateInternetTime(now, "http://www.swatch.com/us_en/internettime.html");
	updateJulianDay(now, "http://en.wikipedia.org/wiki/Julian_day");
//	updateDiscordianDate(now, "http://www.tranglos.com/fnord/klock.html");	// set timeout to 1000 or less

	delete now;

	clockTimerID = setTimeout("update_clock_display()", 500)	// normally 4000 is enough
}

// Roman calendar

var prevRomanDate = "";
function updateRomanDate(now, link)
{
	var nRmonth, nRevent, nRday, bRbis;
	var nNones, nIdes;

	var nYear  = now.getFullYear();
	var nMonth = now.getMonth() + 1;
	var nDay   = now.getDate();
	var nHour  = now.getHours();

	// Begin the day at sunrise (06:00).
	// Historians disagree whether the Roman day began at midnight or sunrise.
	if (nHour < 6)
	{
		nDay--;
		if (nDay <= 0)
		{
			nMonth--;
			if (nMonth <= 0)
			{
				nYear--;
				nMonth += 12;
			}
			nDay = DaysInMonth(nMonth, nYear);
		}
	}

	var nDaysInMonth = DaysInMonth(nMonth, nYear);

	if ((nMonth == 3) || (nMonth == 5) || (nMonth == 7) || (nMonth == 10))
		nNones = 7;
	else
		nNones = 5;

	nIdes = nNones + 8;

	bRbis = false;

	if (nDay == 1)
	{
		nRmonth = nMonth;
		nRevent = 0;	// kalends
		nRday = 1;
	}
	else if (nDay <= nNones)
	{
		nRmonth = nMonth;
		nRevent = 1;	// nones
		nRday = nNones - nDay + 1;
	}
	else if (nDay <= nIdes)
	{
		nRmonth = nMonth;
		nRevent = 2;	// ides
		nRday = nIdes - nDay + 1;
	}
	else
	{
		nRmonth = (nMonth % 12) + 1;
		nRevent = 0;	// kalends
		nRday = nDaysInMonth - nDay + 2;
		if (nMonth == 2 && LeapYear(nYear))
		{
			if (nDay < 25)
				nRday--;
			else if (nDay == 25)
				bRbis = true;
		}
	}

	var htmstr = "";

	if (nRday == 2)
	{
		htmstr = htmstr + "pr. ";
	}
	else if (nRday > 2)
	{
		htmstr = htmstr + "a.d. ";
		if (bRbis)
			htmstr = htmstr + "bis ";
		htmstr = htmstr + RomanNumeral(nRday) + " ";
	}

	if (nRevent == 0)	// kalends
		htmstr = htmstr + "Kal. ";
	else if (nRevent == 1)	// nones
		htmstr = htmstr + "Non. ";
	else	// ides
		htmstr = htmstr + "Id. ";

	htmstr = htmstr + RomanMonthName(nRmonth);

	if (htmstr != prevRomanDate)
	{
		prevRomanDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('romandate').innerHTML = htmstr;
	}
}

function RomanMonthName(n)
{
	var rMonths = new Array("Ian.", "Feb.", "Mart.", "Apr.", "Mai.", "Iun.", "Iul.", "Aug.", "Sept.", "Oct.", "Nov.", "Dec.");
	var month = rMonths[n - 1];
	delete rMonths;
	return month;
}

/*
function PrintLink()
{
	var nYear, nMonth, nDay, nPageDay;

	var t = new Date();
	nYear = t.getFullYear();
	nMonth = t.getMonth() + 1;
	nDay = t.getDate();
	delete t;

	nPageDay = Math.min(26, (Math.floor((nDay - 1) / 5) * 5) + 1);

//	url = "http://www.clubs.psu.edu/aegsa/rome/" + EnglishMonthName(nMonth) + pad(nPageDay, 2) + ".htm#" + EnglishMonthName(nMonth) + pad(nDay, 2);
	url = "http://www.personal.psu.edu/users/w/x/wxk116/RomanCalendar/" + EnglishMonthName(nMonth) + pad(nPageDay, 2) + ".htm#" + EnglishMonthName(nMonth) + pad(nDay, 2);
	document.write("<a href='" + url + "'>")
}

function EnglishMonthName(n)
{
	var eMonths = new Array("jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec");
	var month = eMonths[n - 1];
	delete eMonths;
	return month;
}
*/

// Mayan Long Count calendar

var prevMayaDate = "";
function updateMayaDate(now, link)
{
	var t = now.getTime() - (now.getTimezoneOffset() * (60 * 1000));
	var kin = Math.floor(t / (24 * 60 * 60 * 1000)) + 1856305;
	var uinal = Math.floor(kin / 20);		kin -= uinal * 20;
	var tun = Math.floor(uinal / 18);		uinal -= tun * 18;
	var katun = Math.floor(tun / 20);		tun -= katun * 20;
	var baktun = Math.floor(katun / 20);	katun -= baktun * 20;
	var htmstr = baktun + '.' + katun + '.' + tun + '.' + uinal + '.' + kin;
	if (htmstr != prevMayaDate)
	{
		prevMayaDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('mayadate').innerHTML = htmstr;
	}
}

// ISO 8601 notation

var prevIsoDate = "";
function updateIsoDate(now, link)
{
	var year   = now.getFullYear();
	var month  = now.getMonth() + 1;
	var date   = now.getDate();
	var day    = now.getDay();
	var hour   = now.getHours();
	var minute = now.getMinutes();
	var htmstr = dayNames[day + 1]
		+ ' ' + pad(year, 4) + '-' + pad(month, 2) + '-' + pad(date, 2)
		+ '&nbsp;&nbsp;' + pad(hour, 2) + ':' + pad(minute, 2);
	if (htmstr != prevIsoDate)
	{
		prevIsoDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('isodate').innerHTML = htmstr;
	}
}

// French Revolutionary calendar

var prevFrcDate = "";
function updateFrcDate(now, link)
{
	var year  = now.getFullYear();
	var month = now.getMonth();
	var date  = now.getDate();

	var frcYear = year - 1792;
	if ((month * 100) + date >= 822)
		frcYear++;

	var frcNewYear = new Date(frcYear + 1791, 8, 22);
	var frcDay = ((now - frcNewYear) / 60000) - now.getTimezoneOffset() + frcNewYear.getTimezoneOffset();
	delete frcNewYear;
	frcDay = Math.floor(frcDay / 1440);

	// next line applies continuous leap-year rule
	// comment this line out to use Romme's proposed fixed rule instead
	// see Wikipedia for explanation of all this
	if ((frcYear % 4) == 0)
	{
		frcDay--;
		if (frcDay < 0)
		{
			frcYear--;
			frcDay = 365;
		}
	}

	frcMonth = Math.floor(frcDay / 30);
	frcDay -= (frcMonth * 30);

	var htmstr;
	if (frcMonth < 12)
	{
		htmstr = (frcDay + 1) + ' ' + FrcMonthName(frcMonth + 1) + ' an ' + RomanNumeral(frcYear)
			+ ' (' + FrcDayName(frcMonth, frcDay) + ')';
	}
	else
	{
		htmstr = FrcSpecialDayName(frcDay + 1) + ' an ' + RomanNumeral(frcYear);
	}

	if (htmstr != prevFrcDate)
	{
		prevFrcDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('frcdate').innerHTML = htmstr;
	}
}

function FrcMonthName(n)
{
	var eMonths = new Array(
		"Vendémiaire", "Brumaire", "Frimaire", "Nivôse", "Pluviôse", "Ventôse",
		"Germinal", "Floréal", "Prairial", "Messidor", "Thermidor", "Fructidor");
	var month = eMonths[n - 1];
	delete eMonths;
	return month;
}

function FrcDayName(month, day)
{
	var eDays = new Array(
	// Vendémiaire
		"Raisin", "Safran", "Châtaigne", "Colchique", "Cheval",
		"Balsamine", "Carotte", "Amarante", "Panais", "Cuve",
		"Pomme de terre", "Immortelle", "Potiron", "Réséda", "Âne",
		"Belle de nuit", "Citrouille", "Sarrasin", "Tournesol", "Pressoir",
		"Chanvre", "Pêche", "Navet", "Amaryllis", "Bœuf",
		"Aubergine", "Piment", "Tomate", "Orge", "Tonneau",
	// Brumaire
		"Pomme", "Céleri", "Poire", "Betterave", "Oie",
		"Héliotrope", "Figue", "Scorsonère", "Alisier", "Charrue",
		"Salsifis", "Macre", "Topinambour", "Endive", "Dindon",
		"Chervis", "Cresson", "Dentelaire", "Grenade", "Herse",
		"Bacchante", "Azerole", "Garance", "Orange", "Faisan",
		"Pistache", "Macjonc", "Coing", "Cormier", "Rouleau",
	// Frimaire
		"Raiponce", "Turneps", "Chicorée", "Nèfle", "Cochon",
		"Mâche", "Chou-fleur", "Miel", "Genièvre", "Pioche",
		"Cire", "Raifort", "Cèdre", "Sapin", "Chevreuil",
		"Ajonc", "Cyprès", "Lierre", "Sabine", "Hoyau",
		"Érable sucré", "Bruyère", "Roseau", "Oseille", "Grillon",
		"Pignon", "Liège", "Truffe", "Olive", "Pelle",
	// Nivôse
		"Tourbe", "Houille", "Bitume", "Soufre", "Chien",
		"Lave", "Terre végétale", "Fumier", "Salpêtre", "Fléau",
		"Granit", "Argile", "Ardoise", "Grès", "Lapin",
		"Silex", "Marne", "Pierre à chaux", "Marbre", "Van",
		"Pierre à plâtre", "Sel", "Fer", "Cuivre", "Chat",
		"Étain", "Plomb", "Zinc", "Mercure", "Crible",
	// Pluviôse
		"Lauréole", "Mousse", "Fragon", "Perce-neige", "Taureau",
		"Laurier-thym", "Amadouvier", "Mézéréon", "Peuplier", "Coignée",
		"Ellébore", "Brocoli", "Laurier", "Avelinier", "Vache",
		"Buis", "Lichen", "If", "Pulmonaire", "Serpette",
		"Thlaspi", "Thimelé", "Chiendent", "Trainasse", "Lièvre",
		"Guède", "Noisetier", "Cyclamen", "Chélidoine", "Traîneau",
	// Ventôse
		"Tussilage", "Cornouiller", "Violier", "Troène", "Bouc",
		"Asaret", "Alaterne", "Violette", "Marceau", "Bêche",
		"Narcisse", "Orme", "Fumeterre", "Vélar", "Chèvre",
		"Épinard", "Doronic", "Mouron", "Cerfeuil", "Cordeau",
		"Mandragore", "Persil", "Cochléaria", "Pâquerette", "Thon",
		"Pissenlit", "Sylve", "Capillaire", "Frêne", "Plantoir",
	// Germinal
		"Primevère", "Platane", "Asperge", "Tulipe", "Poule",
		"Bette", "Bouleau", "Jonquille", "Aulne", "Couvoir",
		"Pervenche", "Charme", "Morille", "Hêtre", "Abeille",
		"Laitue", "Mélèze", "Ciguë", "Radis", "Ruche",
		"Gainier", "Romaine", "Marronnier", "Roquette", "Pigeon",
		"Lilas", "Anémone", "Pensée", "Myrtille", "Greffoir",
	// Floréal
		"Rose", "Chêne", "Fougère", "Aubépine", "Rossignol",
		"Ancolie", "Muguet", "Champignon", "Hyacinthe", "Râteau",
		"Rhubarbe", "Sainfoin", "Bâton-d'or", "Chamérops", "Ver à soie",
		"Consoude", "Pimprenelle", "Corbeille d'or", "Arroche", "Sarcloir",
		"Statice", "Fritillaire", "Bourrache", "Valériane", "Carpe",
		"Fusain", "Civette", "Buglosse", "Sénevé", "Houlette",
	// Prairial
		"Luzerne", "Hémérocalle", "Trèfle", "Angélique", "Canard",
		"Mélisse", "Fromental", "Martagon", "Serpolet", "Faux",
		"Fraise", "Bétoine", "Pois", "Acacia", "Caille",
		"Œillet", "Sureau", "Pavot", "Tilleul", "Fourche",
		"Barbeau", "Camomille", "Chèvrefeuille", "Caille-lait", "Tanche",
		"Jasmin", "Verveine", "Thym", "Pivoine", "Chariot",
	// Messidor
		"Seigle", "Avoine", "Oignon", "Véronique", "Mulet",
		"Romarin", "Concombre", "Échalote", "Absinthe", "Faucille",
		"Coriandre", "Artichaut", "Girofle", "Lavande", "Chamois",
		"Tabac", "Groseille", "Gesse", "Cerise", "Parc",
		"Menthe", "Cumin", "Haricot", "Orcanète", "Pintade",
		"Sauge", "Ail", "Vesce", "Blé", "Chalémie",
	// Thermidor
		"Épeautre", "Bouillon blanc", "Melon", "Ivraie", "Bélier",
		"Prêle", "Armoise", "Carthame", "Mûre", "Arrosoir",
		"Panis", "Salicorne", "Abricot", "Basilic", "Brebis",
		"Guimauve", "Lin", "Amande", "Gentiane", "Écluse",
		"Carline", "Câprier", "Lentille", "Aunée", "Loutre",
		"Myrte", "Colza", "Lupin", "Coton", "Moulin",
	// Fructidor
		"Prune", "Millet", "Lycoperdon", "Escourgeon", "Saumon",
		"Tubéreuse", "Sucrion", "Apocyn", "Réglisse", "Échelle",
		"Pastèque", "Fenouil", "Épine vinette", "Noix", "Truite",
		"Citron", "Cardère", "Nerprun", "Tagette", "Hotte",
		"Églantine", "Noisette", "Houblon", "Sorgho", "Écrevisse",
		"Bigarade", "Verge d'or", "Maïs", "Marron", "Panier");
	var day = eDays[(month * 30) + day];
	delete eDays;
	return day;
}

function FrcSpecialDayName(n)
{
	var eDays = new Array(
		"La Fête de la Vertu",
		"La Fête du Génie",
		"La Fête du Travail",
		"La Fête de l’Opinion",
		"La Fête des Récompenses",
		"La Fête de la Révolution");
	var day = eDays[n - 1];
	delete eDays;
	return day;
}

// Hebrew calendar

var prevHebrewDate = "";
function updateHebrewDate(now, link)
{
	// add 6 hours to start day at 6 pm local time
	var nowPlus6 = new Date();
	nowPlus6.setTime(now.getTime() + (6 * 60 * 60 * 1000));
	var tday   = nowPlus6.getDate();
	var tmonth = nowPlus6.getMonth() + 1;
	var tyear  = nowPlus6.getFullYear();
	delete nowPlus6;
	var hebDate = civ2heb(tday, tmonth, tyear);
	var hmS = hebDate.substring(hebDate.indexOf(' ') + 1, hebDate.length);
	var hDay = eval(hebDate.substring(0, hebDate.indexOf(' ')));
	var hMonth = eval(hmS.substring(0, hmS.indexOf(' ')));
	var hYear = hmS.substring(hmS.indexOf(' ') + 1, hmS.length);
	var htmstr = hDay + ' ' + hebMonth[hMonth + 1] + ' ' + hYear;

	if (htmstr != prevHebrewDate)
	{
		prevHebrewDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('hebrewdate').innerHTML = htmstr;
	}
}

// Swatch Internet time

var prevInternetTime = "";
function updateInternetTime(now, link)
{
	var seconds = now.getTime() / 1000;

	// add 1 hour for Biel offset
	seconds = seconds + (60 * 60);

	// convert to beats
	var beats = Math.floor(seconds / 86.4) % 1000;

	var htmstr = '@' + pad(beats, 3);
	if (htmstr != prevInternetTime)
	{
		prevInternetTime = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('internettime').innerHTML = htmstr;
	}
}

// Julian day

var prevJulianDay = "";
function updateJulianDay(now, link)
{
	var seconds = now.getTime() / 1000;
	var julianDay = (seconds / 86400) + 2440587.5;
	var wholePart = Math.floor(julianDay);
	var fracPart = pad(Math.floor((julianDay - wholePart) * 1000), 3);
	var htmstr = 'JD ' + wholePart + '.' + fracPart;
	if (htmstr != prevJulianDay)
	{
		prevJulianDay = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('julianday').innerHTML = htmstr;
	}
}

// Discordian calendar and clock

var prevDiscordianDate = "";
function updateDiscordianDate(now, link)
{
	// day starts at 5:23 UTC
	var tMinus523 = new Date();
	tMinus523.setTime(now.getTime() - (((5 * 60) + 23) * (60 * 1000)));

	// New Year's Day
	var tNewYear = new Date(tMinus523.getFullYear(), 0, 1);
	var dayOfYear = Math.floor((tMinus523 - tNewYear) / (24 * 60 * 60 * 1000));
	delete tNewYear;

	var dateString = '';
	if (LeapYear(tMinus523.getFullYear()))
	{
		if (dayOfYear == 59)
			dateString = "St. Tib's Day";
		else if (dayOfYear > 59)
			dayOfYear--;
	}

	if (dateString == '')
	{
		var disYear = tMinus523.getFullYear() + 1166;
		var disSeason = Math.floor(dayOfYear / 73);
		var disDay = (dayOfYear % 73) + 1;
		var disWeekday = dayOfYear % 5;

		dateString = DiscordianWeekdayName(disWeekday) + ', ' + DiscordianSeasonName(disSeason)
			+ ' ' + disDay + ', ' + disYear + ' YOLD';
	}

	var disAneristicSeconds = ((tMinus523.getTime() / 1000) % 86400);
	var disTotalSeconds, disHour, disMinute, disSecond;
	if (disAneristicSeconds < (115 * 60))
	{
		// THUD
		disTotalSeconds = Math.floor(disAneristicSeconds / 60);
		disHour = 0;
		disMinute = Math.floor(disTotalSeconds / 23);
		disSecond = disTotalSeconds - (disMinute * 23);
	}
	else
	{
		disTotalSeconds = Math.floor((disAneristicSeconds - (115 * 60)) / 12);
		disHour = Math.floor(disTotalSeconds / 25) + 1;
		disTotalSeconds -= ((disHour - 1) * 25);
		disMinute = Math.floor(disTotalSeconds / 5);
		disSecond = disTotalSeconds - (disMinute * 5);
	}

	delete tMinus523;

	var htmstr = dateString + ' at ' + pad(disHour, 3) + ':' + pad(disMinute, 2) + ':' + pad(disSecond, 2) + '(1)';
	if (disHour == 0)
		htmstr += ' (THUD)';
	if (htmstr != prevDiscordianDate)
	{
		prevDiscordianDate = htmstr;
		if (link != '')
			htmstr = '<a href="' + link + '">' + htmstr + '</a>';
		document.getElementById('discordiandate').innerHTML = htmstr;
	}
}

function DiscordianWeekdayName(weekday)
{
	var eDays = new Array(
		"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange");
	var day = eDays[weekday];
	delete eDays;
	return day;
}

function DiscordianSeasonName(season)
{
	var eSeasons = new Array(
		"Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath");
	var season = eSeasons[season];
	delete eSeasons;
	return season;
}

// utility functions

function pad(str, places)
{
	str = str + '';
	while (str.length < places)
		str = '0' + str;

	return str;
}

function RomanNumeral(n)
{
	var s = "", d, p = 0;

	if (n == 0)
	{
		return s;
	}
	else if (n < 0)
	{
		s = "&#x2212;";
		n = -n;
	}

	var c = ["I", "V", "X", "L", "C", "D", "M", "V&#x305;", "X&#x305;",
		"L&#x305;", "C&#x305;", "D&#x305;", "M&#x305;"];
	n = Math.floor(n % 4000000);
	while (n > 0)
	{
		d = n % 10; n = (n - d) / 10;
		if (d == 4)
		{
			s = c[p + 1] + s;
			d = 1;
		}
		else if (d == 9)
		{
			s = c[p + 2] + s;
			d = 1;
		}
		while (d > 0)
		{
			if (d == 5)
			{
				s = c[p + 1] + s;
				break;
			}
			s = c[p] + s; d--;
		}
		p += 2;
	}
	return s;
}

function DaysInMonth(m, y)
{
	if ((m == 4) || (m == 6) || (m == 9) || (m == 11))
		return 30;
	else if (m != 2)
		return 31;
	else if (LeapYear(y))
		return 29;
	else
		return 28;
}

function LeapYear(y)	// works for all years
{
	if ((y % 4) != 0)
		return false;
	else if ((y % 100) != 0)
		return true;
	else if ((y % 400) != 0)
		return false;
	else
		return true;
}
