Julian Day

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

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

This tape is a compilation of programs from user group members (Robert Burton, David Baulch, Frank Bouldin, Chuck Dawson, Ryan

Related Products

Related Articles

Related Content

Image Gallery

Julian Day

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