
var R = 287;	// Gaskonstante Luft
var g = 9.81;
var omega = 7.292E-5;	// Winkelgeschwindigkeit Erde

function runde(x, n)
{
	n = Math.pow(10, n);
	x = Math.round(x*n);
	return x/n;
}

function degToRad(x)
{
	return (x/180)*Math.PI;
}


// Sättingungsdampfdruck in Abhängigkeit von der Temperatur
function SDD(T)
{
	var a, b;
	if(T >= 0)	// Sättigungsdampfdruck über Wasser
	{
		a = 7.5;
		b = 237.3;
	}
	else
	{
		a = 7.6;
		b = 240.7;
	}

	var sdd = 6.1078 * Math.exp(((a*T)/(b+T))/Math.LOG10E);

	return sdd;
}

// Dampfdruck in Abhängigkeit von der Temperatur und der relativen Feuchte
function DD(T, r)
{
	var sdd = SDD(T);
	var dd = r/100 * sdd;

	return dd;
}


function RHtoDP(T, r)
{
	var dd = DD(T, r);
	var a, b;

	if(T >= 0)
	{
		a = 7.5;
		b = 237.3;
	}
	else
	{
		a = 7.6;
		b = 240.7;
	}
	
	var c = Math.log(dd/6.1078) * Math.LOG10E;

	var Taupunkt = (b * c) / (a - c);

	return Taupunkt;

}


function DPtoRH(T, TD)
{
	var dd  = SDD(TD);
	var sdd = SDD(T);

	return 100 * (dd / sdd);
}

function berechneTT()
{
	if(document.TT.Temperatur.value == "")
	{
		alert("Bitte geben Sie eine Temperatur ein!");
		return;
	}
	var Temperatur = parseFloat(document.TT.Temperatur.value);

	if(document.TT.gesucht[0].checked == true && document.TT.Taupunkt.value == "")
	{
		var text = "Bitte geben Sie die Taupunkttemperatur ein,\n"
		text += "damit die relative Luftfeuchtigkeit berechnet werden kann.";
		alert(text);
		return;
	}	
	else if(document.TT.gesucht[1].checked == true && document.TT.RelativeFeuchte.value == "")
	{
		var text = "Bitte geben Sie die relative Luftfeuchtigkeit ein,\n"
		text += "damit die Taupunkttemperatur berechnet werden kann.";
		alert(text);
		return;
	}	



	if(document.TT.gesucht[0].checked == true)	// berechne relative Feuchte
	{
		var Taupunkt = DPtoRH(Temperatur, parseFloat(document.TT.Taupunkt.value));
		document.TT.RelativeFeuchte.value = runde(Taupunkt, 1);
	}	
	else if(document.TT.gesucht[1].checked == true)	// berechne Taupunkt
	{
		var Taupunkt = RHtoDP(Temperatur, parseFloat(document.TT.RelativeFeuchte.value));
		document.TT.Taupunkt.value = runde(Taupunkt, 1);
	}	

	var mw = 18.016;
	var RStern = 8314.3;
	var dd = 100 * DD(Temperatur, document.TT.RelativeFeuchte.value);
	var absFeuchte = 1000 * mw/RStern * dd/CelsiusToKelvin(Temperatur);
	document.TT.AbsFeuchte.value = runde(absFeuchte, 1);
}

function CelsiusToKelvin(T)
{
	return T + 273.15;
}

function berechneBaroE(T, z)
{
	return Math.exp(-(g*z)/(R*T));
}

function berechneBaro()
{
	if(document.BM.Temperatur.value == "")
	{
		alert("Bitte geben Sie die mittlere Temperatur in der Luftschicht ein!");
		return;
	}
	var Temperatur = CelsiusToKelvin(parseFloat(document.BM.Temperatur.value));

	if(document.BM.gesucht[0].checked == true &&
		(document.BM.p1.value == "" || document.BM.z.value == ""))
	{
		var text = "Bitte geben Sie den Luftdruck 2 und den Höhenunterschied an,\n"
		text += "damit der Luftdruck 1 berechnet werden kann.";
		alert(text);
		return;
	}	
	else if(document.BM.gesucht[1].checked == true &&
		(document.BM.p0.value == "" || document.BM.z.value == ""))
	{
		var text = "Bitte geben Sie den Luftdruck 1 und den Höhenunterschied an,\n"
		text += "damit der Luftdruck 2 berechnet werden kann.";
		alert(text);
		return;
	}	
	else if(document.BM.gesucht[2].checked == true &&
		(document.BM.p0.value == "" || document.BM.p1.value == ""))
	{
		var text = "Bitte geben Sie den Luftdruck 1 und den Luftdruck 2 an,\n"
		text += "damit der Höhenunterschied berechnet werden kann.";
		alert(text);
		return;
	}	



	if(document.BM.gesucht[0].checked == true)	// berechne Luftdruck 0
	{
		var p1  = parseFloat(document.BM.p1.value);
		var z = parseFloat(document.BM.z.value);
		var e = berechneBaroE(Temperatur, z);
		var p0 = p1 / e;
		document.BM.p0.value = runde(p0, 1);
		return;
	}	
	else if(document.BM.gesucht[1].checked == true)	// berechne Luftdruck 1
	{
		var p0  = parseFloat(document.BM.p0.value);
		var z = parseFloat(document.BM.z.value);
		var e = berechneBaroE(Temperatur, z);
		var p1 = p0 * e;
		document.BM.p1.value = runde(p1, 1);
		return;
	}	
	else if(document.BM.gesucht[2].checked == true)	// berechne Z
	{
		var p0  = parseFloat(document.BM.p0.value);
		var p1  = parseFloat(document.BM.p1.value);
		var z = (Temperatur*R)/g*Math.log(p0/p1);

		document.BM.z.value = runde(z, 1);
		return;
	}	
}

