--- title: "Solar/Lunar Eclipses" id: 55044 type: "computer_media" slug: "solar-lunar-eclipses" url: "http://localhost/computer_media/solar-lunar-eclipses/" markdown_url: "http://localhost/computer_media/solar-lunar-eclipses.md" published_at: "2024-06-11T13:41:03+00:00" modified_at: "2026-03-30T21:45:23+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Predict every solar and lunar eclipse across four millennia using rigorous astronomical math, complete with eclipse type, magnitude, and GMT contact times." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" genre: - name: "Astronomy" slug: "astronomy" taxonomy: "genre" url: "http://localhost/type/astronomy/" media_contents: - id: 55036 title: "TS-2068 Computer Programs" type: "computer_media" url: "http://localhost/computer_media/ts-2068-computer-programs/" media_type: "Program" programmers: - name: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" mediadate: "1985" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260330-mnxh.png" - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260330-mnsu.png" media_type_tags: "Astronomy" --- This program calculates and displays solar and lunar eclipses for any year between 1000 and 4000, using Jean Meeus’s astronomical algorithms. It computes Julian Day Numbers and applies trigonometric correction terms to determine the eclipse magnitude, type (total, annular, annular/total, or partial for solar; umbral, penumbral, or partial for lunar), and geographic visibility zone. For lunar eclipses, subroutine 600 further calculates the precise GMT times of partial and total phase start and end. Output can be directed to either the screen (stream 4 opened to “s”) or a printer (stream 4 opened to “p”), and two UDG characters are defined via POKEs and DATA at line 2000 for the title screen decoration. *** ## Program Analysis ### Program Structure The program is divided into a title/setup section, a main eclipse-scanning loop, and a set of reusable subroutines. Execution begins at line 1000 via `GO TO 1000` at line 8, which handles initialization, title display, year input, and output device selection before jumping to line 50 to start processing. 1. **Lines 1000–1300:** Initialization — builds lookup strings, defines UDGs, draws the title screen, accepts year input and output device choice, opens stream `#4`. 2. **Lines 50–94:** Main loop — iterates over lunation numbers `j` for the chosen year, checking first for solar eclipses (new moon, `k=j`) then lunar eclipses (full moon, `k=j+0.5`). 3. **Lines 100–145:** Subroutine — computes the Julian Day Number and orbital elements (`m`, `n`, `f`) for lunation `k`. 4. **Lines 150–160:** Subroutine — applies time corrections to `jd`. 5. **Lines 200–240:** Subroutine — computes eclipse magnitude parameters `g` (gamma), `u`, and `s`. 6. **Lines 300–370:** Subroutine — converts Julian Day to calendar date (year `yr`, month `m`, day `dy`), handling the Gregorian calendar reform at JD 2299161. 7. **Lines 500–540:** Subroutine — prints the geographic visibility zone based on the sign of `g`. 8. **Lines 600–670:** Subroutine — computes and prints GMT contact times for lunar eclipses (partial start/end, total start/end, and maximum). 9. **Lines 15–48:** Utility subroutines — format fractional day fractions into `HH:MM` time strings using the pre-built digit lookup string `n$`. 10. **Line 9000:** Year-end cleanup — issues blank lines and closes stream `#4`. ### Astronomical Algorithm The core mathematics follows Jean Meeus’s eclipse prediction method. Lunation number `k` is derived at line 50 from the expression `(y-1900)*12.3685`, and both new moon (`k=j`) and full moon (`k=j+0.5`) are tested each iteration. Line 100 computes `t=k/1236.85` as the centuries-scaled argument. The Julian Day formula at line 120 includes a periodic perturbation term using `SIN`. Lines 130–140 compute the Sun’s mean anomaly `m`, the Moon’s argument of latitude `f`, and the Moon’s mean anomaly `n`. Subroutine 200 calculates gamma `g` (the minimum distance of the Moon’s shadow axis from Earth’s center) and the penumbra/umbra size parameter `u`. ### Eclipse Classification Logic Solar eclipse types are determined by a cascade of `IF` tests at lines 58–66, based on the values of `g`, `u`, and a computed threshold `w`: - `ABS g >= 0.9972` → Partial eclipse of the Sun (line 68) - `u < 0` → Total (line 60) - `u > 0.0047` → Annular (line 62) - `u < w` (where `w = 0.00464*COS(ASN g)`) → Annular/Total (hybrid, line 65) - Otherwise → Annular (line 66) Lunar eclipses (lines 72–93) compute two magnitude values: `m1` (umbral) and `m2` (penumbral). If `m1 < 0` the eclipse is penumbral only; if `m1 <= 1.00` it is partial umbral; otherwise it is total. ### Calendar Conversion Subroutine 300 implements the standard Julian Day to Gregorian/Julian calendar algorithm. The branch at lines 310–320 handles the Gregorian reform: dates before JD 2299161 (October 15, 1582) use the Julian calendar path, while later dates apply the Gregorian correction via the intermediate variable `a`. This makes the program astronomically correct for the full year range 1000–4000. ### Time Formatting with Lookup Strings Rather than using `STR$` and padding, the program pre-builds the string `n$` at line 1020 containing the two-digit representations “00” through “60” concatenated. Hours and minutes are then extracted by slicing: `n$(2*h+1 TO 2*h+2)`. This avoids formatting conditionals and is a compact BASIC idiom well-suited to memory-limited environments. Similarly, `d$` holds two-character day abbreviations and `m$` holds four-character month abbreviations for date display. ### Output Stream Abstraction All output is directed to stream `#4`, which is opened to either `"s"` (screen) or `"p"` (printer) at lines 1230 and 1300 respectively. This clean abstraction means all PRINT statements in the subroutines are identical regardless of output device. The user selects the device by pressing `1` or `2`, with input validated at line 1210. ### UDG Definition Lines 1030–1040 read 8 pairs of bytes from the `DATA` statement at line 2000 and POKE them into the UDG area for characters `"a"` and `"b"` (using `USR "a"` and `USR "b"`). The defined UDGs are used in the title screen display at line 1220 via `CHR$ 144` and `CHR$ 145`, providing decorative graphical markers. ### Notable Techniques and Idioms - `DEF FN d(x)=INT (1000*x+0.5)/1000` at line 5 provides a rounding-to-3-decimal-places function used for clean magnitude display. - The expression `12*(e>=13.5)` at line 350 exploits the fact that Boolean results are 1 or 0 to perform a conditional subtraction inline. - `PAUSE 0` is not used; instead the program uses `PAUSE 30` (line 1195) for brief display delays. - The year boundary check at line 10 (`IF yr>y THEN GO TO 9000`) and line 57 (`IF yry THEN GO TO 9000 11 RETURN 12 PRINT #4;"________________________________": PRINT #4: RETURN 15 LET f=24*f: LET h=INT f 20 LET n=INT (60*(f-h)) 25 LET t$=n$(2*h+1 TO 2*h+2)+":"+n$(2*n+1 TO 2*n+2): LET d=z+1.0: LET d=d-(7*INT (d/7))+1 30 PRINT #4;"Date: ";d$(2*d-1 TO 2*d);" ";m$(4*m-3 TO 4*m);n$(2*dy+1 TO 2*dy+2);",";yr;" ";t$ 35 RETURN 40 LET f=24*f: LET h=INT f 42 LET n=INT (60*(f-h)) 44 LET t$=n$(2*h+1 TO 2*h+2)+":"+n$(2*n+1 TO 2*n+2) 46 PRINT #4;t$;" GMT" 48 RETURN 50 BEEP 0.05,22: LET j=(y-1900)*12.3685: LET j=INT j: LET mn=1 52 PRINT #4;" Solar/Lunar Eclipses ";y: PRINT #4;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''": 54 LET k=j: GO SUB 100 55 IF ABS (SIN f)>0.359 THEN GO TO 72 56 GO SUB 200: IF ABS g>(1.5432+u) THEN GO TO 72 57 GO SUB 150: GO SUB 300: GO SUB 10: IF yr=0.9972 THEN GO TO 68 59 PRINT #4;"Central Eclipse - "; 60 IF u<0 THEN PRINT #4;" Total ":: GO SUB 15:: GO SUB 500: GO SUB 12: GO TO 72 62 IF u>0.0047 THEN PRINT #4;"Annular":: GO SUB 15: GO SUB 500: GO SUB 12: GO TO 72 64 LET w=0.00464*COS (ASN g) 65 IF u0.25 THEN PRINT #4;"northern hemisphere": RETURN 520 IF g<-0.25 THEN PRINT #4;"southern hemisphere": RETURN 530 PRINT #4;"equatorial regions" 540 RETURN 600 LET p=1.0129-u: LET t=0.4679-u: LET n=0.5458+0.04*COS w 605 IF t*t-g*g<=0 THEN RETURN 608 IF p*p-g*g<=0 THEN RETURN 610 LET pp=SQR (p*p-g*g)/24/n 620 LET tp=SQR (t*t-g*g)/24/n 630 PRINT #4: LET t=jd: LET jd=t-pp: GO SUB 300: PRINT #4;" Start partial: ";: GO SUB 40 640 LET jd=t-tp: GO SUB 300: PRINT #4;" Start - total: ";: GO SUB 40: LET jd=t: GO SUB 300 650 PRINT #4;" Max. eclipse : ";: GO SUB 40: LET jd=t+tp: GO SUB 300: PRINT #4;" End of total : ";: GO SUB 40: LET jd=t+pp 660 GO SUB 300: PRINT #4;" End - partial: ";: GO SUB 40 670 RETURN 1000 LET d$="SuMoTuWeThFrSa" 1010 LET m$="Jan.Feb.Mar.Apr.May Jun.Jul.Aug.Sep.Oct.Nov.Dec." 1020 LET n$="00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960" 1030 BEEP 0.05,22: BEEP 0.06,20: POKE 23609,10: RESTORE 2000 1040 FOR m=0 TO 7: READ n,f: POKE USR "a"+m,n: POKE USR "b"+m,f: NEXT m 1100 BORDER 5: PAPER 3: CLS 1150 PRINT PAPER 6;AT 2,3;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";AT 3,3;"\: Solar & Lunar Eclipses \ :";AT 4,3;"\: \ :";AT 5,3;"\: \* 1985 I. Auersbacher \ :";AT 6,3;"\:.\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.:" 1155 PLOT 0,0: DRAW 0,175: DRAW 255,0: DRAW 0,-175: DRAW -255,0 1160 PRINT PAPER 7;AT 8,4;"Enter Year:"; 1165 INPUT y: IF y<1000 OR y>4000 THEN BEEP 1.5,-22: GO TO 1165 1170 PRINT PAPER 6;" ";y;" " 1180 PAUSE 30: PRINT PAPER 6;AT 10,4;"Output to which device? " 1190 PRINT PAPER 7;AT 12,9;"1-TV Screen ";AT 13,9;"2-TS Printer" 1195 PAUSE 30: PRINT PAPER 6;AT 15,4;"Please pick option (1-2)" 1200 LET q$=INKEY$: IF q$="" THEN GO TO 1200 1210 LET t=CODE q$-48: IF (t<1)+(t>2) THEN BEEP 0.5,-15: BEEP 0.6,-20: GO TO 1200 1220 BEEP .05,22: PRINT INK 0;AT 11+t,6;CHR$ 144; INK 6;CHR$ 145 1230 PAUSE 75: IF t=1 THEN OPEN #4,"s": PAPER 7: CLS : GO TO 50 1300 OPEN #4,"p": PRINT FLASH 1; PAPER 7;AT 18,4;" See printer for output ": GO TO 50 2000 DATA 0,24,0,48,127,96,127,255,127,255,115,248,115,248,127,240 3000 SAVE "eclipse" LINE 8: 3100 STOP : STOP 9000 LPRINT : LPRINT : LPRINT : CLOSE #4: BEEP .2,22: BEEP .2,20 ```