/* CZ.js . AlexanderZ.net . 20100107
	Associated files: CZ.html, CZ.css
*/
defaultStatus="Calendar: Dynamic, Interactive and Virtual ";
window.status=defaultStatus;

function statusMsg(msg) {
	window.status = msg;
}
var weekNo = 0; // Sun - Wed -> 1
var hdr = "";	// Varies by month
var ftr = ""; // used each time
var sDays = "";
var sMonths = new Array(12);

var curDate, curMonth, curYear, mo, yr;

var aDay = 1000*60*60*24 // = 86400000, Difference day in milliseconds
var aWeek = 7 * aDay;

var today = new Date();
var curDay = today.getDay();
var curDate = today.getDate();
var curMonth = today.getMonth();
var curYear = today.getYear();
if (curYear < 1000)
		curYear = curYear + 1900;
today.setFullYear(curYear,curMonth,curDate);

function makeDate(y, m, d) { // Q = new Date(y,m,d)
	y = (y < 1000) ? y + 1900 : y;
	w = new Date;
	w.setFullYear(y);
	w.setMonth(m);
	w.setDate(d); //	alert("Date: " + w);
	return w;
}
function makeDay(y, m, d) {
	y = (y < 1000) ? y + 1900 : y;
	return new Date(y,m,d).getDay(); //Q;
}
function bLeapYear(y) {
	return (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0));
}
function y2k(number) { return (number < 1000) ? number + 1900 : number; }
function dFirstDay(y, m, d) {
	return new Date(y,m,d).setFullYear(y,m,d);
}
function dLastDay(y, m) {
	return new Date(y,m,d).setFullYear(y,m,dMoNoDays(m, y));
}
var dLastDayYr = new Date();
dLastDayYr.setFullYear(curYear,11,31);

function daysDiff(then,now) { //Month is 0-11
	return Math.ceil((now-then)/aDay); //86400000); // ISO Standard Issue?
}
function weeksDiffISO(then,now) { // Month is 0-11 in JavaScript. ISO correction for Week 0 - Thurs
	return Math.ceil(daysDiff(then,now) / 7);
}
function weeksInYear(y,m,d) {
w = getWeek(y,11,31)
z = makeDay(y,11,31)
	if (bLeapYear(y)) // bLeapYear(y) = true;
	{
		if (z == 0) ++w;
		if (z == 1) { ++w; }
		if (z == 2) { ++w; ++w; }
		if (z == 3) { ++w; ++w; }
		if (z == 4) { ++w; }
		if (z == 5) { ++w; }
		if (z == 6) { ++w; }
	}
	else // bLeapYear(y) = false;
	{
		if (z == 0) ++w;
		if (z == 1) { ++w; ++w; }
		if (z == 2) { ++w; ++w; }
		if (z == 3) { ++w; ++w; }
		if (z == 4) ++w;
//		if (z == 5) ++w;
		if (z == 6) ++w; //{ ++w; ++w; }
	}
	return w;
}
//function weeksLeftInYear(y,m,d) {
//	y = (y < 1000) ? y + 1900 : y;
//	w = weeksDiffISO(makeDate(y,m,d),makeDate(y,11,31)); //	
//	return weeksInYear(y,0,1)-getWeek(y,m,d);
//}
//  Holiday Object:
function Holiday(nom, observed, actual, determination) {
	this.nom = nom;
	this.observed = observed;
	this.actual = actual;
	this.determination = determination;
}
var nHolidates = 11; // n Holidays w/ holiday[0] showing definitions
var holiday = new Array(nHolidates); // Holiday
var Holidate = new Array(nHolidates); // Holiday
//  Astronomical - Seasonal and Sun-Earth distance Object:
function Astroday(nom,actual,distance) {
	this.nom = nom;
	this.actual = actual;
	this.distance = distance; // Averages for aphelion and perihelion
// Sun-Earth distance and Seasons - Angles of incidence of sun's direct rays on earth's surface at 23 degrees axis
}
var nAstrodates = 7; // n Astrodays w/ astroday[0] showing definitions
var astroday = new Array(nAstrodates); // Holiday
var Astrodate = new Array(nAstrodates); // Holiday
var Astros = new Array(nAstrodates); // Holiday

var	hdr = "<table class='inner'><tbody>";
var	ftr = "</tbody></table>";

var d, l, m, n, s, t, x, y;

