<?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;'>
View/Copy Source Code </a></b>
</td>
</tr>
</table>
<pre style='font-family:monospace; font-size:13pt; font-weight:bold;'>
#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 .= "#$CurrBodyID$RTSTable\n\n";
}
return $out;
}
?>