function berechneWindchill(showWarning)
{

	if(document.WC.Temperatur.value == "" || document.WC.v.value == "")
	{
		if(!showWarning)
		{
			return;
		}
		var text = "Bitte geben Sie die Temperatur und die Windgeschwindigkeit an,\n";
		text += "damit die empfundene Temperatur berechnet werden kann.";
		alert(text);
		return;
	}	



	var T  = parseFloat(document.WC.Temperatur.value);
	var v  = parseFloat(document.WC.v.value);
	if(document.WC.unit[0].checked)
	{
		v = v / 3.6;
	}
	else if(document.WC.unit[1].checked)
	{
		v = v * 1.852 / 3.6;
	}


	TF =  9.0 * T / 5.0 + 32.0;
	vmph = v * 2.237;	// m/s -> mph


	TWCold = (0.0817 * (3.71*(Math.sqrt(vmph)) + 5.81-0.25*vmph) * (TF-91.4) + 91.4);
	TWCnew = (35.74 + 0.6215*TF - 35.75*Math.pow(vmph,0.16) + 0.4275*TF*Math.pow(vmph,0.16) );

	TWCold = 5.0 * (TWCold - 32.0) / 9.0;
	TWCnew = 5.0 * (TWCnew - 32.0) / 9.0;

	TWCold = (vmph <= 4) ? T : TWCold;
	TWCnew = (vmph <= 3) ? T : TWCnew;

	document.WC.TWCnew.value = runde(TWCnew, 1);
	document.WC.TWCold.value = runde(TWCold, 1);

	return;
}


function berechneWind(showWarning)
{

	if(document.GW.Temperatur.value == "" ||
		document.GW.phi.value == "" ||
		document.GW.p.value == "" ||
		document.GW.dp.value == "" ||
		document.GW.dn.value == "")
	{
		if(!showWarning)
		{
			return;
		}
		var text = "Bitte geben Sie alle Parameter an,\n";
		text += "damit die Windgeschwindigkeit berechnet werden kann.";
		alert(text);
		return;
	}	



	var T  = parseFloat(document.GW.Temperatur.value);
	T = CelsiusToKelvin(T);
	var phi  = parseFloat(document.GW.phi.value);
	var p  = parseFloat(document.GW.p.value);
	var dp  = parseFloat(document.GW.dp.value);
	var dn  = parseFloat(document.GW.dn.value) * 1000;	// km -> m

	var v = (R * T * dp) / (2 * omega * Math.sin(degToRad(phi)) * p * dn);

	if(document.GW.unit[0].checked)
	{
		v = v * 3.6;
	}
	else if(document.GW.unit[1].checked)
	{
		v = v * 3.6 / 1.852;
	}

	document.GW.v.value = runde(v, 1);
	return;

}


/**********************/
/* Sunset Calculation */
/**********************/

function month(name, numdays, abbr) 
{
	this.name = name;
	this.numdays = numdays;
	this.abbr = abbr;
}

function ans(daySave,value)
{
	this.daySave = daySave;
	this.value = value;
}


function city(name, lat, lng)
{
	this.name = name;
	this.lat = lat;
	this.lng = lng;
}



function setLatLong(f, index)
{
	f["latDeg"].value = City[index].lat;
	f["lonDeg"].value = City[index].lng;

	f["latMin"].value = 0;
	f["latSec"].value = 0;
	f["lonMin"].value = 0;
	f["lonSec"].value = 0;

	convLatLong(f);
}


function isLeapYear(yr) 
{
	return ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0);
}


