Code:
<%@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
//
// 05-Feb-14 Mod By Jonas Grinde to add durations of each twilight to the table
// and adding day/night map with observatory location marked
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 cdiff(JulianStart, JulianEnd) {
// Calculates the difference between two Julian Dates
// and returns the result as hh:mm:ss
var diff = JulianEnd - JulianStart;
var msec = diff;
var hh = Math.floor(msec / 1000 / 60 / 60);
msec -= hh * 1000 * 60 * 60;
var mm = Math.floor(msec / 1000 / 60);
msec -= mm * 1000 * 60;
var ss = Math.floor(msec / 1000);
msec -= ss * 1000;
TimeDiff = hh + "h" + mm + "m" + ss + "s";
return TimeDiff;
}
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" + "|!Duration|" + ">|!Dawn|");
Response.write("\n| Sunset is| " + this_twilight(SUNSET, DUSK, TOMORROW) + " | " + cdiff(this_twilight(SUNSET, DUSK, TOMORROW), this_twilight(SUNSET, DAWN, TOMORROW)) + " |" + this_twilight(SUNSET, DAWN, TOMORROW) + " |is Sunrise |");
Response.write("\n| Civil twilight ends| " + this_twilight(CIVIL, DUSK, TOMORROW) + " | " + cdiff(this_twilight(CIVIL, DUSK, TOMORROW), this_twilight(CIVIL, DAWN, TOMORROW)) + " |" + this_twilight(CIVIL, DAWN, TOMORROW) + " |begins Civil twilight |");
Response.write("\n| Nautical twilight ends| " + this_twilight(NAUTICAL, DUSK, TOMORROW) + " | " + cdiff(this_twilight(NAUTICAL, DUSK, TOMORROW), this_twilight(NAUTICAL, DAWN, TOMORROW)) + " |" + this_twilight(NAUTICAL, DAWN, TOMORROW) + " |begins Nautical twilight |");
Response.write("\n| Amateur twilight ends| " + this_twilight(AMATEUR, DUSK, TOMORROW) + " | " + cdiff(this_twilight(AMATEUR, DUSK, TOMORROW), this_twilight(AMATEUR, DAWN, TOMORROW)) + " |" + this_twilight(AMATEUR, DAWN, TOMORROW) + " |begins Amateur twilight |");
Response.write("\n| Astronomical twilight ends| " + this_twilight(ASTRONOMICAL, DUSK, TOMORROW) + " | " + cdiff(this_twilight(ASTRONOMICAL, DUSK, TOMORROW), this_twilight(ASTRONOMICAL, DAWN, 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" + "|!Duration|" + ">|!Dawn|");
Response.write("\n| Sunset is| " + this_twilight(SUNSET, DUSK, TODAY) + " | " + cdiff(this_twilight(SUNSET, DUSK, TODAY), this_twilight(SUNSET, DAWN, TODAY)) + " |" + this_twilight(SUNSET, DAWN, TODAY) + " |is Sunrise |");
Response.write("\n| Civil twilight ends| " + this_twilight(CIVIL, DUSK, TODAY) + " | " + cdiff(this_twilight(CIVIL, DUSK, TODAY), this_twilight(CIVIL, DAWN, TODAY)) + " |" + this_twilight(CIVIL, DAWN, TODAY) + " |begins Civil twilight |");
Response.write("\n| Nautical twilight ends| " + this_twilight(NAUTICAL, DUSK, TODAY) + " | " + cdiff(this_twilight(NAUTICAL, DUSK, TODAY), this_twilight(NAUTICAL, DAWN, TODAY)) + " |" + this_twilight(NAUTICAL, DAWN, TODAY) + " |begins Nautical twilight |");
Response.write("\n| Amateur twilight ends| " + this_twilight(AMATEUR, DUSK, TODAY) + " | " + cdiff(this_twilight(AMATEUR, DUSK, TODAY), this_twilight(AMATEUR, DAWN, TODAY)) + " |" + this_twilight(AMATEUR, DAWN, TODAY) + " |begins Amateur twilight |");
Response.write("\n| Astronomical twilight ends| " + this_twilight(ASTRONOMICAL, DUSK, TODAY) + " | " + cdiff(this_twilight(ASTRONOMICAL, DUSK, TODAY), this_twilight(ASTRONOMICAL, DAWN, TODAY)) + " |" + this_twilight(ASTRONOMICAL, DAWN, TODAY) + " |begins Astronomical twilight |");
}
Response.write("\n----\n");
var MapX = (Math.round(-2+((Telescope.SiteLongitude+180)*(720/360))));
var MapY = (Math.round(20+(((Telescope.SiteLatitude*-1)+90)*(360/180))));
Response.Write("<html><style>");
Response.Write(".marker{position:relative;left:" + MapX + "px;top:" + MapY + "px;z-index:10;border:0px;opacity:1.00;}");
Response.Write(".map{position:relative;left:0px;top:0px;z-index:1;border:0px;}</style>");
Response.Write("<div class='marker'><font color=red><b>*</b></font> " + Prefs.SiteName + "</div>");
Response.Write("<div class='map'><IMG SRC=http://www.timeanddate.com/scripts/sunmap.php border=0></div></html>");
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, Erik Young, Jeffrey Jongmans and Jonas Grinde^^//");
%>