<?php

/*
   This program demonstrates a function designed to generate a
   table of Rise/Transit/Set times for multiple solar system
   bodies given in the BodyIDList for the given date.
*/

   
$LocLabel  'Geneva, NY, USA';
   
$DateStr   date('Y-M-d');
   
$TimeZone  '-05:00';
   
$DaySumYN  'No';
   
$LatDeg    '+42.868473';
   
$LonDeg    '-76.996490';
   
$AltMet    '0.0';


   
$EWLabel = (trim($LonDeg) < 0)? 'West':'East';
   
$NSLabel = (trim($LatDeg) < 0)? 'South':'North';

// -----------------------------------
// Define list of Body IDs to process.

   
$BodyIDList '10   Sun,301  Moon,1;   Ceres;,199  Mercury,299  Venus,499  Mars,599  Jupiter,699  Saturn';

// -------------------------------------------------
// Generate RTS table for the given bodies and date.

   
$RTSTimesTable Bodies_RTS_Table ($BodyIDList,$DateStr,$TimeZone,$DaySumYN,
                                      
$LocLabel,$LatDeg,$LonDeg,$AltMet);


   print <<< END_OF_HTML_PAGE

<!-- Top yellow source code view link. --->
<br>
<table width="420" align="bottom" cellspacing="1" cellpadding="3">
<tr>
<td colspan="1" style='font-size:10pt; color:black; background:white;
                       text-align:left;' title=' Tries to Open in a New Tab. '>
<b><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; box-shadow:2px 2px 5px #444444;
            font-weight:normal;'>
&nbsp;View/Copy Source Code&nbsp;</a></b>
</td>
</tr>
</table>

<pre style='font-family:monospace; font-size:13pt; font-weight:bold;'>
&#35;RISE/TRANSIT/SET TIMES TABLE

Local Date        =  
$DateStr
Location Label    =  
$LocLabel
Time Zone         =  
$TimeZone
Day/Sum Time Y/N  =  
$DaySumYN
Latitude  Deg     =  
$LatDeg \t($NSLabel)
Longitude Deg     =  
$LonDeg \t($EWLabel)
Altitude meters   =  
$AltMet m

$RTSTimesTable
</pre>

<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>

END_OF_HTML_PAGE;











/*
   ###########################################################################
   This function returns a topocentric ephemeris of rise/transit/set times
   from the NASA/JPL Horizons API. A topocentric ephemeris takes the location
   and altitude of the observer into account. Standard Earth refraction model
   is applied.

   NOTE: The BodyID MUST be an integer record # (301)
         For small bodies, add a semicolon (;) to the number value. (301;)

   DaySumYN = Means Daylght Saving/Summer Time 'Yes|No'
             'No'  = Use Standard Clock Time (Default)
             'Yes' = Use Daylight Saving/Summer Clock Time

   Angles are expressed in degrees.


COLUMN  CONTENT
======  =======================================================================
  1     Date and Time String (UT or ZONE)
  2     Sp (Solar Presence Symbol)
  3     Lp (Lunar Presence Symbol)
  4     Azimuth Angle (Compass Direction Reckoned Clockwise From North = 0)
  5     Elevation Angle (Relative to Horizon = 0 degrees)
  6     Apparent Visual Magnitude or Brightness Level
  7     S-brt (Brightness of 1 Square Arcsecond of Visible Disc)

   NO DEPENDENCIES
   ###########################################################################
*/
   
