--- title: "Julian Day" id: 64544 type: "computer_media" slug: "julian-day" url: "http://localhost/computer_media/julian-day/" markdown_url: "http://localhost/computer_media/julian-day.md" published_at: "2026-03-02T02:21:56+00:00" modified_at: "2026-03-30T21:43:23+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/03/SCR-20260301-snal.png" excerpt: "A two-way Julian Day Number converter that handles BC dates, century corrections, and day-of-week calculation via a clever shared subroutine." 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: "Ben H. Jackson" slug: "ben-h-jackson" taxonomy: "indiv" url: "http://localhost/indiv/ben-h-jackson/" genre: - name: "Utility" slug: "utility" taxonomy: "genre" url: "http://localhost/type/utility/" media_contents: - id: 60550 title: "Fort Worth TS2068 Club Library Tape" type: "computer_media" url: "http://localhost/computer_media/fort-worth-ts2068-club-library-tape/" media_type: "Program" programmers: - name: "Ben H. Jackson" slug: "ben-h-jackson" taxonomy: "indiv" url: "http://localhost/indiv/ben-h-jackson/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Julian%20Day%20%281984%29%28Jackson%2C%20Ben%29%28TS2068%29%28US%29%28PRogram%29.zip" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2026/03/SCR-20260301-snal.png" - url: "http://localhost/wp-content/uploads/2026/03/SCR-20260301-smux.png" media_type_tags: "Utility" --- # Julian Day Converts Gregorian calendar and Julian dates. Based on a TI-59 program by Charles Kluepfel. This program converts dates between the Gregorian calendar and Julian Day Numbers, a continuous count of days used in astronomy. It accepts input in either direction: a calendar date (month, day, year, and AD/BC era) to its Julian Day Number, or a Julian Day Number back to a calendar date. The Gregorian-to-Julian conversion handles the BC/AD era transition by negating and shifting the year, and corrects for century leap-year irregularities using the standard INT(Y/100) adjustment. A shared subroutine at line 4000 performs the repeated division-with-remainder operations needed during the reverse (JD-to-date) conversion. The day-of-week calculation uses a fractional-part trick on (JD+1)/7 to map the Julian Day Number to a named weekday. *** ## Program Structure The program is divided into clearly labelled sections using `REM` blocks. Control flow is menu-driven from line 110, branching to one of two main routines: 1. **Lines 1000–2230:** Gregorian date → Julian Day Number, followed by day-of-week display, then looping back to line 1000. 2. **Lines 3000–3170:** Julian Day Number → Gregorian date, looping back to line 3000. 3. **Lines 4000–4090:** Shared subroutine used three times during JD-to-date conversion. Both main routines loop indefinitely (`GO TO 1000` at line 2230, `GO TO 3000` at line 3170), requiring a BREAK to exit. There is no unified main loop or return-to-menu option after either calculation path is entered. ## Gregorian-to-Julian Conversion (Lines 2000–2150) The algorithm follows the standard astronomical formula, ported from a TI-59 program by Charles Kluepfel (1978). Key steps: - Months January and February are treated as months 13 and 14 of the previous year (lines 2015–2020), a standard technique that simplifies the 30.6-day month-length formula. - For BC years, the astronomical year numbering convention is applied at line 1045: `Y = -(Y-1)`, mapping 1 BC → 0, 2 BC → −1, etc. - Negative years trigger a 400-year block alignment at lines 2055–2070, accumulating a correction in `J` and shifting `Y` into a non-negative range before the main formula runs. - The Gregorian century correction is `INT(Y/100)` scaled by 0.75 and subtracted at line 2130, implementing the standard `-INT(A/100)+INT(A/400)+2` correction folded into the constant 1721060. A notable oddity is the use of `DIS` at lines 2140–2150: it is set to `JD` (which is 0 at this point), then `JD` is set to `J`, and `DIS = J - 0`, so the display value always equals `J`. This appears to be a vestige of a more general accumulation pattern from the original calculator program. ## Julian-Day-to-Gregorian Conversion (Lines 3000–3170) This section calls the subroutine at line 4000 three times to successively extract the year century, year within century, and month. The logic relies on a shared register protocol using `T`, `DIS`, `XT`, and `SAVE`: | Call | DIS (divisor) | Purpose | | --- | --- | --- | | 1st (line 3030) | 36524.25 | Extract century count → contributes to `Y` | | 2nd (line 3060) | 365.25 | Extract year within century → adds to `Y` | | 3rd (line 3105) | 30.6 | Extract month number → sets `M` | After the third call, a swap at line 3120 puts the day remainder into `DIS` and `D = DIS + 1` at line 3130. The month adjustment for January/February (adding back the 12 offset) is at lines 3140–3150, and BC conversion at line 3155 using `ABS Y + 1`. ## Shared Subroutine (Lines 4000–4090) The subroutine performs an integer division of `T` by `DIS`, returning the quotient in `J` and the remainder (scaled back to the original units) in `T`. It uses a swap idiom with `XT` as a temporary register since the platform lacks multi-variable swap syntax. Key steps: - Line 4010: Swaps `DIS` and `T`; saves original `DIS` into `J` and pre-computes `SAVE = DIS + 0.9`. - Lines 4030–4032: Computes `DIS = INT((DIS+0.9)/T)`, with a correction `+1` if negative before truncation — handling negative-year edge cases. - Line 4050: Computes remainder as `SAVE - quotient * original_divisor`. - Lines 4070–4071: Applies the same negative-integer floor correction to the remainder `T`. The `+0.9` bias before `INT` is used in place of rounding, since the inputs are not exact integers due to floating-point intermediate values. ## Day-of-Week Calculation Lines 2210–2227 use a fractional-part technique: `(JD+1)/7 - INT((JD+1)/7)` gives the fractional day position within a week cycle, then `INT(7*frac + 1.5)` maps it to an integer 1–7. Seven consecutive `IF` statements print the named weekday. This is slightly inefficient but clear; a `DATA`/array approach was not available in standard Sinclair BASIC of this era. ## Notable Bugs and Anomalies - Line 20’s `REM` says “CALENDER” (misspelling of “calendar”) — a cosmetic issue only. - The variable `SAVE` used in the subroutine (line 4010) is not declared in the variable list in the `REM` at lines 30–31, suggesting it was added during porting. - The menu at line 110 does not validate input beyond checking for 0 or 1; any other value causes the program to fall through both `IF` checks and re-display the `PRINT AT` line from line 100, effectively looping but without re-prompting cleanly. - Line 3080 adds 91.4 to `T`, which is a fixed offset used in month extraction; this is a direct translation of the TI-59 register arithmetic and works correctly but is not self-documenting. - The `© = RESET` keyword in the title `REM` at line 10 is the TS2068 `RESET` token, used here as part of the copyright symbol in the author credit — a coincidence of character encoding. ## Source Code ``` 10 REM "JULIAN DAY" © by Beb H.Jackson, 1984; ALL RIGHTS RESERVED 20 REM -- CONVERTS GREGORIAN CALENDER & JULIAN DAY 25 REM SOURCE-- TI-59 PROGRAM "JULIAN DAY NUMBER CALENDER" BY CHARLES KLUEPFEL 2/23/78 30 REM VARIABLES-- M-- MONTH D-- DATE Y-- YEAR E$-- ERA [AD or BC] JD--JULIAN DAY J-- JULIAN ACCUM 31 REM DIS--DISPLAY REG WD--WEEK DAY[1=SUN] F-- MENU FLAG WR--WORKING REG XT--DISPLAY<>TEST REG T -- TEST REGISTER 100 PRINT AT 1,5;"JULIAN DAY PROGRAM" 110 INPUT "DATE TO JD: 0 JD TO DATE: 1 CHOICE=";F 120 IF F=0 THEN GO TO 1000 130 IF F=1 THEN GO TO 3000 1000 INPUT "MONTH [1 TO 12]=";M 1005 PRINT "MONTH=";M 1010 INPUT "DATE [1 TO 31]=";D 1015 PRINT "DATE=";D 1020 INPUT "YEAR [XXXX]=";Y 1030 INPUT "[ AD or BC ]=";E$ 1035 IF E$<>"AD" AND E$<>"BC" THEN GO TO 1030 1040 PRINT "YEAR=";Y;" ";E$ 1045 IF E$="BC" THEN LET Y=-1*( Y-1) 2000 REM --GREG TO JULIAN 2010 LET J=0: LET JD=0 2015 IF (M-3)>=0 THEN GO TO 2050 2017 LET Y=Y-1 2020 LET M=M+12 2050 IF Y>=0 THEN GO TO 2100 2055 LET J=146097 2060 LET J=J*((INT (Y/400))-1) 2070 LET Y=Y-400*((INT (Y/400))-1) 2100 LET J=J+D 2110 LET J=J+INT (30.6*M-32.4) 2120 LET J=J+INT (365.25*Y) 2130 LET J=J+1721060-INT (.8+.75*INT (Y/100)) 2140 LET DIS=JD 2145 LET JD=J 2150 LET DIS=J-DIS 2160 PRINT "JULIAN DAY=";DIS 2200 REM --DAY OF WEEK 2210 LET DIS=(JD+1)/7-INT ((JD+1)/7) 2220 LET WD=INT (7*DIS+1.5) 2221 IF WD=1 THEN PRINT "SUNDAY" 2222 IF WD=2 THEN PRINT "MONDAY" 2223 IF WD=3 THEN PRINT "TUESDAY" 2224 IF WD=4 THEN PRINT "WEDNESDAY" 2225 IF WD=5 THEN PRINT "THURSDAY" 2226 IF WD=6 THEN PRINT "FRIDAY" 2227 IF WD=7 THEN PRINT "SATURDAY" 2230 GO TO 1000 3000 REM --JULIAN DAY TO GREG 3005 INPUT "JULIAN DAY=";JD 3007 PRINT "JD=";JD 3010 LET T=JD+32045-1 3020 LET DIS=36524.25 3030 GO SUB 4000 3040 LET Y=100*DIS-4800 3050 LET DIS=365.25 3060 GO SUB 4000 3070 LET Y=Y+DIS 3080 LET T=T+91.4 3090 LET DIS=30.6 3105 GO SUB 4000 3110 LET M=DIS 3120 LET XT=DIS: LET DIS=T: LET T=XT 3130 LET D=DIS+1 3140 IF M<13 THEN GO TO 3154 3150 LET Y=Y+1: LET M=M-12 3154 LET E$="AD" 3155 IF Y<=0 THEN LET Y=ABS Y+1: LET E$="BC" 3160 PRINT M;"-";D;"-";Y;" ";E$ 3170 GO TO 3000 4000 REM --JD TO GREG SBR 4010 LET XT=DIS: LET DIS=T: LET T=XT: LET J=T: LET SAVE=DIS+.9 4030 LET DIS=((DIS+.9)/T) 4031 IF DIS<0 THEN LET DIS=DIS+1 4032 LET DIS=INT DIS 4040 LET WR=DIS: LET DIS=J: LET J=WR 4050 LET DIS=-1*WR*DIS+SAVE 4060 LET XT=DIS: LET DIS=T: LET T=XT 4070 IF T<0 THEN LET T=T+1 4071 LET T=INT T 4080 LET DIS=J 4090 RETURN ```