function moonEphemeris(year, month, day, latitude, longitude) {

// This function will calculate orbital data for Moon base of the
// date and location passed in.
// Latitude and longitude should be passed in radians.
	
	var dataArray = new Array();
	var h  = -0.833;
	
// Calculate the day number

	var d = calcDayNumber(year, month, day) + 1.5;
	
// Get the Sun's position.  It will be needed for Moon's ephemeris.

	var sunData = new Array();
	sunData = sunEphemeris(year, month, day, latitude, longitude);
		
// Calculate the orbital parameters for the given day.

	var o = obliquity(d);
	var N = NMoon(d);
	var i = iMoon(d);
	var w = wMoon(d);
	var a = aMoon(d);
	var e = eMoon(d);
	var M = MMoon(d);
		
// Calculate the eclipse values.

	var L = LMoon(d);
	var E = Ecc(e, M);
	
	var x = a * (Math.cos(E) - e);
	var y = a * (Math.sin(E) * Math.sqrt(1.0 - Math.pow(e, 2)));
	var r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
	var v = Math.atan2(y, x);
	v = normalize(v, 2 * Math.PI);
		
// Calculate the geocentric ecliptical coordinates.

	var xGeoEcl = r * (Math.cos(N) * Math.cos(v + w) - Math.sin(N) * Math.sin(v + w) * Math.cos(i));
	var yGeoEcl = r * (Math.sin(N) * Math.cos(v + w) + Math.cos(N) * Math.sin(v + w) * Math.cos(i));
	var zGeoEcl = r * Math.sin(v + w) * Math.sin(i);
	
// Calculate the geocentric spherical coordinates.

	var lonGeoEcl = Math.atan2(yGeoEcl, xGeoEcl);
	lonGeoEcl = lonGeoEcl + lonPerturMoon(d);
	lonGeoEcl = normalize(lonGeoEcl, 2 * Math.PI);
	var latGeoEcl = Math.atan2(zGeoEcl, Math.sqrt( Math.pow(yGeoEcl, 2) + Math.pow(xGeoEcl, 2) ));
	latGeoEcl = latGeoEcl + latPerturMoon(d);
	latGeoEcl = normalize(latGeoEcl, 2 * Math.PI);
	var RGeoEcl = Math.sqrt( Math.pow(xGeoEcl, 2) + Math.pow(yGeoEcl, 2) + Math.pow(zGeoEcl, 2) );
	RGeoEcl = RGeoEcl + RPerturMoon(d);
	
// Re-calculate the geocentric ecliptical coordinates.

	var xGeoEcl = RGeoEcl * Math.cos(lonGeoEcl) * Math.cos(latGeoEcl);
	var yGeoEcl = RGeoEcl * Math.sin(lonGeoEcl) * Math.cos(latGeoEcl);
	var zGeoEcl = RGeoEcl * Math.sin(latGeoEcl);

// Calculate the geocentric equitorial coordinates.

	var xGeoEqu = xGeoEcl;
	var yGeoEqu = yGeoEcl * Math.cos(o) - zGeoEcl * Math.sin(o);
	var zGeoEqu = yGeoEcl * Math.sin(o) + zGeoEcl * Math.cos(o);
	
// Calculate the right accension, declination and distance.

	var R   = Math.sqrt(Math.pow(xGeoEqu, 2) + Math.pow(yGeoEqu, 2) + Math.pow(zGeoEqu, 2));
	var RA  = Math.atan2(yGeoEqu, xGeoEqu);
	RA = normalize(RA, 2 * Math.PI);
	var Dec = Math.asin(zGeoEqu / R);
	Dec = normalize(Dec, 2 * Math.PI);
	
// Calculate the elongation, percent illumination, apparent diameter and magnitude.

	var lonGeoEclSun = Math.atan2(sunData[1], sunData[0]);
	lonGeoEclSun = normalize(lonGeoEclSun, 2 * Math.PI);
	var elongation = Math.acos(Math.cos(lonGeoEclSun - lonGeoEcl) * Math.cos(latGeoEcl));
	
	var FV = Math.PI - elongation;
		
	var pctIllumination = (Math.PI - FV) / Math.PI * 100;
	
	var aprntDiameter = 1873.7 / 60 / R;
	
	FV = radToDeg(FV);
	var magnitude = "Not Available";

// Calculate the rise, south and set time.

	var L = LSun(d);
	var UTSouth = RA - L + Math.PI - longitude;
	UTSouth = UTSouth / degToRad(15.04107);
	UTSouth = normalize(UTSouth, 24);
	
	var LHA = (Math.sin(degToRad(h)) - Math.sin(latitude) * Math.sin(Dec)) /
		(Math.cos(latitude) * Math.cos(Dec));
	if (LHA <= -1) {
		UTRise = "Always Up"
		UTSet  = "Always Up"
		}
	else if (LHA >= 1) {
		UTRise = "Always Set"
		UTSet  = "Always Set"
		}
	else {
		LHA = Math.acos(LHA);
		LHA = LHA / degToRad(15.04107);
	
		var UTRise = UTSouth - LHA;
		UTRise = normalize(UTRise, 24);
		var UTSet  = UTSouth + LHA;
		UTSet = normalize(UTSet, 24);
		}
	
	dataArray[0]  = xGeoEcl;
	dataArray[1]  = yGeoEcl;
	dataArray[2]  = zGeoEcl;
	dataArray[3]  = RA;
	dataArray[4]  = Dec;
	dataArray[5]  = R;
	dataArray[6]  = elongation;
	dataArray[7]  = aprntDiameter;
	dataArray[8]  = magnitude;
	dataArray[9]  = pctIllumination;
	dataArray[10] = UTRise;
	dataArray[11] = UTSouth;
	dataArray[12] = UTSet;
	
	return dataArray;
			
	}
	
