This program computes the approximate rise, transit, and set times for the Sun, Moon, and all eight planets (Mercury through Pluto) for any user-specified date and geographic location. The user supplies a latitude and longitude (defaulting to approximately 34.85°N, 87.65°W) and selects one of ten bodies by number. Planetary orbital elements are packed as fixed-width seven-character fields into string variables and parsed with VAL and substring slicing at line 1970, allowing nine orbital parameters per body to be loaded into the 9×9 array P without a DATA statement. Sidereal time is computed at lines 3280–3400, and rise/set hour angles are derived via the ACS function using the tangent product of latitude and declination. The Moon uses a separate simplified positional algorithm (lines 2670–2860) based on mean longitude, perigee, and ecliptic anomaly rather than the general planetary routine.
Program Analysis
Program Structure
The program is organized into a set of clearly delineated subroutines called from a mostly linear main flow. After initialization and user prompts, control passes through date entry, planet selection, orbital calculations, and time display. The top-level flow is:
- Lines 10–230: Variable and array dimensioning, conversion constants.
- Lines 260–590: Set/confirm latitude and longitude.
- Lines 600–630: Load planetary element arrays via
GO SUB 1360. - Lines 640–830: Date entry and Julian Day Number computation.
- Lines 840–980: Compute
NI(days from epoch), sidereal time, planet selection. - Lines 990–1350: Display planetary data and offer a printed copy.
- Lines 1360–1660: Planetary orbital element loader.
- Lines 1670–1950: Planet name assignment and orbital position computation loop.
- Lines 1960–2000: Element parser subroutine.
- Lines 2010–2120: Mean anomaly / true anomaly / distance solver.
- Lines 2130–2420: Geocentric RA and declination computation.
- Lines 2430–2660: Rise, transit, and set time computation.
- Lines 2670–3030: Dedicated Moon position routine.
- Lines 3040–3270: Planet selection menu.
- Lines 3280–3400: Sidereal time subroutine.
- Lines 3410–3560: Rise/transit/set display subroutine.
- Lines 3570–3840: “Another planet / another date” re-run logic.
Orbital Element Storage and Parsing
Rather than using DATA/READ statements, the nine orbital parameters for each planet are packed as fixed-width 7-character decimal fields concatenated into the string M$. The subroutine at line 1960 iterates K from 1 to 9, extracting each field with:VAL (M$(1+((K-1)*7) TO (K*7)))
and storing the result in the 9×9 array P(U,K). This packs 63 characters per planet into a single string, allowing all element data to be initialized without any DATA statements, which is a useful memory technique. The outer loop at lines 1370–1640 calls this subroutine once per planet, incrementing the planet counter U each time.
Orbital Position Computation
The subroutine at lines 2010–2120 computes a first-order Keplerian orbit. Starting from mean anomaly (A), it applies a single-step equation-of-center correction using P(J,3)*SIN(A-P(J,4)) to approximate true anomaly. Heliocentric distance is then found from P(J,5)+P(J,6)*SIN(A-P(J,7)) and latitude perturbation L from P(J,8)*SIN(A-P(J,9)). Angle wrapping is handled by repeated conditional addition/subtraction of P2 (2π) rather than a modulo operation.
Geocentric RA and Declination
Lines 2130–2420 convert heliocentric positions to geocentric equatorial coordinates. The angular separation Z between the Sun and the planet (in heliocentric longitude) is computed, and the law of cosines gives the geocentric distance Q. Right ascension is derived using ACS (arccosine), with the sign of Z determining whether the planet is east or west of the Sun. Declination uses the obliquity of the ecliptic (23.44194°). The Sun’s own RA and declination are computed at lines 2320–2410 using a small constant 3.141159 (note the slight typographic error — should be 3.14159, differing at the fifth decimal place) rather than PI.
Moon Routine
When body 10 (Moon) is selected, the program branches at line 980 to a separate algorithm (lines 2670–2860). This uses three fundamental lunar quantities:
LZ= mean longitude epoch value (311.1687°)LE= mean longitude of the Sun’s perigee epoch (178.699°)LP= mean longitude of lunar perigee epoch (255.7433°)
The mean lunar longitude is advanced by the sidereal period (27.32158 days), and a single sine correction term (6.2886°) approximates the equation of the center. Declination combines the Moon’s ecliptic latitude (derived from the angle to the ecliptic node) with the Sun’s obliquity contribution. The result is stored in R(10) and V(10) before passing to the shared rise/set subroutine.
Rise, Transit, and Set Calculation
The subroutine at lines 2430–2660 computes times using the standard hour-angle formula. The critical intermediate value is:TA = ACS(ABS(TAN(FR*LA) * TAN(FR*V(CI))))
where FR is the degrees-to-radians factor, LA is latitude, and V(CI) is declination. The sign of TA is manipulated at lines 2440–2510 using an unusual idiom: if TA<0 the absolute value is taken, if TA>0 it is negated, with the result that the sign logic appears inverted. This may produce incorrect results for bodies with positive declination at northern latitudes — a potential bug. Rise and set times are adjusted by small constants (−1/60 and +3/60 hours respectively) as atmospheric refraction corrections, and all times are corrected to sidereal time via the factor 0.99727.
Sidereal Time
The subroutine at lines 3280–3400 computes local sidereal time at noon as:T2 = TC*(NI - 7020) + GC
where GC = 11.927485 hours and TC = 0.065711 hours/day are empirical constants, and NI is the day count from the program’s epoch (Julian Day 715875, approximately January 1, 1960). Normalization to [0, 24) hours is performed by successive conditional subtraction/addition, the same pattern used throughout the program in place of MOD arithmetic.
Day Number Computation
Lines 880–950 compute a modified Julian Day number. For months before March, a different formula is used (line 910) that incorporates a Gregorian leap-year correction INT(0.75 * INT((Y-1)/100 + 1)). For March onward, a simpler expression is applied (lines 930–940). The longitude offset is added to the day at line 888 to shift the calculation to apparent noon at the observer’s meridian.
Key Variables
| Variable | Role |
|---|---|
P(U,K) | 9×9 array of orbital elements, one row per planet |
NI | Day count from epoch (Julian Day minus 715875) |
T2 | Local sidereal time at noon |
CI | Currently selected body index (1–10) |
FL | Flag to skip re-loading planet names on subsequent queries |
FR | Degrees-to-radians factor (π/180 ≈ 0.01745329) |
FD | Radians-to-degrees factor (180/π ≈ 57.29578) |
TR, TT, TS | Rise, transit, and set times in decimal hours |
R(CI), V(CI) | Right ascension (hours) and declination (degrees) for body CI |
Notable Bugs and Anomalies
- Line 2400 uses the literal
3.141159instead of3.14159— a digit transposition typo, though the error (≈6×10⁻⁶) has negligible practical effect. - Lines 2440–2500 contain a sign-reversal logic for
TAthat appears to invert the expected behavior: negativeTAis made positive and positiveTAis negated beforeACSis applied. This may cause rise and set times to be swapped or incorrect for some declination/latitude combinations. - Line 1880 uses
IF I=3 THEN NEXT Ito skip the Sun (index 3) in the geocentric conversion loop, since the Sun does not need a heliocentric-to-geocentric transform — a clean idiom for loop body exclusion. - Lines 1940–1950 show a
FOR I=1 TO 9immediately followed byRETURN, with no loop body and noNEXT. This fragment appears to be dead code or a copying artifact; execution falls through toRETURNon the first iteration. - The
FLflag is set to 2 at line 3700 when the Sun is reselected on the same date, but the test at line 1680 only checksFL=1, so planet names are always reloaded whenFL=2— the intended optimization for the Sun re-query case does not fire.
Content
Source Code
10 CLEAR
20 DIM A$(10)
30 DIM U(9)
40 DIM P(9,9)
50 DIM N$(22)
60 DIM M$(63)
70 DIM P$(10,7)
80 LET P2=2*PI
100 DIM A(9)
110 DIM D(9)
120 DIM L(9)
130 DIM Q(9)
140 DIM R(10)
150 DIM V(10)
160 DIM K(9)
170 LET FL=0
180 DIM V$(9)
200 DIM R$(10)
230 LET FR=.01745329
240 LET FD=57.29578
250 REM ----SET LATITUDE----
260 LET LA=34.85
270 REM ----SET LONGITUDE----
280 LET LO=87.65
300 PRINT
310 PRINT
320 PRINT
330 PRINT " THIS PROGRAM COMPUTES THE "
340 PRINT "APPROXIMATE TIMES OF THE RISING,"
350 PRINT "TRANSIT, AND SETTING OF A PLANET"
360 PRINT "THE SUN OR THE MOON FOR ANY DATE"
370 PRINT "WHICH YOU REQUEST."
380 PRINT
390 PRINT "INITIAL CONDITIONS ARE SET FOR.."
400 PRINT " LATITUDE ";LA
410 PRINT " LONGITUDE ";LO
420 PRINT
430 PRINT "DO YOU WISH TO CHANGE THEM? Y/N";
500 INPUT B$
510 PRINT
520 IF B$<>"Y" THEN GO TO 590
522 PRINT
530 PRINT "TYPE LATITUDE ";
540 INPUT LA: PRINT LA
550 PRINT "TYPE LONGITUDE ";
560 INPUT LO: PRINT LO
590 PRINT
600 PRINT
610 PRINT "PLEASE WAIT ... LOADING ARRAYS"
620 GO SUB 1360
630 CLS
640 PRINT
650 PRINT
660 PRINT "ENTER THE DATE"
670 PRINT
680 PRINT " YEAR.... ";
690 INPUT Y: PRINT Y
700 PRINT
710 PRINT " MONTH... ";
720 INPUT M: PRINT M
750 IF M<1 OR M>12 THEN GO TO 720
760 PRINT
770 PRINT " DAY..... ";
780 INPUT DY: PRINT DY
800 IF DY<1 OR DY>31 THEN GO TO 770
810 IF M=2 AND DY>29 THEN GO TO 770
830 GO SUB 3040
840 PRINT
850 LET DX=DY
860 LET MX=M
870 LET YX=Y
880 LET DY=DY+(LO/15)/24
890 LET DG=365*Y+DY+((M-1)*31)
900 IF M>=3 THEN GO TO 930
910 LET DG=DG+INT ((Y-1)/4)-INT ((.75)*INT ((Y-1)/100+1))
920 GO TO 950
930 LET DG=DG-INT (M*.4+2.3)+INT (Y/4)
940 LET DG=DG-INT ((.75)*INT ((Y/100)+1))
950 LET NI=DG-715875
970 GO SUB 3280
980 IF CI=10 THEN GO TO 2670
990 CLS
1010 GO SUB 1670
1030 PRINT
1040 PRINT "DATA REQUESTED FOR ";YX;" ";MX;" ";DX
1050 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
1060 IF CI=3 THEN PRINT TAB 20;"R.A. DEC"
1070 IF CI=3 THEN PRINT TAB 20;"HRS DEG"
1080 IF CI=3 THEN GO TO 1110
1090 PRINT " HEL. DIST. R.A. DEC"
1100 PRINT " LONG. A.U. HRS DEG."
1110 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
1120 IF CI=3 THEN PRINT P$(CI);TAB 19;R$( TO 4);" ";V$
1130 IF CI=3 THEN PRINT
1140 IF CI=3 THEN GO TO 1250
1150 PRINT P$(CI);
1160 LET A(CI)=A(CI)*57.29578
1170 LET A$=STR$ (A(CI))
1180 PRINT TAB 8;A$( TO 4);
1190 LET A$=STR$ (Q(CI))
1200 PRINT TAB 13;A$( TO 5);
1210 LET A$=STR$ (R(CI))
1220 PRINT TAB 19;A$( TO 5);
1230 LET A$=STR$ (V(CI))
1240 PRINT TAB 25;A$( TO 5)
1250 PRINT "-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-"
1260 GO SUB 3410
1270 PRINT
1280 PRINT "WANT A COPY? Y/N "
1290 INPUT C$
1300 IF C$="N" OR C$="NO" THEN GO TO 1320
1310 COPY
1320 CLS
1330 PRINT
1340 PRINT
1350 GO TO 3570
1360 REM ---PLANETARY DATA------
1370 LET U=1
1380 LET N$=".0714223.84840.3883011"
1390 LET M$=N$+".34041.387100.0797402.73514.122173.836013"
1400 GO SUB 1960
1410 LET N$=".0279623.02812.0131952"
1420 LET M$=N$+".28638.723300.0050603.85017.0593411.33168"
1430 GO SUB 1960
1440 LET N$=".0172021.74022.0320441"
1450 LET M$=N$+".785471.00000.0170003.3392600000000000000"
1460 GO SUB 1960
1470 LET N$=".0091464.51234.1753015"
1480 LET M$=N$+".852091.52370.1417041.04656.031420.858702"
1490 GO SUB 1960
1500 LET N$=".0014504.53364.090478."
1510 LET M$=N$+"2391105.20280.2493741.76188.0197201.74533"
1520 GO SUB 1960
1530 LET N$=".0005844.89884.1055581"
1540 LET M$=N$+".610949.53850.5341563.12570.0436331.97746"
1550 GO SUB 1960
1560 LET N$=".0002052.46615.0885932"
1570 LET M$=N$+".9670619.1820.9015544.49084.0139601.28805"
1580 GO SUB 1960
1590 LET N$=".0001043.78556.016965."
1600 LET M$=N$+"77318130.0600.2705402.33498.0314162.29162"
1610 GO SUB 1960
1620 LET N$=".0000693.16948.4712393"
1630 LET M$=N$+".9130339.44009.860005.23114.3001971.91812"
1640 GO SUB 1960
1650 LET M$=""
1660 RETURN
1670 REM ----PLANET NAMES----
1680 IF FL=1 THEN GO TO 1790
1690 LET P$(1)="MERCURY"
1700 LET P$(2)="VENUS"
1710 LET P$(3)="SUN"
1720 LET P$(4)="MARS"
1730 LET P$(5)="JUPITER"
1740 LET P$(6)="SATURN"
1750 LET P$(7)="URANUS"
1760 LET P$(8)="NEPTUNE"
1770 LET P$(9)="PLUTO"
1780 LET P$(10)="MOON"
1790 LET I=1
1800 FOR J=1 TO 9
1810 GO SUB 2010
1820 LET A(I)=A
1830 LET D(I)=D
1840 LET L(I)=L
1850 LET I=I+1
1860 NEXT J
1870 FOR I=1 TO 9
1880 IF I=3 THEN NEXT I
1890 GO SUB 2130
1900 LET Q(I)=Q
1910 LET R(I)=R
1920 LET V(I)=V
1930 NEXT I
1940 FOR I=1 TO 9
1950 RETURN
1960 FOR K=1 TO 9
1970 LET P(U,K)=VAL (M$(1+((K-1)*7) TO (K*7)))
1980 NEXT K
1990 LET U=U+1
2000 RETURN
2010 LET A=NI*P(J,1)+P(J,2)
2020 IF A>6.28318 THEN LET A=((A/6.28318)-INT (A/6.28318))*6.28318
2030 IF A<0 THEN LET A=A+P2
2040 IF A<0 THEN GO TO 2030
2050 LET C=P(J,3)*SIN (A-P(J,4))
2060 LET A=A+C
2070 IF A>P2 THEN LET A=A-P2
2080 IF A<0 THEN LET A=A+P2
2090 IF A<0 THEN GO TO 2080
2100 LET D=P(J,5)+P(J,6)*SIN (A-P(J,7))
2110 LET L=P(J,8)*SIN (A-P(J,9))
2120 RETURN
2130 LET Z=A(3)-A(I)
2140 IF ABS (Z)>PI AND Z<0 THEN LET Z=Z+P2
2150 IF ABS (Z)>PI AND Z>0 THEN LET Z=Z-P2
2160 LET CZ=COS (Z)
2170 LET Q=D(I)^2+D(3)^2-2*D(I)*D(3)*CZ
2180 LET Q=SQR (Q)
2190 LET P=(D(I)+D(3)+Q)/2
2200 LET X=2*ACS (SQR (((P*(P-D(I)))/(D(3)*Q))))
2210 IF Z<0 THEN LET R=57.29578*(A(3)+3.14159-X)/15
2220 IF Z>0 THEN LET R=57.29578*(A(3)+3.14159+X)/15
2230 IF R>24 THEN LET R=R-24
2240 IF R>24 THEN GO TO 2230
2250 IF R<-24 THEN LET R=R+24
2260 IF R<-24 THEN GO TO 2250
2270 IF R<0 THEN LET R=R+24
2280 IF R<0 THEN GO TO 2270
2290 IF Z<0 THEN LET V=SIN (A(3)+PI-X)*23.44194+FD*L(I)
2300 IF Z>0 THEN LET V=SIN (A(3)+PI+X)*23.44194+FD*L(I)
2310 LET X=FD*X
2320 LET R(3)=FD*(A(3)+PI)/15
2330 IF R(3)<=24 THEN GO TO 2360
2340 LET R(3)=R(3)-24
2350 GO TO 2330
2360 IF R(3)>=0 THEN GO TO 2390
2370 LET R(3)=R(3)+24
2380 GO TO 2360
2390 LET R$=(STR$ (R(3)))( TO 4)
2400 LET V(3)=SIN (A(3)+3.141159)*23.44194
2410 LET V$=(STR$ (V(3)))( TO 4)
2420 RETURN
2430 REM -----CALC TIMES-------
2440 LET TA=TAN (FR*LA)*TAN (FR*V(CI))
2450 IF TA<0 THEN GO TO 2470
2460 IF TA>0 THEN GO TO 2490
2470 LET TA=ABS (TA)
2480 GO TO 2500
2490 LET TA=-TA
2500 LET TA=ACS (TA)
2510 LET TA=FD*TA
2520 LET B=-TA/15
2530 LET TZ=0
2540 LET TR=(B+R(CI)+TZ-T2)*.99727
2550 LET TR=TR-1/60
2560 IF TR<0 THEN LET TR=TR+24
2570 IF TR>24 THEN LET TR=TR-24
2580 LET C=TA/15
2590 LET TS=(C+R(CI)+TZ-T2)*.99727
2600 LET TS=TS+3/60
2610 IF TS<0 THEN LET TS=TS+24
2620 IF TS>24 THEN LET TS=TS-24
2630 LET TT=R(CI)-T2+1/60
2640 IF TT<0 THEN LET TT=TT+24
2650 IF TT>24 THEN LET TT=TT-24
2660 RETURN
2670 REM --MOON-RISE,XSIT,SET---
2680 LET LZ=311.1687
2690 LET LE=178.699
2700 LET LP=255.7433
2710 LET PG=.111404*NI+LP
2720 LET PG=(PG/360-INT (PG/360))*360
2730 LET LMD=LZ+360*NI/27.32158
2740 LET LMD=(LMD/360-INT (LMD/360))*360
2750 LET PG=LMD-PG
2760 LET DR=6.2886*SIN (FR*PG)
2770 LET LMD=LMD+DR
2780 LET LMD=(LMD/360-INT (LMD/360))*360
2790 LET RM=LMD/15
2800 IF RM>24 THEN LET RM=RM-24
2810 IF RM<0 THEN LET RM=RM+24
2820 LET AL=LE-NI*.052954
2830 LET AL=LMD-AL
2840 LET AL=(AL/360-INT (AL/360))*360
2850 LET HE=5.1454*SIN (AL*3.14159/180)
2860 LET DM=HE+23.1444*SIN (LMD*3.14159/180)
2870 LET R$=(STR$ (RM))( TO 5)
2880 LET D$=(STR$ (DM))( TO 5)
2890 CLS
2900 PRINT
2910 PRINT "MOON DATA REQUESTED FOR...."
2920 PRINT TAB 4;"YEAR ";YX;" MONTH ";
2930 PRINT MX;" DAY ";DX
2940 PRINT
2950 PRINT "AT NOON"
2960 PRINT "R.A. OF MOON IS. ";R$;" HRS"
2970 PRINT "DECLINATION IS.. ";D$;" DEG"
2980 PRINT "-------------------------------"
2990 LET R(10)=RM
3000 LET V(10)=DM
3010 LET P$(CI)="MOON"
3020 GO SUB 2430
3030 GO TO 3420
3040 REM ---PLANET SELECTION----
3050 CLS
3060 PRINT
3070 PRINT
3080 PRINT
3090 PRINT "SELECT BY NUMBER"
3100 PRINT
3110 PRINT TAB 5;"MERCURY.... 1"
3120 PRINT TAB 5;"VENUS...... 2"
3130 PRINT TAB 5;" 3....SUN"
3140 PRINT TAB 5;"MARS....... 4"
3150 PRINT TAB 5;"JUPITER.... 5"
3160 PRINT TAB 5;"SATURN..... 6"
3170 PRINT TAB 5;"URANUS..... 7"
3180 PRINT TAB 5;"NEPTUNE.... 8"
3190 PRINT TAB 5;"PLUTO...... 9"
3200 PRINT TAB 5;" 10..MOON"
3210 PRINT
3220 PRINT "TYPE NUMBER... ";
3230 INPUT SS
3240 IF SS<1 OR SS>10 THEN GO TO 3050
3250 PRINT SS
3260 LET CI=SS
3270 RETURN
3280 REM -----SIDERAL TIME------
3290 LET GC=11.927485
3300 LET TC=.065711
3310 LET T2=TC*(NI-7020)+GC
3320 IF T2<24 THEN GO TO 3350
3330 LET T2=T2-24
3340 GO TO 3320
3350 IF T2>-24 THEN GO TO 3380
3360 LET T2=T2+24
3370 GO TO 3350
3380 IF T2>0 THEN GO TO 3400
3390 LET T2=T2+24
3400 RETURN
3410 GO SUB 2430
3420 PRINT
3430 PRINT
3440 LET TM=60*(TR-INT (TR))
3450 LET TR=INT (TR)
3460 LET TN=60*(TT-INT (TT))
3470 LET TT=INT (TT)
3480 LET TP=60*(TS-INT (TS))
3490 LET TS=INT (TS)
3500 PRINT
3510 PRINT P$(CI)
3520 PRINT "RISES AT.... ";TR;" HRS ";INT (TM);" MIN"
3530 PRINT "TRANSITS AT. ";TT;" HRS ";INT (TN);" MIN"
3540 PRINT "SETS AT..... ";TS;" HRS ";INT (TP);" MIN"
3550 IF CI=10 THEN GO TO 1270
3560 RETURN
3570 PRINT
3580 PRINT "WANT ANOTHER PLANET FOR THE"
3590 PRINT "SAME DATE? Y/N ";
3600 INPUT B$
3610 PRINT B$
3620 IF B$="N" THEN GO TO 3750
3630 IF CI=10 THEN GO TO 3650
3640 IF B$="Y" THEN GO TO 3690
3650 LET DY=DX
3660 LET M=MX
3670 LET Y=YX
3680 GO TO 820
3690 GO SUB 3050
3700 IF CI=3 THEN LET FL=2
3710 IF CI=10 THEN GO SUB 2670
3720 IF CI=10 THEN GO TO 3760
3730 CLS
3740 GO TO 1030
3750 PRINT
3760 PRINT "WANT ANOTHER DATE? Y/N ";
3770 INPUT B$
3780 PRINT B$
3790 IF B$="N" THEN GO TO 3830
3800 LET FL=0
3810 LET F=0
3820 IF B$="Y" THEN GO TO 630
3830 CLS
3840 STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