function isPosInteger(inputVal) 
{
	inputStr = "" + inputVal;
	for (var i = 0; i < inputStr.length; i++) {
		var oneChar = inputStr.charAt(i);
		if (oneChar < "0" || oneChar > "9")
			return false;
	}
	return true;
}

function isInteger(inputVal) 
{
	inputStr = "" + inputVal;
	if(inputStr == "NaN") return false;
	if(inputStr == "-NaN") return false;
	for (var i = 0; i < inputStr.length; i++) 
	{
		var oneChar = inputStr.charAt(i);
		if (i == 0 && (oneChar == "-" || oneChar == "+"))
		{
			continue;
		}
		if (oneChar < "0" || oneChar > "9")
		{
			return false;
		}
	}
	return true;
}



function isNumber(inputVal) 
{
	var oneDecimal = false;
	var inputStr = "" + inputVal;
	for (var i = 0; i < inputStr.length; i++) 
	{
		var oneChar = inputStr.charAt(i);
		if (i == 0 && (oneChar == "-" || oneChar == "+"))
		{
			continue;
		}
		if (oneChar == "." && !oneDecimal) 
		{
			oneDecimal = true;
			continue;
		}
		if (oneChar < "0" || oneChar > "9")
		{
			return false;
		}
	}
	return true;
}



function isValidInput(f, index, latLongForm) 
{
	if (f["day"].value == "") 
	{
		alert("Bitte geben Sie ein Datum ein.");
		return false;
	}
	else if (f["year"].value == "") 
	{
		alert("Bitte geben Sie ein Datum ein.");
		return false;
	}
	else if (!isPosInteger(f["day"].value) || f["day"].value == 0)
	{
		alert("Der Tag muss eine positive ganze Zahl sein.");
		return false;
	}
	else if (!isInteger(f["year"].value)) 
	{
		alert("Das Jahr muss eine positive ganze Zahl sein.");
		return false;
	}
	else if ( (f["year"].value < -1000) || (f["year"].value > 3000) )
	{
		alert("Bitte geben Sie ein Jahr zwischen -1000 und 3000 ein.");
		return false;
	}
	else if ((index != 1) && (f["day"].value > monthList[index].numdays)) 
	{
		alert("Es gibt nur " + monthList[index].numdays + " Tage im " 
			+ monthList[index].name + ".");
		return false;
	}
	else if (index == 1) 
	{
		if (isLeapYear(f["year"].value)) {
			if (f["day"].value > (monthList[index].numdays + 1)) 
			{
				alert("Es gibt nur " + (monthList[index].numdays + 1) 
					+ " Tage im " + monthList[index].name + ".");
				return false;
			}
			else
				return true;
		}
		else 
		{
			if (f["day"].value > monthList[index].numdays) 
			{
				alert("Es gibt nur " + monthList[index].numdays 
					+ " Tage im " + monthList[index].name + ".");
				return false;
			}
			else
				return true;
		}
	}
	else 
		return true;	
}


