Julian Day

Developer(s): Ben H. Jackson
Date: 1984
Type: Program
Platform(s): TS 2068
Tags: Utility

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:

CallDIS (divisor)Purpose
1st (line 3030)36524.25Extract century count → contributes to Y
2nd (line 3060)365.25Extract year within century → adds to Y
3rd (line 3105)30.6Extract 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.

Content

Appears On

One of the largest single-tape collections anywhere, with over 40 programs spanning flight planning, satellite tracking, hydrology, Forth programming, a 17-game mega-pack, and a complete calligraphic font renderer. A snapshot of a thriving Texas user group at its peak.

Related Products

Related Articles

Related Content

Image Gallery

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 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top