// flwg located at http://www.squ1.com/index.php?http://www.squ1.com/solar/solar-position.html
// I do not profess to understand any of it, I just adapted it to my own nefarious purposes :)

function computeSunTimes(what)
{
// Loc radians.
   var fLatitude;
   var fLongitude;
   var fTimeZone;

// Calculated data.
   var oToday;
   var fDifference;
   var fDeclination;
   var fEquation;

// Solar information.
   var fSunrise;
   var fSunset;

// Integer values.
   var iJulianDate;

// Temp data.
   var t, m, month, hour, minute, local_noon, test;

/********************* READ INPUT DATA ************************/

// Get location data.
   oToday     = new Date();
   fTimeZone  = parseFloat((oToday.getTimezoneOffset() / 60) * 15 * (Math.PI / 180.0));
   fLatitude  = parseFloat(52.9  * (Math.PI / 180.0));
   fLongitude = parseFloat( 5.23 * (Math.PI / 180.0));

   switch(oToday.getMonth())
   {
      case  0: month =   0; break;
      case  1: month =  31; break;
      case  2: month =  59; break;
      case  3: month =  90; break;
      case  4: month = 120; break;
      case  5: month = 151; break;
      case  6: month = 181; break;
      case  7: month = 212; break;
      case  8: month = 243; break;
      case  9: month = 273; break;
      case 10: month = 304; break;
      case 11: month = 334;
   }

// Get julian date.
   iJulianDate = parseInt(month + oToday.getDate());

/***************************** CALCULATE SOLAR VALUES ******************************/

// Preliminary check.
   if (iJulianDate > 365) iJulianDate -= 365;
   if (iJulianDate <   0) iJulianDate += 365;

// Secondary check of julian date.
   if (iJulianDate > 365) iJulianDate = 365;
   if (iJulianDate <   1) iJulianDate = 1;

// Calculate solar declination as per Carruthers et al.
   t = 2 * Math.PI * ((iJulianDate - 1) / 365.0);

   fDeclination =
   (
      0.322003
      - 22.971    * Math.cos(t)
      -  0.357898 * Math.cos(2*t)
      -  0.14398  * Math.cos(3*t)
      +  3.94638  * Math.sin(t)
      +  0.019334 * Math.sin(2*t)
      +  0.05928  * Math.sin(3*t)
   );

// Convert degrees to radians.
   if (fDeclination >  89.9) fDeclination =  89.9;
   if (fDeclination < -89.9) fDeclination = -89.9;

// Convert to radians.
   fDeclination = fDeclination * (Math.PI / 180.0);

// Calculate the equation of time as per Carruthers et al.
   t = (279.134 + 0.985647 * iJulianDate) * (Math.PI / 180.0);

   fEquation =
   (
      5.0323
      - 100.976  * Math.sin(t)
      + 595.275  * Math.sin(2*t)
      +   3.6858 * Math.sin(3*t)
      -  12.47   * Math.sin(4*t)
      - 430.847  * Math.cos(t)
      +  12.5024 * Math.cos(2*t)
      +  18.25   * Math.cos(3*t)
   );

// Convert seconds to hours.
   fEquation = fEquation / 3600.00;

// Calculate difference (in minutes) from reference longitude.
   fDifference = (((fLongitude - fTimeZone) * 180 / Math.PI) * 4) / 60.0;

// Convert solar noon to local noon.
   local_noon = 12.0 - fEquation - fDifference;

// Calculate angle normal to meridian plane.
   if (fLatitude >  (0.99 * (Math.PI / 2.0))) fLatitude =  (0.99 * (Math.PI / 2.0));
   if (fLatitude < -(0.99 * (Math.PI / 2.0))) fLatitude = -(0.99 * (Math.PI / 2.0));

   test = -Math.tan(fLatitude) * Math.tan(fDeclination);

        if (test < -1) t = Math.acos(-1.0) / (15 * (Math.PI / 180.0));
   else if (test >  1) t = Math.acos(1.0)  / (15 * (Math.PI / 180.0));
   else                t = Math.acos(-Math.tan(fLatitude) * Math.tan(fDeclination)) / (15 * (Math.PI / 180.0));

// Sunrise and sunset.
   fSunrise = local_noon - t;
   fSunset  = local_noon + t;

/******************************* OUTPUT DATA ****************************************/

   if (what == 'sunrise')
   {
   // Output sunrise time.
      t = Math.floor(fSunrise);
      m = Math.floor((fSunrise - t) * 60.0);
   }
   else
   {
   // Output sunset time.
      t = Math.floor(fSunset);
      m = Math.floor((fSunset - t) * 60.0);
   }

   return Date.UTC(oToday.getFullYear(), oToday.getMonth(), oToday.getDate(), t, m);
}