function convLatLong(f)
{
	var neg = 0;
	if(f["latDeg"].value[0] == '-') 
	{
		neg = 1;
	}

	if(neg != 1)
	{
		var latSeconds = (parseFloat(f["latDeg"].value))*3600 
			+ parseFloat(f["latMin"].value)*60 
			+ parseFloat(f["latSec"].value)*1;

		f["latDeg"].value = Math.floor(latSeconds/3600);
		f["latMin"].value = Math.floor((latSeconds
			- (parseFloat(f["latDeg"].value)*3600))/60);
		f["latSec"].value = Math.floor((latSeconds
			- (parseFloat(f["latDeg"].value)*3600) 
			- (parseFloat(f["latMin"].value)*60)) + 0.5);
	}
	else if(parseFloat(f["latDeg"].value) > -1)
	{
		var latSeconds = parseFloat(f["latDeg"].value)*3600 
			- parseFloat(f["latMin"].value)*60 
			- parseFloat(f["latSec"].value)*1;

		f["latDeg"].value = "-0";
		f["latMin"].value = Math.floor((-latSeconds)/60);
		f["latSec"].value = Math.floor( (-latSeconds 
			- (parseFloat(f["latMin"].value)*60)) + 0.5);

	}
	else
	{
		var latSeconds = parseFloat(f["latDeg"].value)*3600 
			- parseFloat(f["latMin"].value)*60 
			- parseFloat(f["latSec"].value)*1;

		f["latDeg"].value = Math.ceil(latSeconds/3600);
		f["latMin"].value = Math.floor((-latSeconds
			+ (parseFloat(f["latDeg"].value)*3600))/60);
		f["latSec"].value = Math.floor((-latSeconds
			+ (parseFloat(f["latDeg"].value)*3600) 
			- (parseFloat(f["latMin"].value)*60)) + 0.5);
	}

	neg = 0;
	if(f["lonDeg"].value[0] == '-') 
	{
		neg = 1;
	}

	if(neg != 1)
	{
		var lonSeconds = parseFloat(f["lonDeg"].value)*3600 
			+ parseFloat(f["lonMin"].value)*60 
			+ parseFloat(f["lonSec"].value)*1;
		f["lonDeg"].value = Math.floor(lonSeconds/3600);
		f["lonMin"].value = Math.floor((lonSeconds
			- (parseFloat(f["lonDeg"].value)*3600))/60);
		f["lonSec"].value = Math.floor((lonSeconds
			- (parseFloat(f["lonDeg"].value)*3600)
			- (parseFloat(f["lonMin"].value))*60) + 0.5);
	}
	else if(parseFloat(f["lonDeg"].value) > -1)
	{
		var lonSeconds = parseFloat(f["lonDeg"].value)*3600 
			- parseFloat(f["lonMin"].value)*60 
			- parseFloat(f["lonSec"].value)*1;

		f["lonDeg"].value = "-0";
		f["lonMin"].value = Math.floor((-lonSeconds)/60);
		f["lonSec"].value = Math.floor((-lonSeconds
			- (parseFloat(f["lonMin"].value)*60)) + 0.5);
	}
	else
	{
		var lonSeconds = parseFloat(f["lonDeg"].value)*3600 
			- parseFloat(f["lonMin"].value)*60 
			- parseFloat(f["lonSec"].value)*1;
		f["lonDeg"].value = Math.ceil(lonSeconds/3600);
		f["lonMin"].value = Math.floor((-lonSeconds
			+ (parseFloat(f["lonDeg"].value)*3600))/60);
		f["lonSec"].value = Math.floor((-lonSeconds
			+ (parseFloat(f["lonDeg"].value)*3600)
			- (parseFloat(f["lonMin"].value)*60)) + 0.5);
	}

	if(latSeconds > 324000)
	{
		alert("Ungültiger Breitengrad.\nSetze 89.8.");
		f["latDeg"].value = 89.8;
		f["latMin"].value = 0;
		f["latSec"].value = 0;
	}
	if(latSeconds < -324000)
	{
		alert("Ungültiger Breitengrad.\nSetze -89.8.");
		f["latDeg"].value = -89.8;
		f["latMin"].value = 0;
		f["latSec"].value = 0;
	}
	if(lonSeconds > 648000)
	{
		alert("Ungültiger Längengrad.\nSetze 180.");
		f["lonDeg"].value = 180;
		f["lonMin"].value = 0;
		f["lonSec"].value = 0;
	}
	if(lonSeconds < -648000)
	{
		alert("Ungültiger Längengrad\n Setze -180.");
		f["lonDeg"].value = -180;
		f["lonMin"].value = 0;
		f["lonSec"].value =0;
	}

}


function radToDeg(angleRad) 
{
	return (180.0 * angleRad / Math.PI);
}

function degToRad(angleDeg) 
{
	return (Math.PI * angleDeg / 180.0);
}


function calcDayOfYear(mn, dy, lpyr) 
{
	var k = (lpyr ? 1 : 2);
	var doy = Math.floor((275 * mn)/9) - k * Math.floor((mn + 9)/12) + dy -30;
	return doy;
}


function calcDayOfWeek(juld)
{
	var A = (juld + 1.5) % 7;
	var DOW = (A==0)?"Sonntag":(A==1)?"Montag":(A==2)?"Dienstag":(A==3)?"Mittwoch":(A==4)?"Donnerstag":(A==5)?"Freitag":"Samstag";
	return DOW;
}


function calcJD(year, month, day)
{
	month++;
	if (month <= 2) {
		year -= 1;
		month += 12;
	}
	var A = Math.floor(year/100);
	var B = 2 - A + Math.floor(A/4);

	var JD = Math.floor(365.25*(year + 4716)) + Math.floor(30.6001*(month+1)) + day + B - 1524.5;
	return JD;
}



function calcDateFromJD(jd)
{
	var z = Math.floor(jd + 0.5);
	var f = (jd + 0.5) - z;

	if (z < 2299161) {
		var A = z;
	} else {
		alpha = Math.floor((z - 1867216.25)/36524.25);
		var A = z + 1 + alpha - Math.floor(alpha/4);
	}

	var B = A + 1524;
	var C = Math.floor((B - 122.1)/365.25);
	var D = Math.floor(365.25 * C);
	var E = Math.floor((B - D)/30.6001);

	var day = B - D - Math.floor(30.6001 * E) + f;
	var month = (E < 14) ? E - 1 : E - 13;
	var year = (month > 2) ? C - 4716 : C - 4715;

	return (day + "-" + monthList[month-1].name + "-" + year);
}



