<%@LANGUAGE="JSCRIPT"%><% // // Display sunset and sunrise times for the current evening current place // // 22-Aug-11 rab Adapted from .vbs script // Created to run in a tiddler instead of in the console // Tweaked the SysJulianDate slightly (see below) // 23-Sep-11 rbd Part of standard ACP UI. Credit Berg! // 21-Sep-12 rbd GEM:871 Incorporate Robert Wahlström's high latitude changes // 02-Feb-13 esy updated to calculate the dusk and dawn for the // current Astronomical day. If past dawn it will // calculate the next instead (same as if it was past // local noon). Also, changed the calculator to be a // function, rather than a "printer". // 02-Feb-13 rab limited arccos test to be [-1 to +1] . // regression tested for mid-Winter high latitudes --> OK var RADIANS_MULTIPLE = 0.0174532925 // multiply by degrees to get radians var SUNSET = -0.833333 * RADIANS_MULTIPLE; // upper limb at horizon, includes refraction correction var CIVIL = -6.0 * RADIANS_MULTIPLE; // need artificial illumination to read outside var NAUTICAL = -12.0 * RADIANS_MULTIPLE; // navigation using sea horizon no longer possible var AMATEUR = -15.0 * RADIANS_MULTIPLE; // dark enough for most astronomical observations var ASTRONOMICAL = -18.0 * RADIANS_MULTIPLE; // sky is completely dark var JULIAN_HOUR = 0.0417 // 1 hour as a fraction of a Julian Day var JULIAN_SECOND = 0.0000115741 // 1 second as a fraction of a Julian Day var DAWN = true ; var DUSK = false; // set some vars to make code cleaner for dawn or dusk var TODAY = false ; var TOMORROW = true; function this_twilight(theta_S, dawn_or_dusk, next_day) { // takes the solar elevation angle in radians and returns the // twilight ends (dusk) or starts (dawn) during this "astronomical day". var KT = new ActiveXObject("Kepler.Ephemeris"); // Re-usable Earth ephem (reverse = Sun!) KT.BodyType = 0; KT.Number = 3; // This is a Planet. Earth. var tvec = new ActiveXObject("NOVAS.PositionVector"); var latitude = Telescope.SiteLatitude * RADIANS_MULTIPLE; var JD = Util.SysJulianDate; // Current UT; Start with tomorrow's date/Time var LOCAL_JD = JD - (Util.SysUTCOffset * JULIAN_HOUR) ; var LOCAL_JDN = Math.floor(LOCAL_JD); // Are we looking for a dawn or dsuk calculation? if (dawn_or_dusk) JD = LOCAL_JDN + 1; else JD = LOCAL_JDN; // similarly, this is here to do the next astronomical day if we // are already past dawn. if (next_day) JD = JD + 1; else JD = JD; var JDPrev = LOCAL_JDN; do { // Iterate through until we converge on a solution. var KA = KT.GetPositionAndVelocity(JD).toArray(); // Get Earth from Sun // Reverse cartesian vector for Sun from Earth tvec.x = -KA[0]; tvec.y = -KA[1]; tvec.z = -KA[2]; // J2000 coordinates of Sun from Earth var right_ascension_sun = tvec.RightAscension; var declination_sun = tvec.Declination * RADIANS_MULTIPLE; var HA = (Math.sin(theta_S) - (Math.sin(latitude) * Math.sin(declination_sun))) / (Math.cos(latitude) * Math.cos(declination_sun)); if (HA >-1.0 && HA <1.0) { HA = Math.acos(HA) / RADIANS_MULTIPLE; // HA in degrees } else { return "//N/A at this latitude//"; // a bust! no solution for this latitude for today or tomorrow. } if (dawn_or_dusk) HA = -HA; // if for dawn, invert the position of the sun. var LMST = Util.Julian_GMST(JD) + (Telescope.SiteLongitude / 15.0); JD = JD + (((HA / 15.0) - Util.HourAngle12(right_ascension_sun, LMST)) / 24.0); if (Math.abs(JD - JDPrev) < JULIAN_SECOND) { break; // Convergence to ~1 second accuracy breaks out of while loop } JDPrev = JD; } while(true); KT = null; tvec = null ; // Explicitly release these return new Date(Util.Julian_Date(JD)); } if (Util.Julian_Date(Util.SysJulianDate) > this_twilight(SUNSET, DAWN, TODAY)) { Response.write("It's After Dawn!\n"); Response.write("Here are the //coming// day's sunset and sunrise times for //" + Prefs.SiteName + "//\n" ); Response.write("|>|!Dusk|" + ">|!Dawn|"); Response.write("\n| Sunset is| " + this_twilight(SUNSET, DUSK, TOMORROW) + " | " + this_twilight(SUNSET, DAWN, TOMORROW) + " |is Sunrise |"); Response.write("\n| Civil twilight ends| " + this_twilight(CIVIL, DUSK, TOMORROW) + " | " + this_twilight(CIVIL, DAWN, TOMORROW) + " |begins Civil twilight |"); Response.write("\n| Nautical twilight ends| " + this_twilight(NAUTICAL, DUSK, TOMORROW) + " | " + this_twilight(NAUTICAL, DAWN, TOMORROW) + " |begins Nautical twilight |"); Response.write("\n| Amateur twilight ends| " + this_twilight(AMATEUR, DUSK, TOMORROW) + " | " + this_twilight(AMATEUR, DAWN, TOMORROW) + " |begins Amateur twilight |"); Response.write("\n| Astronomical twilight ends| " + this_twilight(ASTRONOMICAL, DUSK, TOMORROW) + " | " + this_twilight(ASTRONOMICAL, DAWN, TOMORROW) + " |begins Astronomical twilight |"); } else { Response.write("Here are //today's// sunset and //tomorrow's// sunrise times for //" + Prefs.SiteName + "//\n" ); Response.write("|>|!Dusk|" + ">|!Dawn|"); Response.write("\n| Sunset is| " + this_twilight(SUNSET, DUSK, TODAY) + " | " + this_twilight(SUNSET, DAWN, TODAY) + " |is Sunrise |"); Response.write("\n| Civil twilight ends| " + this_twilight(CIVIL, DUSK, TODAY) + " | " + this_twilight(CIVIL, DAWN, TODAY) + " |begins Civil twilight |"); Response.write("\n| Nautical twilight ends| " + this_twilight(NAUTICAL, DUSK, TODAY) + " | " + this_twilight(NAUTICAL, DAWN, TODAY) + " |begins Nautical twilight |"); Response.write("\n| Amateur twilight ends| " + this_twilight(AMATEUR, DUSK, TODAY) + " | " + this_twilight(AMATEUR, DAWN, TODAY) + " |begins Amateur twilight |"); Response.write("\n| Astronomical twilight ends| " + this_twilight(ASTRONOMICAL, DUSK, TODAY) + " | " + this_twilight(ASTRONOMICAL, DAWN, TODAY) + " |begins Astronomical twilight |"); } Response.write("\n----\n"); Response.Write("//~~Contributed by Dick Berg, author of the [[ACP Reference Guide|http://solo.dc3.com/ar/ACPRefGuide.html]]~~//\n"); Response.Write("//^^Computational improvements by Robert Wahlstrom and Erik Young^^//"); %>