function R_T_S_Times ($BodyID,$DateStr,$TimeZone,$DaySumYN,
                         
$LocLabel,$LatDeg,$LonDeg,$AltMet)
{
// ===========================================================================
// Construct query URL for the NASA/JPL Horizons API.

   
$BodyID trim($BodyID);

   if (
strPos($BodyID';') === FALSE)
      {
$BodyID IntVal(trim($BodyID));}
   else
      {
$BodyID IntVal(trim($BodyID)) . ';';}


   
$Command  URLEncode($BodyID);
   
$AltKm    trim($AltMet) / 1000;
   
$LocLabel trim($LocLabel);  if ($LocLabel == '') {$LocLabel '---';}

/* -----------------------------------------------------------
   Adjust for Daylight/Summer Time, if indicated. This assumes
   that the Time Zone string is given in the standard +-HH:mm
   format or an error may occur.
*/
   
$DaySumYN  substr(StrToUpper(trim($DaySumYN)),0,1);
   
$DaySumAdj = ($DaySumYN == 'N')? 0:1;
   list(
$TZHH$TZmm) = PReg_Split("[\:]"$TimeZone);
   
$TZSign substr($TZHH,0,1);
   
$TZHours = (($TZSign == '-')? -1:1)*(abs($TZHH) + $TZmm/60) + $DaySumAdj;
   
$i StrPos($TZHours'.');  if ($i == FALSE) {$TZHours .= '.00';}
   
$i StrPos($TZHours'.');
   
$TZHH $TZSign.SPrintF("%02d"abs(substr($TZHours,0,$i)));
   
$TimeZone "$TZHH:$TZmm";

// -------------------------------------
// Construct URL for Horizons API query.

   
$From_Horizons_API =
   
"https://ssd.jpl.nasa.gov/api/horizons.api?format=text" .
   
"&COMMAND='$Command'"                      .
   
"&OBJ_DATA='NO'"                           .
   
"&MAKE_EPHEM='YES'"                        .
   
"&EPHEM_TYPE='OBSERVER'"                   .
   
"&CAL_FORMAT='CAL'"                        .
   
"&REF_SYSTEM='ICRF'"                       .
   
"&APPARENT='REFRACTED'"                    .
   
"&CENTER='COORD@399'"                      .
   
"&COORD_TYPE='GEODETIC'"                   .
   
"&SITE_COORD='$LonDeg,$LatDeg,$AltKm'"     .
   
"&TIME_DIGITS='MINUTES'"                   .
   
"&TIME_ZONE='$TimeZone'"                   .
   
"&START_TIME='$DateStr%2000:00:00%20UT'"   .
   
"&STOP_TIME='$DateStr%2023:59:59'"         .
   
"&STEP_SIZE='1 MINUTE'"                    .
   
"&EXTRA_PREC='YES'"                        .
   
"&R_T_S_ONLY='TVH'"                        .
   
"&QUANTITIES='4,9'"                        .
   
"&CSV_FORMAT='YES'"                        ;
// ============================================

/* -----------------------------------------------------------------------
   Send query to Horizons API to obtain the apparent topocentric ephemeris
   data we need for the R-T-S times of the given body ID.
*/
   
$RTS Str_Replace(",\n"" \n"File_Get_Contents($From_Horizons_API));

/* ----------------------------------------------------------------------
   If no ephemeris data is found, then return an empty string as an error
   state indicator.
*/
   
if (StrPos($RTS'$$SOE') === FALSE) {return $RTS;}

/* -------------------------------------------------------------------------
   DO NOT TRIM HERE BECAUSE INITIAL CHARACTER MAY BE A SPACE INDICATING AN
   'AD' YEAR.  'BC' YEARS BEGIN WITH A SINGLE 'b' AS THE INITIAL CHARACTER.

   BAD PRACTICE. LEADING/TRAILING SPACES SHOULD NOT BE USED AS TABLE DATA.
   IT CAN SOMETIMES LEAD TO CONFUSION WHEN READING A LINE OF TABULAR TEXT.

   IF A DATA COLUMN IS EMPTY, A SPECIAL CHARACTER SHOULD BE ASSIGNED AS AN
   INDICATOR OF AN EMPTY COLUMN.  EXAMPLE (~), SIMILAR TO USING (n/a).
   SOMETHING OTHER THAN SIMPLY LEAVING IT EMPTY OR USING A SPACE CHARACTER.

   DIFFERENT PROGRAMMING LANGUAGES, WHEN READING THE TABLE, MAY NOT TREAT
   LEADING OR TRAILING SPACES THE SAME WAY AND THEY MAY POSSIBLY BE LOST.
*/
   
return $RTS;

// End of  R_T_S_Times(...)



/*

*/

   
function Bodies_RTS_Table ($BodyIDList,$DateStr,$TimeZone,$DaySumYN,
                              
$LocLabel,$LatDeg,$LonDeg,$AltMet)
{
   
$LocLabel trim($LocLabel);  if ($LocLabel == '') {$LocLabel '---';}

   
$wArray PReg_Split("[,]"trim($BodyIDList));
   
$wCount count($wArray);

   
$out '';

   for (
$i=0;   $i $wCount;   $i++)
  {
   
$CurrBodyID trim($wArray[$i]);
   
$w R_T_S_Times ($CurrBodyID,$DateStr,$TimeZone,$DaySumYN,$LocLabel,$LatDeg,$LonDeg,$AltMet);

/* -----------------------------------------------------
   Set pointers to start and end of CSV ephemeris table.
   A value of FALSE means no ephemeris was found within
   the given source text.
*/
   
$j StrPos($w'$$SOE');
   
$k StrPos($w'$$EOE');

/* ------------------------------------------------
   Extract ONLY the existing ephemeris data line(s)
   from between the pointers.
*/
   
$RTSTable RTrim(substr($w$j+5$k-$j-5));

   
$out .= "&#35;$CurrBodyID$RTSTable\n\n";

  }

  return 
$out;
}









?>