function calcDayFromJD(jd)
{
	var z = Math.floor(jd + 0.5);
	var f = (jd + 0.5) - z;

	if (z < 2299161) {
		var A = z;
	} else {
		alpha = Math.floor((z - 1867216.25)/36524.25);
		var A = z + 1 + alpha - Math.floor(alpha/4);
	}

	var B = A + 1524;
	var C = Math.floor((B - 122.1)/365.25);
	var D = Math.floor(365.25 * C);
	var E = Math.floor((B - D)/30.6001);

	var day = B - D - Math.floor(30.6001 * E) + f;
	var month = (E < 14) ? E - 1 : E - 13;
	var year = (month > 2) ? C - 4716 : C - 4715;

	return ((day<10 ? "0" : "") + day + monthList[month-1].abbr);
}


function calcTimeJulianCent(jd)
{
	var T = (jd - 2451545.0)/36525.0;
	return T;
}


function calcJDFromJulianCent(t)
{
	var JD = t * 36525.0 + 2451545.0;
	return JD;
}


function calcGeomMeanLongSun(t)
{
	var L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
	while(L0 > 360.0)
	{
		L0 -= 360.0;
	}
	while(L0 < 0.0)
	{
		L0 += 360.0;
	}
	return L0;
}


function calcGeomMeanAnomalySun(t)
{
	var M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
	return M;
}

function calcEccentricityEarthOrbit(t)
{
	var e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
	return e;
}


function calcSunEqOfCenter(t)
{
	var m = calcGeomMeanAnomalySun(t);

	var mrad = degToRad(m);
	var sinm = Math.sin(mrad);
	var sin2m = Math.sin(mrad+mrad);
	var sin3m = Math.sin(mrad+mrad+mrad);

	var C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289;
	return C;
}


function calcSunTrueLong(t)
{
	var l0 = calcGeomMeanLongSun(t);
	var c = calcSunEqOfCenter(t);

	var O = l0 + c;
	return O;
}

function calcSunTrueAnomaly(t)
{
	var m = calcGeomMeanAnomalySun(t);
	var c = calcSunEqOfCenter(t);

	var v = m + c;
	return v;
}

function calcSunRadVector(t)
{
	var v = calcSunTrueAnomaly(t);
	var e = calcEccentricityEarthOrbit(t);

	var R = (1.000001018 * (1 - e * e)) / (1 + e * Math.cos(degToRad(v)));
	return R;
}

function calcSunApparentLong(t)
{
	var o = calcSunTrueLong(t);

	var omega = 125.04 - 1934.136 * t;
	var lambda = o - 0.00569 - 0.00478 * Math.sin(degToRad(omega));
	return lambda;
}

function calcMeanObliquityOfEcliptic(t)
{
	var seconds = 21.448 - t*(46.8150 + t*(0.00059 - t*(0.001813)));
	var e0 = 23.0 + (26.0 + (seconds/60.0))/60.0;
	return e0;
}

function calcObliquityCorrection(t)
{
	var e0 = calcMeanObliquityOfEcliptic(t);

	var omega = 125.04 - 1934.136 * t;
	var e = e0 + 0.00256 * Math.cos(degToRad(omega));
	return e;
}

function calcSunRtAscension(t)
{
	var e = calcObliquityCorrection(t);
	var lambda = calcSunApparentLong(t);

	var tananum = (Math.cos(degToRad(e)) * Math.sin(degToRad(lambda)));
	var tanadenom = (Math.cos(degToRad(lambda)));
	var alpha = radToDeg(Math.atan2(tananum, tanadenom));
	return alpha;
}

function calcSunDeclination(t)
{
	var e = calcObliquityCorrection(t);
	var lambda = calcSunApparentLong(t);

	var sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda));
	var theta = radToDeg(Math.asin(sint));
	return theta;
}

function calcEquationOfTime(t)
{
	var epsilon = calcObliquityCorrection(t);
	var l0 = calcGeomMeanLongSun(t);
	var e = calcEccentricityEarthOrbit(t);
	var m = calcGeomMeanAnomalySun(t);

	var y = Math.tan(degToRad(epsilon)/2.0);
	y *= y;

	var sin2l0 = Math.sin(2.0 * degToRad(l0));
	var sinm   = Math.sin(degToRad(m));
	var cos2l0 = Math.cos(2.0 * degToRad(l0));
	var sin4l0 = Math.sin(4.0 * degToRad(l0));
	var sin2m  = Math.sin(2.0 * degToRad(m));

	var Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0
			- 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m;

	return radToDeg(Etime)*4.0;
}

