<?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 "&#97;&#116;"$UTC "&#85;&#84;&#67;";
   
$_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 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 Substr_Count($TextArea1Text"\n");


// --------------------------------------------
// Text Area 2 - Default = At least 80 columns.

   
$TextArea2Cols Max(Array_Map('StrLen'PReg_Split("[\n]"trim($TextArea2Text))));
   if (
$TextArea2Cols 80) {$TextArea2Cols 80;} // Default
   
$TextArea2Rows 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&nbsp;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&nbsp;ID&nbsp;#<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;'>
         &nbsp;<span style='font-weight:normal;'>View/Copy PHP Source Code</span>&nbsp;</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  , ''&deg;  &#39;    &deg;  &#39; '$table);
   
$table Str_Replace('</div>'''$table);
   
$table substr($table0StrLen($table) - 6);
   
$table Str_Replace("</pre>"''$table);


   return 
RTrim($table);
}












?>