<?php
/*
Sun/Moon Rise/Set and Twighlight Times Table For Any Year
*/
ob_start();
/* Define the program cookie name and set it to expire in 30 days.
This cookie can be shared by other programs in the same common
home folder together.
*/
$CookieName = 'Sun-Moon-Rise-Set-and-Twilight-Times-Table-For-Any-Year';
$SetToExpireIn30Days = time() + 30*86400;
// Define script path and filename.
$_AUTHOR_ = 'Jay Tanner';
$_PROGRAM_VERSION_ = ''; $at = "at"; $UTC = "UTC";
$_SCRIPT_PATH_ = Filter_Input(INPUT_SERVER, 'SCRIPT_FILENAME');
$_RUN_ = Filter_Input(INPUT_POST, 'SCRIPT_NAME');
// Define internal document page title, HTML page heading text and revision date
$_INTERNAL_TITLE_ = "Sun/Moon Rise/Set and Twilight Times Table For Any Year";
$_INTERFACE_TITLE_ = "<span style='font-size:14pt;'>Sun/Moon Rise/Set and Twilight Times Table For AnyYear</span><br>Via Astronomical Applications Dept. U.S. Naval Observatory, Washington, D.C.<br><span style='font-size:10pt;'>Program by Jay Tanner of Waterloo, NY, USA</span>";
$_REVISION_DATE_ = $_PROGRAM_VERSION_ .'Revised: '. GMDate("l, F d, Y $at h:i:s A $UTC", FileMTime($_SCRIPT_PATH_));
// Define main TextArea text, background
// colors and HTML table row span.
$TxColor = 'black';
$BgColor = 'white';
$ColSpan = 7; // Don't ask!
// ---------------------------------------------
// Do this only if [COMPUTE] button was clicked.
$w = Filter_Input(INPUT_POST, 'ComputeButton');
if (!IsSet($w))
{
// ----------------------------------------------------
// If [COMPUTE] button was clicked and an active cookie
// exists, then restore the previous interface settings
// from it.
$w = Filter_Input(INPUT_COOKIE, $CookieName);
if (IsSet($w))
{
$CookieDataString = Filter_Input(INPUT_COOKIE, $CookieName);
list($year,$label,$lat,$lon,$tz,$task01234) = Preg_Split("[\|]", $CookieDataString);
}
else
// --------------------------------------------------
// Set the initial default interface startup values.
{
$year = date('Y'); // Current year.
$label = 'Waterloo-NY-USA';
$lat = '+42.904788';
$lon = '-76.862737';
$tz = '-05:00';
$task01234 = '0';
// -------------------------------------------
// Store current interface settings in cookie.
$CookieDataString = "$year|$label|$lat|$lon|$tz|$task01234";
SetCookie ($CookieName, $CookieDataString, $SetToExpireIn30Days);
}
} // End of if (!isset(_POST['ComputeButton']))
// =======================================
// Read values of all interface arguments.
// Empty value is set to zero by default.
$w = Filter_Input(INPUT_POST, 'ComputeButton');
if (isset($w))
{
$year = trim(Filter_Input(INPUT_POST, 'year'));
$label = trim(Filter_Input(INPUT_POST, 'label'));
$label = Str_Replace("_", '-', $label);
$lat = trim(Filter_Input(INPUT_POST, 'lat'));
$lon = trim(Filter_Input(INPUT_POST, 'lon'));
$tz = trim(Filter_Input(INPUT_POST, 'tzone'));
$task01234 = trim(Filter_Input(INPUT_POST, 'task01234'));
// ---------------------------------------------
// Set empty values to default values.
if ($year == '') {$year = date('Y');}
if ($label == '') {$label = '---';}
if ($lat == '') {$lat = '+42.904788';}
if ($lon == '') {$lon = '-76.862737';}
if ($tz == '') {$tz = '-05:00';}
if ($task01234 == '') {$task01234 = '0';}
// ------------------------------------
// Store interface argument in cookie.
$CookieDataString = "$year|$label|$lat|$lon|$tz|$task01234";
SetCookie ($CookieName, $CookieDataString, $SetToExpireIn30Days);
}
// --------------------------------------------------
// Initialize error detection flag and error message.
$ErrorFlag = FALSE; // Default = FALSE = No error yet.
$ErrorMssg = ''; // Default = Empty string.
// Filter for error(s) staring below. In this inverse
// case, TRUE means an error was reported and FALSE
// means no error was reported.
// *********************
// START OF ERROR FILTER
// *********************
//
// ---------------------------------------------
// ERROR if year is not a valid numerical value.
if (!Is_Numeric($year))
{
$ErrorFlag = TRUE;
$ErrorMssg = "The year argument must be a valid numerical value.";
}
if ($task01234 < 0 or $task01234 >= 5)
{
$ErrorFlag = TRUE;
$ErrorMssg =
"
Task # Annual Table Generated
====== ===========================
0 Sun Rise/Set Table
1 Moon Rise/Set Table
2 Civil Twilight Table
3 Nautical Twilight Table
4 Astronomical Twilight Table
====== ===========================
";
}
// *******************
// END OF ERROR FILTER
// *******************
// -------------------------------
// Check if error reported (TRUE).
if ($ErrorFlag === TRUE)
{
$TxColor = 'white';
$BgColor = '#CC0000';
$TextArea2Text = '';
$TextArea1Text =
"=== ERROR ===
Invalid argument:
$ErrorMssg";
}
else
// ===================================================
// BEGIN COMPUTATIONS HERE IF NO ERROR DETECTED ABOVE.
{
$label = PReg_Replace("/\s+/", " ", trim($label));
$label = Str_Replace('_', '-', $label);
$label = Str_Replace(' ', '-', $label);
$label = Str_Replace(',', '-', $label);
$label = Str_Replace('--' ,'-', $label);
$NSLabel = ($lat < 0)? 'S' : 'N';
$EWLabel = ($lon < 0)? 'W' : 'E';
$RSTable = Moon_Sun_Rise_Set_Twilight_Times ($year, $label, $lat, $lon, $tz, $task01234);
$RSTable = Str_Replace("The input task is invalid", $ErrorMssg, $RSTable);
$TextArea1Text =
"PHP Program by Jay Tanner - Computations via USNO
For the Year $year
$RSTable";
}
// TextArea2.
$TextArea2Text =
"
There ARE 5 COMPUTATIONAL TASKS AVALABLE:
0 = Sun Rise/Set Table
1 = Moon Rise/Set Table
2 = Civil Twilight Table
3 = Nautical Twilight Table
4 = Astronomical Twilight Table
";
// --------------------------------------------
// Text Area 1 - Default = At least 80 columns.
$TextArea1Cols = Max(Array_Map('StrLen', PReg_Split("[\n]", trim($TextArea1Text))))-12;
if ($TextArea1Cols < 80) {$TextArea1Cols = 80;} // Default
$TextArea1Rows = 4 + Substr_Count($TextArea1Text, "\n");
// --------------------------------------------
// Text Area 2 - Default = At least 80 columns.
$TextArea2Cols = 1 + Max(Array_Map('StrLen', PReg_Split("[\n]", trim($TextArea2Text))));
if ($TextArea2Cols < 80) {$TextArea2Cols = 80;} // Default
$TextArea2Rows = 3 + Substr_Count($TextArea2Text, "\n");
print <<< _HTML
<!DOCTYPE HTML>
<HTML>
<head>
<style>
BODY
{color:silver; background-color:black; font-family:Verdana; font-size:100%}
TABLE
{font-size:12px; border: 1px solid black;}
TD
{color:black; background-color:white; line-height:200%; font-size:12px;
padding:6px; text-align:center;}
DIV
{
color:black; background-color:white; font-family:Verdana; font-size:110%;
text-align:justify; padding:4px;
}
PRE
{color:black; background-color:white; font-family:monospace; font-size:150%;
font-weight:bold; text-align:left; padding:4px;}
CODE
{font-family:monospace; font-size:150%; font-weight:normal;}
TEXTAREA
{
color:black; background:white; font-family:monospace; font-size:11pt;
font-weight:bold; border-radius: 8px; border:1px solid black; padding:4px;
white-space:pre;
}
INPUT[type="text"]::-ms-clear {width:0; height:0;}
INPUT[type="text"]
{
color:black; background:white; font-size:12pt; font-family:monospace;
font-weight:bold; text-align:center; box-shadow:2px 2px 3px #666666;
border:2px solid black; border-radius:4px;
}
INPUT[type="text"]:focus
{
background:white; box-shadow:2px 2px 3px #666666; font-family:monospace;
font-size:12pt; border:2px solid blue; text-align:center; font-weight:bold;
border-radius:4px;
}
INPUT[type="submit"]
{font-weight:bold;}
INPUT[type="submit"]:hover
{box-shadow:2px 2px 5px #555555; font-weight:bold;}
HR {background:black; height:2px; border:0px;}
A:link
{
font-size:100%; background:transparent; color:blue; font-family:Verdana;
font-weight:bold; text-decoration:none; line-height:175%; padding:3px;
border:1px solid transparent;
}
A:visited {font-size:100%; background:transparent; color:blue;}
A:hover
{
font-size:100%; background:yellow; color:black; border:1px solid black;
box-shadow:1px 1px 3px #222222;
}
A:active {font-size:100%; background:yellow; color:black;}
::selection {background-color:yellow; color:black;}
::-moz-selection {background-color:yellow; color:black;}
</style>
</head>
<body>
<form name='form1' method='post' action="$_RUN_">
<table align='center' width='800' border='0' cellspacing='1' cellpadding='3'>
<tr><td colspan="$ColSpan" style='color:white; background-color:#000066; border:2px solid white; border-radius:8px 8px 0px 0px;'>$_INTERFACE_TITLE_</td></tr>
<tr>
<td width='150' style='background:white;' title=' Valid Year Span = 1700 to 2100 '><b>Year</b><br>
<input name='year' type='text' value="$year" size='5' maxlength='4'>
</td>
<td width='16%' style='background:#BBFFBB;'>Optional Label<br>
<input name='label' type='text' value="$label" size='33' maxlength='32'>
</td>
<td width='16%' style='background:LightCyan;'>Latitude<br>
<input name='lat' type='text' value="$lat" size='15' maxlength='14'>
</td>
<td width='16%' style='background:LightCyan;' title=' -Negative = West'>Longitude<br>
<input name='lon' type='text' value="$lon" size='15' maxlength='14'>
</td>
<td width='150' style='background:LightYellow;' title=' -Negative = West'>Time Zone<br>
<input name='tzone' type='text' value="$tz" size='7' maxlength='6'>
</td>
<td width='150' title=' TASKS:\n 0 = Sun Rise/Set Table \n 1 = Moon Rise/Set Table \n 2 = Civil Twilight Table \n 3 = Nautical Twilight Table \n 4 = Astronomical Twilight Table '>Task ID #<br>
<input name='task01234' type='text' value="$task01234" size='6' maxlength='5' >
</td>
</tr>
<tr><td colspan="$ColSpan" style='background-color:black;'>
<input name='ComputeButton' type='submit' value=' C O M P U T E '>
</td></tr>
<!-- Yellow source code view link. --->
<tr>
<td colspan='6' style='background:transparent; color:black; font-size:10pt;
text-align:center;'>
<a href='View-Source-Code.php' target='_blank'
style='font-family:Verdana; color:black; background:yellow;
text-decoration:none; border:1px solid black; padding:4px;
border-radius:4px;'>
<span style='font-weight:normal;'>View/Copy PHP Source Code</span> </a>
</td>
</tr>
<tr>
<td colspan="$ColSpan" style='color:white; background-color:black;'>Double-Click Within Text Area to Select ALL Text<br>
<textarea name='TextArea1' style='color:$TxColor; background:$BgColor; padding:6px; border:2px solid white;' cols="$TextArea1Cols" rows="$TextArea1Rows" ReadOnly OnDblClick='this.select();' OnMouseUp='return true;'>
$TextArea1Text
</textarea></td>
</tr>
<!--
<tr>
<td colspan="$ColSpan" style='color:white; background:black;'>Double-Click Within Text Area to Select ALL Text<br>
<textarea name='TextArea2' style='color:black; background:white; padding:6px;' cols="81" rows="$TextArea2Rows" ReadOnly OnDblClick='this.select();' OnMouseUp='return true;'>
$TextArea2Text
</textarea></td>
</tr>
--->
<tr><td colspan="$ColSpan" style='color:gray; background:black;'>Program by $_AUTHOR_<br>$_REVISION_DATE_</td></tr>
</table>
</form>
<br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br>
</body>
</HTML>
_HTML;
/*
###########################################################################
This function converts a HMS time string into equivalent decimal hours.
INPUT: 1, 2 or 3-element HMS (Hours Minutes Seconds) separated by spaces
as angular string as 'hrs min sec' values.
Example: Given HMS string = '19 12 50.306'
Returned = 1.2139738888888889
NO DEPENDENCIES
ERRORS:
No error checking is done.
###########################################################################
*/
function HMS_to_Hours ($HMSstr)
{
$hms = StrToLower(trim($HMSstr));
/* ----------------------------------------------------
Normalize the spacing and then split and extract the
individual angular string elements (dh or hh, mm,ss).
*/
$hms = PReg_Replace("/\s+/", " ", trim($hms));
$hms = Str_Replace(':', ' ', $hms);
$whms = PReg_Split("[ ]", $hms);
$whmscount = count($whms);
$hh = ($whmscount >= 1)? bcAdd($whms[0],'0', 20) : '0';
$mm = ($whmscount >= 2)? bcAdd($whms[1],'0', 20) : '0';
$ss = ($whmscount >= 3)? bcAdd($whms[2],'0', 20) : '0';
/* -------------------------------------------------
Remember and then remove any numerical (+/-) sign
for reattachment to the returned output.
*/
$NumSign = (substr($HMSstr,0,1) == '-')? '-' : '';
$hh = Str_Replace('+', '', Str_Replace('-', '', $hh));
/* -------------------------------------------------------------
If original angle argument began with a + sign, then preserve
it so that all returned positive results will have a + sign.
Otherwise, positive results will NOT have a + sign.
*/
if (substr($HMSstr,0,1) == '+') {$NumSign = '+';}
// ----------------------------------------------
// Compute decimal hours value equivalent
// to the given HHMS argument elements.
$w2 = bcAdd(bcAdd(bcMul($hh,"3600",20),bcMul($mm,"60",20),20),$ss,20);
// -----------------------------------------------------------
// If result equates to zero, then suppress any numerical sign.
if (bcComp($w2, '0', 20) == 0) {$NumSign = '';}
// ---------------------------------------------------------
// round off result to 16 decimals, recalling original sign.
$w = $NumSign . bcAdd(bcDiv($w2,"3600",20), "0.00000000000000005",16);
$w = RTrim(RTrim($w, '0'), '.');
return $w;
} // end of HMS_to_Hours (...)
/*
###########################################################################
This function returns a table of moon/sun rise/set and twilight times for
an entire year at a specified location and time zone.
Program by Jay Tanner
Computations done via:
Astronomical Applications Dept.
U. S. Naval Observatory
Washington, DC 20392-5420
###########################################################################
*/
function Moon_Sun_Rise_Set_Twilight_Times ($year, $label, $lat, $lon, $tz, $task01234='0')
{
$year = trim($year);
$label = trim($label);
$lat = trim($lat);
$lon = trim($lon);
$tz = trim($tz);
$label = Str_Replace('_', '-', $label);
$task01234 = trim($task01234);
/*
list($HH, $mm) = PReg_Split("[\:]", $tz);
$HH = Str_Replace('+', '', $HH);
$tz_sign = (substr($HH,0,1) == '-')? '-1' : '1';
$tz = abs(FloatVal($HH)) + FloatVal($mm/60);
*/
$tz = HMS_to_Hours($tz);
$tz_sign = ($tz < 0)? '-1' : '1'; $tz = abs($tz);
//https://aa.usno.navy.mil/calculated/rstt/year?ID=AA&year=2025&task=0&lat=0.0000&lon=0.0000&label=home&tz=5&tz_sign=-1&submit=Get+Data
$URL = "https://aa.usno.navy.mil/calculated/rstt/year?ID=AA"
. "&year=$year&task=$task01234&lat=$lat&lon=$lon&label=$label&tz=$tz&tz_sign=$tz_sign&submit=Get+Data";
// exit("$URL");
$F = File_Get_Contents($URL);
$Q = '<pre style="text-align: left; margin-left: auto; margin-right: auto;">';
$i = StrPos($F, $Q);
$j = StrPos($F,'</pre>');
$table = '';
// -----------------------
// Isolate rise/set table.
if ($i !== FALSE) {$table = substr($F, $i+70, $j-$i);}
$table = Str_Replace('o , o , ', '° ' ° ' ', $table);
$table = Str_Replace('</div>', '', $table);
$table = substr($table, 0, StrLen($table) - 6);
$table = Str_Replace("</pre>", '', $table);
return RTrim($table);
}
?>