n = 3; // Abbreviation substring length - some languages use other lengths
var lDay = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday");
var lDayAbbrev = new Array(lDay.length);
for (var i = 0; i < lDayAbbrev.length; i++) {
	lDayAbbrev[i] = lDay[i].substring(0, n);
}
var lMonth = new Array("January","February","March","April","May","June");
lMonth = lMonth.concat("July","August","September","October","November","December");
var lMonthAbbrev = new Array(lMonth.length);
for (var i = 0; i < lMonthAbbrev.length; i++) {
	lMonthAbbrev[i] = lMonth[i].substring(0, n);
}
function isValidDate(ds) {
// Date validation function courtesty of Sandeep V. Tamhankar (stamhankar@hotmail.com) -->
// Checks for the following valid date formats:
// MM/DD/YY   MM/DD/YYYY   MM-DD-YY   MM-DD-YYYY
	var dPat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/; // requires 4 digit year
	var matchArray = ds.match(dPat); // is the format ok?
	if (matchArray == null) {
		alert(ds + " Date is not in a valid format.")
	return ds; // false;
}}
function dMoNoDays(m, y) {
	d = 31;	// most months (7) have 31 days
	if (m==3 || m==5 || m==8 || m==10) d = 30; // 4 months have 30
	if (m==1) { d = (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) ? 29 : 28; } // Feb
	return (d);
}
function dayString(y, m, d) {
	t = new Date(y, m, d);
//	ccyy = t.getFullYear(); // century century year year
	return lDayAbbrev[t.getDay()] + ", " + lMonthAbbrev[t.getMonth()] + " " + t.getDate();
}
function nthWeekDayOfMonth(y, m, d, n) {
/* e.g., 2005, 0, 1, 3 -> M. L. King Day - 3rd Mon of Jan
Presidents Day	3rd Monday of Feb 	Mon, Feb 16th
2006 10, 4, 4 -> Thanksgiving Day - 4th Thu of Nov
*/
	t = 0;
	first = new Date(y, m, 1).getDay();	//day of week
	if(( m == 4) && ( first > 1 )) n--; //Memorial Day	last Monday of May - need correction
	if(( m == 4) && ( first == 6 )) n++;
	if (first > d) { t = (7 * n) - (first - d - 1); }
	else { t = (7 * (n-1)) + (d - first + 1); }
	return dayString(y, m, t);
}
function hdrMonth(i){
	s = "<tr><th class='mml' colspan='8'>" + lMonth[i] +  "</th></tr>"
	s += "<tr><th class='wn' width='11'>Weeks</th>";
	s += "<th class='we' width='22'>" + lDayAbbrev[0] + "</th>";
	for (var i = 1; i <= 5; i++) { // lDay abbrev
		s += "<th class='ddl' width='11'>" + lDayAbbrev[i] + "</th>";
	}
	s += "<th class='we' width='22'>" + lDayAbbrev[6] + "</th></tr>";
	return s;
}
function sMonthCalendars(lo, up) {
	str = "<tr>";
	for (var i = lo; i <= up; i++) {
		str += sMonths[i];
	}
		str += "</tr>";
	return str;
}
function init() {
	s = initYear();
	s += "  ";
	s += initMonth();
	document.write (s);
}
function initYear() {
	y = today.getFullYear();
	s = "<select name='yyy' onclick='yearCalendar(document.Choices.yyy.options[document.Choices.yyy.selectedIndex].value, 0, 11)' />";
	for (var k = y-20; k <= y+20; k++) 
	{
		if (k == y) s += "<option value='" + k.toString() + "' selected='selected'>" + k.toString() + "</option>";
		else s += "<option value='" + k.toString() + "'>" + k.toString() + "</option>";
	}
	s += "</select>";
	return s;
}
function initMonth() {
	m = today.getFullYear();
	s = "<select name='mmm' onchange='yearCalendar(document.Choices.yyy.options[document.Choices.yyy.selectedIndex].value, document.Choices.mmm.options[document.Choices.mmm.selectedIndex].value, document.Choices.mmm.options[document.Choices.mmm.selectedIndex].value)' />";
	for (var k = 0; k <= 11; k++) 
	{
		if (k == m) s += "<option value='" + k.toString() + "' selected='selected'>" + lMonth[k] + "</option>";
		else s += "<option value='" + k.toString() + "'>" + lMonth[k] + "</option>";
	}
	s += "</select>";
	return (s);
}
function yearCalendar(yr,lo,up) {
	yr = (yr < 1000) ? yr + 1900 : yr;
	lo = (lo < 0) ? 0 : lo; // Jan
	up = (up > 11) ? 11 : up; // Dec
	sDays = "";
	weekNo = (makeDay(yr,0,1) < 5) ? 1 : 0;
	if (lo == up) {
		weekNo = getWeek(yr,lo,1); // +1; // ISOWeekNo(yr,lo,1,1); 
	}
	nWeeksYr = weeksInYear(yr,11,31)
	dspHolidays(s, yr);
	dspAstrodays(s, yr);

 for (k = lo; k <= up; k++) {	// initialize before each iteration
	sMonths[k] = mmddyy(k, yr);
	if ((((k + 1) % 3) == 0) && (k < 10))
	{
		sMonths[k] += "</tr><tr>"; } // Skip at 3 month intervals
	}
	document.getElementById('dCalendar').innerHTML = hdr + sMonthCalendars(lo, up) + ftr;
	document.getElementById('dHolidays').innerHTML = dspHolidays(s, yr);
	document.getElementById('dAstros').innerHTML = dspAstrodays("", yr);
}
function mmddyy(mo, yr) {
	dMonth = 1;
	dFirst = makeDay(yr,mo,1); //.getDay();
	dLast = dMoNoDays(mo, yr); //makeDate(yr,mo,mnDays); //.getDate();
// Weeks of month - Pad blank cells before first and after last week 
	i = 0;	//Set to Sunday
	nWeeks = 0;	// Vertical ht./month   // Start table row ****
	sDays = "<td><table class='mon'><tbody><tr><th>" + hdrMonth(mo) + "</th></tr>";
	sDays += "<tr><td class='wn'>" + weekNo + " : " + (nWeeksYr - weekNo) + "</td>";
	for (var j = 0; j < dFirst + dLast; j++) {
	if (j < dFirst) {
		sDays += "<td></td>";	//alert(dFirst + " " + dLast);
		}
	else {
		if (dMonth == curDate && mo == curMonth  && yr == curYear) {
			sDays += "<td class='hoy'>" + dMonth; // alert(dMonth + " " + curDate);
		}
		else if (j % 7 == 0 || j % 7 - 6 == 0) {
			sDays += "<td class='we'>" + dMonth;
		}
		else
			sDays += "<td>" + dMonth;
		sDays += hrefHoliday(dMonth,mo); // Holiday
		sDays += hrefAstroday(dMonth,mo); // Astronomical / Solar day
		sDays += "</td>";
		dMonth++;
	}
	i++;
	if (i == 7) {
		weekNo++;  // ISO base: 0 (year started on or after Thurs) or 1 year started before Thurs)
		sDays += "</tr><tr>";
		if (j < dFirst + dLast - 1)
			sDays += "<td class='wn'>" + weekNo + " : " + (nWeeksYr-weekNo) + "</td>";
		i = 0;
	}}
	/*while (nWeeks < 6) { //6 weeks -> all months have vertical ht.
		sDays += "<td></td>"; nWeeks++; }*/
	sDays += "</tr></tbody></table></td>";
return sDays;
}
// Holidays functions
function hrefHoliday(n,m) {
	s = "";
	bHoliday = false;
	switch (m)
{
case 0 :
	if ((Holidate[1].getDate() == n) && (n != 31)) bHoliday = true; // n -> day Of Month - caution - 31st
	if (Holidate[2].getDate() == n) bHoliday = true;
	break;
case 1 :
	if (Holidate[3].getDate() == n) bHoliday = true;
	break;
case 4 :
	if (Holidate[4].getDate() == n) bHoliday = true;
	break;
case 6 :
	if (Holidate[5].getDate() == n) bHoliday = true;
	break;
case 8 :
	if (Holidate[6].getDate() == n) bHoliday = true;
	break;
case 9 :
	if (Holidate[7].getDate() == n) bHoliday = true;
	break;
case 10 :
	if (Holidate[8].getDate() == n) bHoliday = true;
	if (Holidate[9].getDate() == n) bHoliday = true;
	break;
case 11 :
	if (Holidate[10].getDate() == n) bHoliday = true;
	if ((Holidate[11].getDate() == n) && (Holidate[11].getDay() == 5)) bHoliday = true;
	break;
} // end switch
	if (bHoliday) s += "<sup>H</sup>";
	return s;
}
function dspHolidays(s, y) {
for (i = 0; i <= nHolidates; i ++) {
	holiday[i] = new Holiday("nom", "observed", "actual", "determination", "date");
}
holiday[0].nom = "Name";
holiday[0].observed = "Observed";
holiday[0].actual = "Actual";
holiday[0].determination = "Determination";
//  holiday[0].date = "Date"; - replaced by Holidate[0] = new Date();
Holidate[0] = new Date();

holiday[1].nom = "New Year's Day";
d = adjustWeekEndHoliday(dayString(y, 0, 1), 1);
if (d == 0)
	holiday[1].observed = dayString(y-1, 11, 31) + "<sup>1</sup>";
else if (d == 7)
	holiday[1].observed = dayString(y, 0, 2) + "<sup>1</sup>";
else
	holiday[1].observed = dayString(y, 0, 1) + "<sup>1</sup>";
holiday[1].actual = dayString(y, 0, 1);
holiday[1].determination = "Actual, Fri before, or Mon after"

Holidate[1] = new Date(y,0,d);

holiday[2].nom = "Martin Luther King, Jr. Day";
holiday[2].observed = nthWeekDayOfMonth(y, 0, 1, 3) + "<sup>2</sup>";
d = nthWeekDayOfMonth(y, 0, 1, 3);
d = d.substr(d.length-2,2);
holiday[2].actual = dayString(y, 0, 15);
holiday[2].determination = "Third Mon in Jan";

Holidate[2] = new Date(y,0,d);

holiday[3].nom = "Presidents' Day";
holiday[3].observed = nthWeekDayOfMonth(y, 1, 1, 3) + "<sup>3</sup>";
d = nthWeekDayOfMonth(y, 1, 1, 3);
d = d.substr(d.length-2,2);
holiday[3].actual = nthWeekDayOfMonth(y, 1, 1, 3);
holiday[3].determination = "Third Mon in Feb";

Holidate[3] = new Date(y,1,d);

holiday[4].nom = "Memorial Day";
holiday[4].observed = nthWeekDayOfMonth(y, 4, 1, 5) + "<sup>2</sup>";
d = nthWeekDayOfMonth(y, 4, 1, 5);
d = d.substr(d.length-2,2);
holiday[4].actual = dayString(y, 4, 30);
holiday[4].determination = "Last Mon in May";

Holidate[4] = new Date(y,4,d);

holiday[5].nom = "Independence Day";
d = adjustWeekEndHoliday(dayString(y, 6, 4), 4);
holiday[5].observed = dayString(y, 6, d) + "<sup>1</sup>";
holiday[5].actual = dayString(y, 6, 4);
holiday[5].determination = "Actual, Fri before, or Mon after";

Holidate[5] = new Date(y,6,d);

holiday[6].nom = "Labor Day";
holiday[6].observed = nthWeekDayOfMonth(y, 8, 1, 1) + "<sup>3</sup>";
d = nthWeekDayOfMonth(y, 8, 1, 1);
d = d.substr(d.length-2,2);
holiday[6].actual = nthWeekDayOfMonth(y, 8, 1, 1);
holiday[6].determination = "First Mon in Sep";

Holidate[6] = new Date(y,8,d);

holiday[7].nom = "Columbus Day";
holiday[7].observed = nthWeekDayOfMonth(y, 9, 1, 2) + "<sup>2</sup>";
d = nthWeekDayOfMonth(y, 9, 1, 2);
d = d.substr(d.length-2,2);
holiday[7].actual = dayString(y, 9, 12);
holiday[7].determination = "Second Mon in Oct";

Holidate[7] = new Date(y,9,d);

holiday[8].nom = "Veterans' Day";
d = adjustWeekEndHoliday(dayString(y, 10, 11), 11);
holiday[8].observed = dayString(y, 10, d) + "<sup>1</sup>";
holiday[8].actual = dayString(y, 10, 11);
holiday[8].determination = "Actual, Fri before, or Mon after";

Holidate[8] = new Date(y,10,d);

holiday[9].nom = "Thanksgiving Day";
holiday[9].observed = nthWeekDayOfMonth(y,10,4,4) + "<sup>3</sup>";
d = nthWeekDayOfMonth(y,10,4,4);
d = d.substr(d.length-2,2);
holiday[9].actual = nthWeekDayOfMonth(y, 10, 4, 4);
holiday[9].determination = "Fourth Thurs in Nov";

Holidate[9] = new Date(y,10,d);

holiday[10].nom = "Christmas Day";
d = adjustWeekEndHoliday(dayString(y,11,25),25);
holiday[10].observed = dayString(y,11,d) + "<sup>1</sup>";
holiday[10].actual = dayString(y,11,25);
holiday[10].determination = "Actual, Fri before, or Mon after";

Holidate[10] = new Date(y,11,d);

Holidate[11] = new Date(y,11,31);

d = 31; // adjustWeekEndHoliday(dayString(y,0,1),1);
holiday[11].observed = dayString(y,11,31) + "<sup>1</sup>";
holiday[11].actual = dayString(y+1,0,1);
holiday[11].determination = "Actual, Fri before, or Mon after"

if (Holidate[11].getDay() == 5) 
{	holiday[11].nom = "New Year's Day";
	nHols = nHolidates;
}
else
{	holiday[11].nom = "";
	nHols = nHolidates-1;
}
s = "<table class='tInfo' summary='Federal Holidays'><tbody>"
s += "<tr><th colspan='4'>" + y + " United States Federal Holidays: Actual and Observed</th></tr>";
s += "<tr><th>Federal Holiday</th> <th>Observed</th> <th>Actual</th> <th>Determination</th></tr>";
for (i=1; i <= nHols; i++) 
{
	s += "<tr><td>" + holiday[i].nom + "</td>";
	s += "<td>" + holiday[i].observed + "</td>";
	s += "<td>" + holiday[i].actual + "</td>";
	s += "<td>" + holiday[i].determination + "</td></tr>"; // + Holidate[i] + "</td></tr>";
}
s += "<tr><td colspan='4' class='l'><strong>Note H: Holidays<br />";
s += "1:</strong> These holidays are observed on the actual date if they occur during the ";
s += "week. However, if the holiday falls on Saturday, it is observed on Friday; ";
s += "if the holiday falls on Sunday, it is observed on Monday.<br />";
s += "<strong>2:</strong> These holidays are observed on the <em>nth</em> weekday of the their respective month, ";
s += "but have a specific date.<br />";
s += "<strong>3:</strong> These holidays are observed on the <em>nth</em> weekday of the their respective month, ";
s += "but have no specific date.</td></tr></tbody></table>";
	return s;
}
function adjustWeekEndHoliday(s, d) {
	reSat = "Sat";
	reSun = "Sun"
	if (s.indexOf(reSat) >= 0)
	{ // Sat - Fri)
		--d; // = dayString(y, 6, 3) + "*";
	}
	else if (s.indexOf(reSun) >= 0)
	{ // Sat - Mon
		++d;
	}
	return (d);
}
// Astronomical and  Seasonal Dates - functions
function hrefAstroday(n,m) {
	s = "";
	bAstroday = false;
	switch (m)
{
case 0 : // Jan - Perihelion - Sun - earth furthest
	if (Astrodate[5].getDate() == n) bAstroday = true;
	break;
case 2 : // Mar - Spring - North Hemisphere; Fall - South
	if (Astrodate[1].getDate() == n) bAstroday = true;
	break;
case 5 : // June - Summer - North Hemisphere; Winter - South
	if (Astrodate[2].getDate() == n) bAstroday = true;
	break;
case 6 : // July - Aphelion - Sun - earth closest
	if (Astrodate[6].getDate() == n) bAstroday = true;
	break;
case 8 : // September - Autumn / Fall - North Hemisphere; Spring - South
	if (Astrodate[3].getDate() == n) bAstroday = true;
	break;
case 11 : // December - Winter - North Hemisphere; Spring - South
	if (Astrodate[4].getDate() == n) bAstroday = true;
	break;
} // end switch
	if (bAstroday == true) s += "<sup>A</sup>";
	return s;
}
// Seasonal and Astrological functions
//var datMoon = new Array();
// var apogee = new Array();
// var perigee = new Array();
// var datSol = new Array(7);
/*
0: Leap Year - String as Boolean // Blue Moon later?
1: Spring - March, 2x
2: Summer - June, 5x
3: Fall - September, 2x
4: Winter - December, 2x
5: Perihelion - Closest; January, x
6: Aphelion - Furthest: July, x
*/
function dspAstrodays(s, y) { //
// var y = yr - 1000;
for (i = 0; i <= nAstrodates; i ++) {
	astroday[i] = new Astroday("nom", "actual", "date");
	Astrodate[i] = new Date();
}
astroday[0].nom = "Name"; // astroday[0].observed = "Observed";
astroday[0].actual = "Actual"; // astroday[0].distance = "Distance";

Astrodate[0] = new Date();
yr = y;
y = y-2000;
switch (y)
{
case 0 : //2000
	Astros = new Array(1,20,20,20,20,3,4);
	break;
case 1 : //2001
	Astros = new Array(0,21,21,21,21,4,4);
	break;
case 2 : //2002
	Astros = new Array(0,21,21,21,21,2,6);
	break;
case 3 : //2003
	Astros = new Array(0,21,21,21,21,4,4);
	break;
case 4 : //2004
	Astros = new Array(1,21,21,21,21,4,5);
	break;
case 5 : //2005
	Astros = new Array(0,21,21,21,21,2,5);
	break;
case 6 : // 2006
	Astros = new Array(0,20,21,23,22,4,3);
	break;
case 7 :
	Astros = new Array(0,21,21,23,22,3,7);
	break;
case 8 : //2008
	Astros = new Array(1,20,20,22,21,3,4);
	break;
case 9 : //2009
	Astros = new Array(0,21,21,21,21,4,4);
	break;
case 10 : //2010
	Astros = new Array(0,21,21,21,21,3,6);
	break;
case 11 : //2011
	Astros = new Array(0,21,21,21,21,3,4);
	break;
case 12 : //2012
	Astros = new Array(1,21,21,21,21,5,5);
	break;
case 13 : //2013
	Astros = new Array(0,21,21,21,21,2,5);
	break;
case 14 : //2014
	Astros = new Array(0,21,21,21,21,4,4);
	break;
case 15 : //2015
	Astros = new Array(0,21,21,21,21,4,6);
	break;
case 16 : //2016
	Astros = new Array(1,21,21,21,21,2,4);
	break;
case 17 : //2017
	Astros = new Array(0,21,21,21,21,4,3);
	break;
case 18 : //2018
	Astros = new Array(0,21,21,21,21,3,6);
	break;
case 19 : //2019
	Astros = new Array(0,21,21,21,21,3,4);
	break;
case 20 : //2020
	Astros = new Array(1,21,21,21,21,5,4);
	break;
/*
case 21 : //2021
	Astros = new Array(0,21,21,21,21,3,4);
	break;
case 22 : //2022
	Astros = new Array(1,21,21,21,21,5,5);
	break;
case 23 : //2023
	Astros = new Array(0,21,21,21,21,2,5);
	break;
case 24 : //2024
	Astros = new Array(1,21,21,21,21,4,4);
	break;
case 25 : //2025
	Astros = new Array(0,21,21,21,21,4,6);
	break;
*/
default:
	Astros = new Array(-1,-1,-1,-1,-1,-1);
}
s = "<table class='tInfo' summary='Astronomical, Earth-Sun Relationship, Dates, Seasons'><tbody>";
s += "<th colspan='7'>" + yr + " Astronomical and Earth-Sun Relationship Dates</th>";
if ((yr < 2000) || (yr > 2020)) //(Astros[0] == -1) //
	{ s += "<tr><td colspan='7'>Data are limited to years 2000 through 2020 inclusively</td></tr>"; }
else 
{
s += "<tr><th>Leap<br />Year</th>";
s += "<th>Vernal<br />Equinox</th><th>Summer<br />Solstice</th>";
s += "<th>Autumnal<br />Equinox</th><th>Winter<br />Solstice</th>";
s += "<th>Perihelion<br />(Closest)</th><th>Aphelion<br />(Farthest)</th></tr>";

s += "<tr><td>" + ((Astros[0] == 1) ? 'Yes' : 'No'); + "</td>"; // leap year
s += "<td>" + dayString(yr, 2, Astros[1]) + "</td>"; // Spring/Fall
	Astrodate[1] = new Date(yr,2,Astros[1]);
s += "<td>" + dayString(yr, 5, Astros[2]) + "</td>"; // Summer/Winter
	Astrodate[2] = new Date(yr,5,Astros[2]);
s += "<td>" + dayString(yr, 8, Astros[3]) + "</td>"; // Fall/Spring
	Astrodate[3] = new Date(yr,8,Astros[3]);
s += "<td>" + dayString(yr, 11, Astros[4]) + "</td>"; // Winter/Summer
	Astrodate[4] = new Date(yr,11,Astros[4]);
s += "<td>" + dayString(yr, 0, Astros[5]) + "</td>"; // Aphelion - farthest
	Astrodate[5] = new Date(yr,0,Astros[5]);
s += "<td>" + dayString(yr, 6, Astros[6]) + "</td></tr>"; // Perihelion - closest
	Astrodate[6] = new Date(yr,6,Astros[6]);
}
s += "</tr><tr><td colspan='7' class='l'><strong>Note A: Astronomical and Earth-Sun Relationship Dates.</strong><br />";
s += "Northern and Southern Hemisphere equinoxes and solstices dates and "
s += "the seasons are opposite from each other. Exchange Spring for Fall Equinoxes and Summer for Winter Solstices.</td></tr>";
s += "</tbody></table>";
	return s;
}
function timeR() { // called recusively repeatedly
	t = new Date();
	hh = t.getHours();
	mm = t.getMinutes();
	ss = t.getSeconds();
	wd = t.getDay(); // week day, start at 0
	dd = t.getDate(); // day of month
	mon = t.getMonth(); // month, start at 0
	ccyy = t.getFullYear(); // century century year year
	UTCth = t.getUTCHours();
	noon = (hh < 12) ? " AM" : " PM";

	ss = (ss < 10) ? "0" + ss : ss;
	mm = (mm < 10) ? "0" + mm : mm;
	hh = (hh == 0) ? 12 : hh; // midnight

	greeting = "Good Evening! ";	// redefine greeting w/ time changes over day
	if (hh < 18) greeting = "Good Afternoon! ";	// midnight included
	if (hh <= 12) greeting = "Good Morning! "; //hh -= 12; // 12 hour clock adjustment

	hh = (hh > 12) ? hh % 12 : hh; // midnight

	univTime = hh+(mm/60); //+(ss/3600); // Adjust for UTC offset?
//	if ((100*ccyy+mon-190002.5) >= 0) {sign = 1}
//		else {sign = -1}
	sign = ((100*ccyy+mon-190002.5) >= 0) ? 1 : -1;
/*	with (Math) { // Details...
		part1 = 367 * ccyy;
		part2 = floor((7*(ccyy+floor((mon+9)/12)))/4);
		part3 = dd+floor((275*mon)/9);
		part4 = 1721013.5; // + (univTime/24)+(univTime/24);
		part5 = 0.5*sign;
		Julian = part1-part2+part3+part4-part5+0.5;
   } */
   	dspDate = lDay[wd] + "<br />" + dd + " " + lMonth[mon] + " " + ccyy;
	dspTime = hh + ":" + mm+ ":" + ss + noon; // put it together

	var dspClock = greeting + '<br />' + dspTime + '<br />' + dspDate; // + '<br />Julian Date:' + Julian;

	document.getElementById('dAbout').innerHTML = greeting + ' ' + lDay[wd] + ' ' + dd + " " + lMonth[mon] + ' ' + ccyy + ' ' + dspTime;

d = new Date;

d.setTime(t) + d.getTimezoneOffset()*60
	UTCDate = d.getUTCDate() + " " + lMonth[d.getUTCMonth()] + " " + d.getUTCFullYear();
	UTCss = (d.getUTCSeconds() < 10) ? "0" + d.getUTCSeconds() : d.getUTCSeconds();
	UTCmm = (d.getUTCMinutes() < 10) ? "0" + d.getUTCMinutes() : d.getUTCMinutes();
	UTChh = (d.getUTCHours() == 0) ? 12 : d.getUTCHours(); // midnight
	UTCTime = d.getUTCHours() + ":" + UTCmm + ":" + UTCss; // put it together
	UTCnoon = (d.getUTCHours() < 12) ? " AM" : " PM";
//	UTCOffset = ((UTChh+24) - t.getHours()) % 24 + " Hours";
	UTCOffset = t.getTimezoneOffset()/60 + " Hours";
	UTCZeit = 'Greenwich Mean Time (GMT) /<br>Universal Coordinated Time (UTC)<br />';
	UTCZeit += 'Greenwich Offset: ' + UTCOffset;

	Julian = GtoJ(mon+1,dd,ccyy);

	UTCZeit += '<br />' + ' ' + lDay[d.getUTCDay()] + ' ' + UTCDate + ' ' + UTCTime + UTCnoon + '<br />Julian Date:' + Julian;

	ISO = '<br />ISO Date: ' + ISOWeekNo(ccyy,mon,dd,2);
	document.getElementById('dUTCClock').innerHTML = UTCZeit + ISO;
		setTimeout('timeR()',1000); // call recursively
}
function dspData(y,m,d) {
// Dec 1 curYear-1 is start of year - i.e.: curYear-1, 11, 31
// Dec 31 curYear is end of year - i.e.: curYear, 11, 31
// Day Numbers
	y = (y < 1000) ? y + 1900 : y;
	now = makeDate(y,m,d);
	dspData = '<table><tbody>'
	dspData += '<tr><td>&nbsp;</td><td> Month </td> <td> Year </td></tr>'
	dspData += '<tr>'
//  Table begin Labels in left column
	dspData += '<td>Day Number:<br />Days Left:<br />Week Number:<br />Weeks Left:</td>'
// Month values column: 1st 2 for Days. Last 2 for Weeks
	dspData += '<td>' + today.getDate() + '<br />';
	dspData += daysDiff(now,dLastDay(y, m)) + '<br />';
//	dspData += ISOWeekNo(y,m,d,1)-ISOWeekNo(y,m,1,1) + 1 + '<br />';
//	dspData += getWeek(y,m,d) - getWeek(y,m,1) + '<br />';
//	if (getWeek(y,m,1) == getWeek(y,m,d)) 
		// dspData += getWeek(y,m,d) - getWeek(y,m,1) + '<br />';
//		dspData += getWeek(y,m,d) + 1 + '<br />';
//	else
//		dspData += getWeek(y,m,d) - getWeek(y,m,1) + 1 + '<br />';
	dspData += getWeek(y,m,d) - getWeek(y,m,1) + 1 + '<br />';
	dspData += weeksDiffISO(now,dLastDay(y, m)) + '</td>';
// Year values column: 1st 2 for Days. Last 2 for Weeks
	dspData += '<td>' + daysDiff(makeDate(y-1,11,31),now) + '<br />';
	dspData += daysDiff(now,dLastDay(y,11)) + '<br />';
	dspData += getWeek(y,m,d)+'<br />'; // ISOWeekNo(y,m,d,1)-1+'<br />'; 
//	dspData += if (getWeek(y,0,d) == 0) weeksInYear(y,0,1)-getWeek(y,m,d)+'</td>'; // ISOWeekNo(y,m,d,1)+'</td>';
//	if (getWeek(y,0,d) == 0) 
//		dspData += weeksInYear(y,0,1)-getWeek(y,m,d)+1; // ISOWeekNo(y,m,d,1)+'</td>';
//	else
	dspData += getWeek(y,11,31)-getWeek(y,m,d);
//	dspData += getWeek(y,m,d) - getWeek(y,m,1) + 1 + '<br />'; 
// Table end
	dspData += '</td></tr></tbody></table>'
	document.getElementById('dData').innerHTML = dspData;
}
// Following adapted from one created by: Dr. Gene Davis, Computer Support Group, http://www.coffeecup.com
// However, the results are the same as several other scripts.
function GtoJ(m,d,y) {
	if (m <= 2) {
		m += 12;
		y -= 1;
	}
	A = Math.floor(y/100);
	B = 2 - A + Math.floor(A/4);
	Julian = Math.floor(365.25*(y+4716)) + Math.floor(30.6001*(m+1)) + d + B - 1524.5;
	return Julian;
}
// Following 2 functions adapted from those at: http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
// Revised to accept any date parameters and use of JavaScript enhancements.
// However, the results are the same as several other scripts.
function GregDayN(y,m,d){ // day number since 0 January 0 CE (Gregorian)
	++m;
	if(m < 2) 
	{
		--y;
		m += 12;
	}
	return Math.floor(365.25*y)-Math.floor(y/100)+Math.floor(y/400)+Math.floor(30.6*m)+d-62;
}
function ISOWeekNo(y,m,d,p){ // ISO week number of parameter date
	var ISOweek;
//	alert(" y= " + y + " m= " + m + " d= " + d + " p= " + p);
	y = (y < 1000) ? y + 1900 : y;
	wday=makeDay(y,m,d);
	wday=((wday+6)%7)+1;
	yISO=y;
	d0=GregDayN(y,1,0);
	wday0=((d0+4)%7)+1;
 	t=GregDayN(y,m+1,d); // t was d in this and lines below
	wnISO=Math.floor((t-d0+wday0+6)/7)-Math.floor((wday0+3)/7);
// last few days of December in next year's ISO week
	if((m == 11) && ((d-wday) > 27))
	{
		wnISO=1;
		++yISO;
	}
// first few days of January in previous year's ISO week
	if((m == 0) && ((wday-d) > 3))
	{
		d0=GregDayN(y-1,1,0);
		wday0=((d0+4)%7)+1;
		wnISO=Math.floor((t-d0+wday0+6)/7)-Math.floor((wday0+3)/7);
		--yISO;
	}
	switch (p)
{
//case 0 : // Day number
//	w = Math.floor(d-d0+wday0+6)-Math.floor(wday0+3); //d0; //	break;
case 1 : // ISO Week number
	w = wnISO;
	break;
case 2 : // Week number string
	w  = (wnISO < 10) ? yISO+"-W0"+wnISO+"-"+wday : yISO+"-W"+wnISO+"-"+wday;
	break;
default:
	alert("Oops! ");
}
//	if(wnISO < 10) ISO = yISO+"-W0"+wnISO+"-"+wday;
//	else ISO =  yISO+"-W"+wnISO+"-"+wday;
	return w;
}
/*
function isLeapYear(yr) {
  return new Date(yr,2-1,29).getDate()==29;
}
*/
function getWeek(y,m,d) {
	year = y2k(y);
    var when = new Date(y,m,d);
    var newYear = new Date(y,0,1);
    var offset = 7 + 1 - newYear.getDay();
    if (offset == 8) offset = 1;
    var daynum = ((Date.UTC(y2k(y),when.getMonth(),when.getDate(),0,0,0)-Date.UTC(y2k(y),0,1,0,0,0)) /1000/60/60/24) + 1;
    var weekNo = Math.floor((daynum-offset+7)/7);
    if (weekNo == 0) {
        y--;
        var prevNewYear = new Date(y,0,1);
        var prevOffset = 7 + 1 - prevNewYear.getDay();
       // if (prevOffset == 2 || prevOffset == 8) weeknum = 53; else weeknum = 52; // tweak line below
    weekNo = (prevOffset == 2 || prevOffset == 8) ? 1 : 0;
    }
	//if (makeDay(y,0,1) < 5) ++weekNo;
    return weekNo;
}
/*
Date.prototype.getWeek = function () {
/ * getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com * /

var newYear = new Date(this.getFullYear(),0,1);
var day = newYear.getDay() - 1; //the day of week the year begins on
day = (day >= 0 ? day : day + 7);
var daynum = Math.floor((this.getTime()-newYear.getTime() - (this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
var weeknum;
//if the year starts before the middle of a week
if(day < 4)
{
	weeknum = Math.floor((daynum+day-1)/7) + 1;
	if(weeknum > 52)
	{
		nYear = new Date(this.getFullYear() + 1,0,1);
		nday = nYear.getDay() - 1;
		nday = nday >= 0 ? nday : nday + 7;
		/*if the next year starts before the middle of
		the week, it is week #1 of that year* /
		/ * weeknum = nday < 4 ? 1 : 53; * /  // tweak line below
		weeknum = (nday < 4) ? 0 : 1;
	}
}
else 
{
	weeknum = Math.floor((daynum+day -1 )/7);
	if(weeknum == 0)
	{
		prevYear = new Date(this.getFullYear()-1,0,1);
		prevDay = prevYear.getDay()-1;
		prevDay = (prevDay >= 0 ? prevDay : prevDay + 7);
		if( prevDay==3 || ( isLeapYear(prevYear.getFullYear()) && prevDay==2 ) )
		//{ weeknum = 53; }
		//	else weeknum = 52;  // tweak lines below
		{ weeknum = 0; }
			else weeknum = 1;
	}
}
return weeknum;
};
*/
