﻿/***************************************************************************
 *
 * SunClass.js
 * 
 * This class calculates sunrise and sunset.
 *
 * Original PHP class sun_class.php
 * by Radek Piekarz
 * radziupiekarz@poczta.fm
 * (C) 2005 radzio
 * http://www.phpclasses.org/browse/package/2642.html
 *
 * Released under GNU General Public License (GPL)
 * http://www.opensource.org/licenses/gpl-license.html
 *
 * This script includes is_daylight_time() function from Steve Edberg
 * and perl code translated from the perl module Astro-SunTime-0.01.
 * 
 * Javascript version includes getDayOfYear function from  
 * Jochen Hilgers AS3 PhpDate Class.
 *
 * Ported from PHP to Javascript by Sudden 2008
 *
 ***************************************************************************/

/**************************************************************************
 *	Sun(latitude, longitude, timezone)

	Example:
	
	var paris=new Sun(48, 2, 1);
	
	document.write('Sun rises in Paris '+paris.sunrise());
	// Sun rises in Paris 08:34
	
	document.write('Sun sets in Paris '+paris.sunset());
	// Sun sets in Paris 21:34
 *	
 *
***************************************************************************/

function Sun(vLat, vLong, vTime){

	var latitude = vLat;
	var longitude = vLong;
	var timezone = vTime;

	var yday;
	var mon;
	var mday;
	var year;

	var wday;
	var hour;
	var min;

	var DST;

	var A;
	var B;
	var C;
	var D;
	var E;
	var F;
	var G;
	var J;
	var K;
	var L;
	var M;
	var P;
	var Q;
	var R;
	var S;
	var T;
	var U;
	var V;

	var date = new Date();

	/* getDayOfYear From Jochen Hilgers AS3 PhpDate Class	*/
	getDayOfYear = function (){

		var _date = new Date();
	
		var firstDayOfYear = new Date( _date.getFullYear(), 0, 1 );
		var millisecondsOffset = _date.getTime() - firstDayOfYear.getTime();
		return Math.floor( millisecondsOffset / 86400000 ) ;
	}	


	yday = getDayOfYear();
	mon = date.getMonth()+1;
	mday = date.getDate();
	year = date.getFullYear();
	wday = date.getDay();
	hour = date.getHours();		
	min = date.getMinutes();
	
	is_daylight_time = function (){

		var retval = true;
		if (mon > 4 && mon < 10){
			retval = true;        // May thru September
		}else if (mon == 4 && mday > 7){
			retval = true;        // After first week in April
		}else if (mon == 4 && mday <= 7 && wday == 0 && hour >= 2){
			retval = true;        // After 2am on first Sunday (wday=0) in April
        }else if (mon == 4 && mday <= 7 && wday != 0 && (mday-wday > 0)){
			retval = true;        // After Sunday of first week in April
		}else if (mon == 10 && mday < 25){
 			retval = true;        // Before last week of October
		}else if (mon == 10 && mday >= 25 && wday == 0 && hour < 2){
			retval = true;        // Before 2am on last Sunday in October
		}else if (mon == 10 && mday >= 25 && wday != 0 && (mday-24-wday < 1) ){
			retval = true;        // Before Sunday of last week in October
		}else{
 			retval = false;
		}
		
	  return retval;

	}
			
	DST = is_daylight_time();
		
	if(DST){
		timezone = (timezone + 1);
	}

	if (timezone == "13"){
		timezone = "-11";
	}
						 
	A = 1.5708;
	B = 3.14159;
	C = 4.71239;
	D = 6.28319;
	E = 0.0174533 * latitude;
	F = 0.0174533 * longitude;
	G = 0.261799  * timezone;
		
	// For astronomical twilight, use
	// R =  -.309017;
	// For     nautical twilight, use
	// R =  -.207912;
	// For        civil twilight, use
	// R =  -.104528;
	// For     sunrise or sunset, use
	R = -.0145439;
	
	
	this.sunrise = function (){
	
			J = A;
			K = parseInt(yday)+((J-F)/D);			/// int(blir *10 annars...?)
			L = (K * .017202) - .0574039;              // Solar Mean Anomoly
			M = L + .0334405 * Math.sin(L);                // Solar True Longitude
			M += 4.93289 + (3.49066E-04) * Math.sin(2 * L);

			if (D == 0){
		    //trace("ERROR Trying to normalize with zero offset...");
			}
		
			while (M < 0){
		 		M = (M + D);
			}
			
			while (M >= D){
				M = (M - D);
		  	}
		
			if ((M / A) - parseInt(M / A) == 0){
				M += 4.84814E-06;
		  	}
		
			P = Math.sin(M) / Math.cos(M);      // Solar Right Ascension
		    P = Math.atan2(.91746 * P, 1);
		
			// Quadrant Adjustment
			if (M > C){
		 		P += D;
		  	}else{
		 		if (M > A){
		               P += B;
				}
		  	}

		    Q = .39782 * Math.sin(M);            // Solar Declination
		    Q = Q / Math.sqrt(-Q * Q + 1);     // This is how the original author wrote it!
		    Q = Math.atan2(Q, 1);
		    S = R - (Math.sin(Q) * Math.sin(E));
		    S = S / (Math.cos(Q) * Math.cos(E));
		
		    if (Math.abs(S) > 1){
				//trace('none');
			}     // Null phenomenon
		
		    S = S / Math.sqrt(-S * S + 1);
		    S = A - Math.atan2(S, 1);
		    S = D - S ;
		    T = S + P - 0.0172028 * K - 1.73364; // Local apparent time
		    U = T - F;                            // Universal timer
		    V = U + G;                            // Wall clock time
		
		    // Quadrant Determination
	        if (D == 0){
	                //trace("Trying to normalize with zero offset...");
			}
			
	        while (V < 0){
	        	V = (V + D);
	        }
	
	        while (V >= D){
	        	V = (V - D);
		    }
		
		    V = V * 3.81972;
		
			if(city == "madrid"){
				offset = 0.5;
				V += offset;
			}
			
		
		    hour = parseInt(V);
		    min  = parseInt(((V - hour) * 60) + 0.5);
			
			if (min == 60){
				min = 0;
				hour +=1;
			}
			
			if(hour<10){
				hour = '0'+hour;
			}
			
			if(min<10){
				min = '0'+min;
			}
			
			return(hour+":"+min);

	}

	this.sunset = function (){
			
			J =  C;
			K = parseInt(yday) + ((J - F) / D);
			L = (K * .017202) - .0574039;              // Solar Mean Anomoly
			M = L + .0334405 * Math.sin(L);                // Solar True Longitude
			M += 4.93289 + (3.49066E-04) * Math.sin(2 * L);
			if (D == 0){
				//trace( "Trying to normalize with zero offset...");
			}
			while (M < 0){
				M = (M + D);
			}
			while (M >= D){
				M = (M - D);
			}
			if ((M / A) - parseInt(M / A) == 0){
				M += 4.84814E-06;
			}
			
			P = Math.sin(M) / Math.cos(M);   // Solar Right Ascension
			P = Math.atan2(.91746 * P, 1);
			// Quadrant Adjustment
			if (M > C){
				P += D;
			}else{
				if (M > A){
					P += B;
				}
			}
			
			Q = .39782 * Math.sin(M);// Solar Declination
			Q = Q / Math.sqrt(-Q * Q + 1); // This is how the original author wrote it!
			Q = Math.atan2(Q, 1);
			S = R - (Math.sin(Q) * Math.sin(E));
			S = S / (Math.cos(Q) * Math.cos(E));
			
			if (Math.abs(S) > 1){
				//trace('none');
			} // Null phenomenon

			S = S / Math.sqrt(-S * S + 1);
			S = A - Math.atan2(S, 1);
			//S = D - S ;
			T = S + P - 0.0172028 * K - 1.73364; // Local apparent time
			U = T - F;// Universal timer
			V = U + G;// Wall clock time

			// Quadrant Determination
			if (D == 0){
			   // trace( "Trying to normalize with zero offset...");
			}
			while (V < 0){
				V = (V + D);
			}
			while (V >= D){
				V = (V - D);
			}
			V = V * 3.81972;
			
			
			if(city == "madrid"){
				offset =0.5;
				V += offset;
			}
			
			
			
			
			hour = parseInt(V);
			min  = parseInt(((V - hour) * 60) + 0.5);

			if (min == 60){
				min = 0;
				hour +=1;
			}
			if(hour<10){
				hour = '0'+hour;
			}

			if(min<10){
				min = '0'+min;
			}
			
			return(hour+":"+min);
		}

}
		