function calcHourAngleSunrise(lat, solarDec)
{
	var latRad = degToRad(lat);
	var sdRad  = degToRad(solarDec)

	var HAarg = (Math.cos(degToRad(90.833))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad));

	var HA = (Math.acos(Math.cos(degToRad(90.833))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad)));

	return HA;
}


function calcHourAngleSunset(lat, solarDec)
{
	var latRad = degToRad(lat);
	var sdRad  = degToRad(solarDec)

	var HAarg = (Math.cos(degToRad(90.833))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad));

	var HA = (Math.acos(Math.cos(degToRad(90.833))/(Math.cos(latRad)*Math.cos(sdRad))-Math.tan(latRad) * Math.tan(sdRad)));

	return -HA;
}


function calcSunriseUTC(JD, latitude, longitude)
{
	var t = calcTimeJulianCent(JD);

	var eqTime = calcEquationOfTime(t);
	var solarDec = calcSunDeclination(t);
	var hourAngle = calcHourAngleSunrise(latitude, solarDec);

	var delta = longitude - radToDeg(hourAngle);
	var timeDiff = 4 * delta;
	var timeUTC = 720 + timeDiff - eqTime;

	var newt = calcTimeJulianCent(calcJDFromJulianCent(t) + timeUTC/1440.0); 
	eqTime = calcEquationOfTime(newt);
	solarDec = calcSunDeclination(newt);
	hourAngle = calcHourAngleSunrise(latitude, solarDec);
	delta = longitude - radToDeg(hourAngle);
	timeDiff = 4 * delta;
	timeUTC = 720 + timeDiff - eqTime;

	return timeUTC;
}


function calcSolNoonUTC(t, longitude)
{
	var newt = calcTimeJulianCent(calcJDFromJulianCent(t) + 0.5 + longitude/360.0); 

	var eqTime = calcEquationOfTime(t);
	var solarNoonDec = calcSunDeclination(t);
	var solNoonUTC = 720 + (longitude * 4) - eqTime;
	
	return solNoonUTC;
}


function calcSunsetUTC(JD, latitude, longitude)
{
	var t = calcTimeJulianCent(JD);

	var eqTime = calcEquationOfTime(t);
	var solarDec = calcSunDeclination(t);
	var hourAngle = calcHourAngleSunset(latitude, solarDec);

	var delta = longitude - radToDeg(hourAngle);
	var timeDiff = 4 * delta;
	var timeUTC = 720 + timeDiff - eqTime;

	var newt = calcTimeJulianCent(calcJDFromJulianCent(t) + timeUTC/1440.0); 
	eqTime = calcEquationOfTime(newt);
	solarDec = calcSunDeclination(newt);
	hourAngle = calcHourAngleSunset(latitude, solarDec);

	delta = longitude - radToDeg(hourAngle);
	timeDiff = 4 * delta;
	timeUTC = 720 + timeDiff - eqTime;

	return timeUTC;
}



function getLatitude(latLongForm)
{
	var neg = 0;
	var degs = parseFloat(latLongForm["latDeg"].value);
	if (latLongForm["latDeg"].value[0] == '-') 
	{
		neg = 1;
	}

	var mins = parseFloat(latLongForm["latMin"].value);

	var secs = parseFloat(latLongForm["latSec"].value);

	if(neg != 1)
	{
		var decLat = degs + (mins / 60) + (secs / 3600);
	} else if(neg == 1)
	{
		var decLat = degs - (mins / 60) - (secs / 3600);
	} else 
	{
		return -9999;
	}
	return decLat;
}	



function getLongitude(latLongForm)
{
	var neg = 0;
	var degs = parseFloat(latLongForm["lonDeg"].value);
	if (latLongForm["lonDeg"].value[0] == '-') 
	{
		neg = 1;
	}
	var mins = parseFloat(latLongForm["lonMin"].value);
	var secs = parseFloat(latLongForm["lonSec"].value);
	var decLon = degs + (mins / 60) + (secs / 3600);

	if(neg != 1)
	{
		var decLon = degs + (mins / 60) + (secs / 3600);
	} else if(neg == 1)
	{
		var decLon = degs - (mins / 60) - (secs / 3600);
	} else 
	{
		return -9999;
	}
	return decLon;
}	


function findRecentSunrise(jd, latitude, longitude)
{
	var julianday = jd;

	var time = calcSunriseUTC(julianday, latitude, longitude);
	while(!isNumber(time)){
		julianday -= 1.0;
		time = calcSunriseUTC(julianday, latitude, longitude);
	}

	return julianday;
}



function findRecentSunset(jd, latitude, longitude)
{
	var julianday = jd;

	var time = calcSunsetUTC(julianday, latitude, longitude);
	while(!isNumber(time)){
		julianday -= 1.0;
		time = calcSunsetUTC(julianday, latitude, longitude);
	}

	return julianday;
}