function aMoon(d) {

// Calculate the Mean Distance, a, for Moon.  Input is the day number, d. 

	var a1 = 60.2666;
	var a2 = 0;
	var a  = 0;
	
	a = a1 + a2 * d;
	
	return a;
	}

function eMoon(d) {

// Calculate the Longitude of Perihelion, w, for Moon.  Input is the day number, d.

	var e1 = 0.054900;
	var e2 = 0;
	var e  = 0;
	
	e = e1 + e2 * d;
	
	return e;
	}

function NMoon(d) {

// Calculate the Logitude of Accending Node, N, for Moon.  Input is the day number, d. 

	var N1 = 125.1228;
	var N2 = -0.0529538083;
	var N  = 0;
	
	N1 = degToRad(N1);
	N2 = degToRad(N2);	
	N  = N1 + N2 * d;
	N  = normalize(N, 2 * Math.PI);
	
	return N;
	}
	
function iMoon(d) {

// Calculate the Inclination, i, for Moon.  Input is the day number, d. 

	var i1 = 5.1454;
	var i2 = 0;
	var i  = 0;
	
	i1 = degToRad(i1);
	i2 = degToRad(i2);	
	i  = i1 + i2 * d;
	i  = normalize(i, 2 * Math.PI);
	
	return i;
	}
	
function wMoon(d) {

// Calculate the Longitude of Perihelion, w, for Moon.  Input is the day number, d.

	var w1 = 318.0634;
	var w2 = 0.1643573223;
	var w  = 0;
	
	w1 = degToRad(w1);
	w2 = degToRad(w2);	
	w  = w1 + w2 * d;
	w  = normalize(w, 2 * Math.PI);
	
	return w;
	}

function LMoon(d) {

// Calculate the Mean Logitude, L, for Moon.  Input is the day number, d. 

	var N = NMoon(d);	
	var M = MMoon(d);	
	var w = wMoon(d);
	
	var L = N + M + w;
	L = normalize(L, 2 * Math.PI);
	
	return L;
	}
	
function MMoon(d) {

// Calculate the Mean Logitude, L, for Moon.  Input is the day number, d. 

	var M1 = 115.3654;
	var M2 = 13.0649929509;
	var M  = 0;
	
	M1 = degToRad(M1);
	M2 = degToRad(M2);	
	M  = M1 + M2 * d;
	M  = normalize(M, 2 * Math.PI);
	
	return M;
	}
	
function lonPerturMoon(d) {

// Calculate the geoentric longitudinal perturbation for Moon.
// Input is the day number, d.

	var Lm = LMoon(d);
	var Ls = LSun(d);
	var Mm = MMoon(d);
	var Ms = MSun(d);
	var N  = NMoon(d);
	var D  = Lm - Ls;
	var F  = Lm - N;
	var perturbation = 0;
	
// Calculate the perturbation.
	
	perturbation = degToRad(-1.274) * Math.sin(Mm - 2 * D);
	perturbation = perturbation + degToRad(0.658)  * Math.sin(2 * D);
	perturbation = perturbation + degToRad(-0.186) * Math.sin(Ms);
	perturbation = perturbation + degToRad(-0.059) * Math.sin(2 * Mm - 2 * D);
	perturbation = perturbation + degToRad(-0.057) * Math.sin(Mm - 2 * D + Ms);
	perturbation = perturbation + degToRad(0.053)  * Math.sin(Mm + 2 * D);
	perturbation = perturbation + degToRad(0.046)  * Math.sin(2 * D - Ms);
	perturbation = perturbation + degToRad(0.041)  * Math.sin(Mm - Ms);
	perturbation = perturbation + degToRad(-0.035) * Math.sin(D);
	perturbation = perturbation + degToRad(-0.031) * Math.sin(Mm + Ms);
	perturbation = perturbation + degToRad(-0.015) * Math.sin(2 * F - 2 * D);
	perturbation = perturbation + degToRad(0.011)  * Math.sin(Mm - 4 * D);
		
	return perturbation;
	}
	
function latPerturMoon(d) {

// Calculate the geoentric latitudinal perturbation for Moon.
// Input is the day number, d.

	var Lm = LMoon(d);
	var Ls = LSun(d);
	var Mm = MMoon(d);
	var Ms = MSun(d);
	var N  = NMoon(d);
	var D  = Lm - Ls;
	var F  = Lm - N;
	var perturbation = 0;
	
// Calculate the perturbation.
	
	perturbation = degToRad(-0.173) * Math.sin(F - 2 * D);
	perturbation = perturbation + degToRad(-0.055) * Math.sin(Mm - F - 2 * D);
	perturbation = perturbation + degToRad(-0.046) * Math.sin(Mm + F - 2 * D);
	perturbation = perturbation + degToRad(0.033)  * Math.sin(F + 2 * D);
	perturbation = perturbation + degToRad(0.017)  * Math.sin(2 * Mm + F);
			
	return perturbation;
	}
	
function RPerturMoon(d) {

// Calculate the geoentric distance perturbation for Moon.
// Input is the day number, d.

	var Lm = LMoon(d);
	var Ls = LSun(d);
	var Mm = MMoon(d);
	var Ms = MSun(d);
	var N  = NMoon(d);
	var D  = Lm - Ls;
	var F  = Lm - N;
	var perturbation = 0;
	
// Calculate the perturbation.
	
	perturbation = -0.58 * Math.cos(Mm - 2 * D);
	perturbation = perturbation + -0.46 * Math.cos(2 * D);
				
	return perturbation;
	}