function findNextSunrise(jd, latitude, longitude)
{
	var julianday = jd;

	var time = calcSunriseUTC(julianday, latitude, longitude);
	while(!isNumber(time)){
		julianday += 1.0;
		time = calcSunriseUTC(julianday, latitude, longitude);
	}

	return julianday;
}


function findNextSunset(jd, latitude, longitude)
{
	var julianday = jd;

	var time = calcSunsetUTC(julianday, latitude, longitude);
	while(!isNumber(time)){
		julianday += 1.0;
		time = calcSunsetUTC(julianday, latitude, longitude);
	}

	return julianday;
}


function timeString(minutes)
{
	var floatHour = minutes / 60;
	var hour = Math.floor(floatHour);
	var floatMinute = 60 * (floatHour - Math.floor(floatHour));
	var minute = Math.floor(floatMinute);
	var floatSec = 60 * (floatMinute - Math.floor(floatMinute));
	var second = Math.floor(floatSec);

	var timeStr = hour + ":";
	if (minute < 10)
		timeStr += "0" + minute + ":";
	else
		timeStr += minute + ":";
	if (second < 10)
		timeStr += "0" + second;
	else
		timeStr += second;

	return timeStr;
}


function timeStringDate(minutes, JD, withDate)
{
	var julianday = JD;
	var floatHour = minutes / 60;
	var hour = Math.floor(floatHour);
	var floatMinute = 60 * (floatHour - Math.floor(floatHour));
	var minute = Math.floor(floatMinute);
	var floatSec = 60 * (floatMinute - Math.floor(floatMinute));
	var second = Math.floor(floatSec);

	var daychange = false;
	if (hour > 23) 
	{
		hour -= 24;
		julianday += 1.0;
		daychange = true;
	}

	if (hour < 0)
	{
		hour += 24;
		julianday -= 1.0;
		daychange = true;
	}

	var timeStr = hour + ":";
	if (minute < 10)
		timeStr += "0" + minute + ":";
	else
		timeStr += minute + ":";
	if (second < 10)
		timeStr += "0" + second;
	else
		timeStr += second;

	if (withDate || daychange) return timeStr + " " + calcDayFromJD(julianday);
	return timeStr;
}

	
function calcSun(riseSetForm, latLongForm, index) 
{
	adjustTimeOffset();

	if(index != 0)
	{
		setLatLong(latLongForm, index);
	}

	var latitude = getLatitude(latLongForm);
	var longitude = getLongitude(latLongForm);
	longitude = -longitude;	// E = +, W = - for Germany
	var indexRS = riseSetForm.mos.selectedIndex
	if (isValidInput(riseSetForm, indexRS, latLongForm)) 
	{
		if((latitude >= -90) && (latitude < -89.8))
		{
			alert("Alle Breitengrade zwischen -89.8 und -90 S\n werden auf -89.8 gesetzt");
			latLongForm["latDeg"].value = -89.8;
			latitude = -89.8;
		}
		if ((latitude <= 90) && (latitude > 89.8))
		{
			alert("Alle Breitengrade zwischen 89.8 und 90 N\n werden auf 89.8 gesetzt");
			latLongForm["latDeg"].value = 89.8;
			latitude = 89.8;
		}
		

		var JD = (calcJD(parseFloat(riseSetForm["year"].value), indexRS, parseFloat(riseSetForm["day"].value)));
		var dow = calcDayOfWeek(JD);
		var doy = calcDayOfYear(indexRS + 1, parseFloat(riseSetForm["day"].value), isLeapYear(riseSetForm["year"].value));
		var T = calcTimeJulianCent(JD);
		var alpha = calcSunRtAscension(T);
		var theta = calcSunDeclination(T);
		var Etime = calcEquationOfTime(T);


		var eqTime = Etime;
		var solarDec = theta;

		riseSetForm["eqTime"].value = (Math.floor(100*eqTime))/100;
		riseSetForm["solarDec"].value = (Math.floor(100*(solarDec)))/100;

		var nosunrise = false;

		var riseTimeGMT = calcSunriseUTC(JD, latitude, longitude);
		if (!isNumber(riseTimeGMT))
		{
			nosunrise = true;
		}


		var nosunset = false;
		var setTimeGMT = calcSunsetUTC(JD, latitude, longitude);
		if (!isNumber(setTimeGMT))
		{
			nosunset = true;
		}

		var zone = hrsToGMT;
		if(zone > 12 || zone < -12.5)
		{
			alert("Verschiebung gegenüber UTC muss zwischen -12.5 und 12 sein.  \n Setze \"Off-Set\"=0");
			zone = "0";
		}

		if (!nosunrise)
		{
			var riseTimeLST = riseTimeGMT - (60 * zone);	
			var riseStr = timeStringDate(riseTimeLST, JD, false);
			var utcRiseStr = timeStringDate(riseTimeGMT, JD, false);

			riseSetForm["sunrise"].value = riseStr;
			riseSetForm["utcsunrise"].value = utcRiseStr;
		}

		if(!nosunset)
		{
			var setTimeLST = setTimeGMT - (60 * zone);
			var setStr = timeStringDate(setTimeLST, JD, false);
			var utcSetStr = timeStringDate(setTimeGMT, JD, false);

			riseSetForm["sunset"].value = setStr;
			riseSetForm["utcsunset"].value = utcSetStr;
		}

		var solNoonGMT = calcSolNoonUTC(T, longitude);
		var solNoonLST = solNoonGMT - (60 * zone);

		var solnStr = timeString(solNoonLST);
		var utcSolnStr = timeString(solNoonGMT);

		riseSetForm["solnoon"].value = solnStr;
		riseSetForm["utcsolnoon"].value = utcSolnStr;
		
		convLatLong(latLongForm);

		if(nosunrise)
		{ 
			riseSetForm["utcsunrise"].value = "";

			if ( ((latitude > 66.4) && (doy > 79) && (doy < 267)) ||
			   ((latitude < -66.4) && ((doy < 83) || (doy > 263))) )
			{
				newjd = findRecentSunrise(JD, latitude, longitude);
				newtime = calcSunriseUTC(newjd, latitude, longitude)
					 - (60 * zone);
				if (newtime > 1440)
				{
					newtime -= 1440;
					newjd += 1.0;
				}
				if (newtime < 0)
				{
					newtime += 1440;
					newjd -= 1.0;
				}
				riseSetForm["sunrise"].value = 
					timeStringDate(newtime, newjd, true);
				riseSetForm["utcsunrise"].value = "vorheriger Sonnenaufgang";
			}
			else if ( ((latitude > 66.4) && ((doy < 83) || (doy > 263))) ||
				((latitude < -66.4) && (doy > 79) && (doy < 267)) )
			{
				newjd = findNextSunrise(JD, latitude, longitude);
				newtime = calcSunriseUTC(newjd, latitude, longitude)
					 - (60 * zone);
				if (newtime > 1440)
				{
					newtime -= 1440;
					newjd += 1.0;
				}
				if (newtime < 0)
				{
					newtime += 1440;
					newjd -= 1.0;
				}
				riseSetForm["sunrise"].value = 
					timeStringDate(newtime, newjd, true);
				riseSetForm["utcsunrise"].value = "nächster Sonnenaufgang";
			}
			else 
			{
				alert("Cannot Find Sunrise!");
			}

		}

		if(nosunset)
		{ 
			riseSetForm["utcsunset"].value = "";

			if ( ((latitude > 66.4) && (doy > 79) && (doy < 267)) ||
			   ((latitude < -66.4) && ((doy < 83) || (doy > 263))) )
			{
				newjd = findNextSunset(JD, latitude, longitude);
				newtime = calcSunsetUTC(newjd, latitude, longitude)
					 - (60 * zone);
				if (newtime > 1440)
				{
					newtime -= 1440;
					newjd += 1.0;
				}
				if (newtime < 0)
				{
					newtime += 1440;
					newjd -= 1.0;
				}
				riseSetForm["sunset"].value = 
					timeStringDate(newtime, newjd, true);
				riseSetForm["utcsunset"].value = "nächster Sonnenuntergang";
				riseSetForm["utcsolnoon"].value = "";
			}
			else if ( ((latitude > 66.4) && ((doy < 83) || (doy > 263))) ||
				((latitude < -66.4) && (doy > 79) && (doy < 267)) )
			{
				newjd = findRecentSunset(JD, latitude, longitude);
				newtime = calcSunsetUTC(newjd, latitude, longitude)
					 - (60 * zone);
				if (newtime > 1440)
				{
					newtime -= 1440;
					newjd += 1.0;
				}
				if (newtime < 0)
				{
					newtime += 1440;
					newjd -= 1.0;
				}
				riseSetForm["sunset"].value = 
					timeStringDate(newtime, newjd, true);
				riseSetForm["utcsunset"].value = "vorheriger Sonnenuntergang";
				riseSetForm["solnoon"].value = "N/A";
				riseSetForm["utcsolnoon"].value = "";
			}

			else 
			{
				alert ("Sonnenuntergang nicht gefunden!");
			}
		}
	}
}

function adjustTimeOffset()
{
	date = new Date(document.riseSetCalc.year.value,
		document.riseSetCalc.mos.selectedIndex,
		document.riseSetCalc.day.value, 12, 0, 0);

	hrsToGMT = date.getTimezoneOffset() / 60;
}

