## 3.3 Julian Day Number to Gregorian and Julian Dates - Implementation Examples

### 3.3.0.1 Choices to be made

The following decisions have to be made regarding any implementation:

• Are dates specified in the Gregorian or Julian Calendar?
• What range of dates are to be supported?
• What number word size will be used?
• Is the greatest integer function available or is only the truncation function?
• Is real arithmetic available and required?
• Is conditional execution such as "IF/THEN" supported?

### 3.3.0.2 Notation

[x] = the greatest integer that does not exceed x. For example, [-1.5]=-2. This is sometimes called the floor function (for example in C/C++).

INT(x) = [x] NOTE: some computer languages have a different definition.

FIX(x) = the number x without its fraction. For example, FIX(-1.5)=-1

x\y = FIX(x/y)

### 3.3.1 Julian Day Number to Gregorian Date

1. The following sequence calculates Gregorian year Y, month M, and day D from Julian Day Number JD. It uses real arithmetic.

Z = INT(JD - 1721118.5)
R = JD - 1721118.5 - Z
G = Z - .25
A = INT(G / 36524.25)
B = A - INT(A / 4)
year = INT((B+G) / 365.25)
C = B + Z - INT(365.25 * year)
month = FIX((5 * C + 456) / 153)
day = C - FIX((153 * month - 457) / 5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• The range of years that are supported is only limited by the word size of the implementation.
• Although FIX((5*C + 456)/ 153) and FIX((153*M-457)/5) are elegant expressions, the use of indexed arrays are usually a faster implementation.
• Some languages only implement, within the language proper, the greatest integer function for a real argument. One can, of course, always create this function as part of the program itself.

2.      The following sequence calculates Gregorian year Y, month M, and day D from Julian Day Number JD. It uses integer arithmetic except for the values of JD, R, and Day since the Julian Day Number may be fractional.

Z = INT(JD - 1721118.5)
R = JD - 1721118.5 - Z
H = 100*Z - 25
A = INT(H / 3652425)
B = A - INT(A / 4)
year = INT((100*B+H) / 36525)
C = B + Z - 365 * year - INT( year/4)
month = FIX((5 * C + 456) / 153)
day = C - FIX((153 * month - 457) / 5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• The range of years that are supported is only limited by the word size of the implementation.
• The greatest integer function can be replaced by integer division if JD > March 1 of the year zero.
• Although FIX((5*C + 456)/ 153) and FIX((153*M-457)/5) are elegant expressions, the use of indexed arrays are usually a faster implementation.
• Some languages only implement the greatest integer function for a real argument.

3.      The following sequence calculates Gregorian year Y, month M, and day D from Julian Day Number JD. It uses integer arithmetic except for the values of JD, R, and Day since the Julian Day Number may be fractional. It uses integer division and the shift right operator to effect integer division by powers of 2.

****WARNING*** Only valid for dates greater than or equal to 1721118.25 (April 28.75 of the year zero).

Z = INT(JD - 1721118.5)
R = JD - 1721118.5 - Z
H = 100*Z - 25
A = H \ 3652425
B = A - SHIFTRIGHT(A,2)
year = (100*B+H) \ 36525
C = B + Z - 365 * year - SHIFTRIGHT( year,2)
month = SHIFTRIGHT((535*C + 48950),14)
day = C - SHIFTRIGHT( (979*M-2918),5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• Only valid for dates greater than or equal to 1721118.25 (April 28.75 of the year zero).
• Although SHIFTRIGHT((535*C + 48950),14) and SHIFTRIGHT( (979*M-2918),5) are elegant expressions, the use of indexed arrays are usually a faster implementation.

4.      QBASIC Implementation as a subroutine - using real arithmetic:

Note: & indicates 32-bit (long) integer and # indicates double precision real

SUB jdtog1 (jd AS DOUBLE, year AS LONG, month AS INTEGER, day AS DOUBLE)
'INPUT: jd = Julian Day Number
'OUTPUT: Gregorian year, month, and day
Z& = INT(jd - 1721118.5#) 'Day 1 is on March 1 of the year 0
R# = jd - 1721118.5# - Z& 'the fractional part of the day
G# = Z& - 0.25#
A& = INT(G# / 36524.25#) 'whole centuries
B& = A& - INT(A& / 4#) 'Julian days in whole centuries - 0.25
year = INT((G#+B&) / 365.25#)
C& = Z& +B& - INT(365.25 * year) 'days in the year
month = (5 * C& + 456) \ 153
day = C& - ((153 * month - 457) \ 5) + R#
IF month > 12 THEN 'convert to year that starts January 1
year = year + 1
month = month - 12
END IF 'convert to year that starts January 1
END SUB

5.      QBASIC Implementation as a subroutine - Integer arithmetic version:

SUB jdtog2 (JD AS DOUBLE, year AS LONG, month AS INTEGER, day AS DOUBLE)
'***WARNING*** ONLY VALID IF JD > 1721118.25 (February 28.75 of year zero)
'INPUT: jd = Julian Day Number
'OUTPUT: Gregorian year, month, and day
Z& = INT(JD - 1721118.5) 'Day 1 is on March 1 of the year 0
R# = JD - 1721118.5 - Z& 'the fractional part of the day
H& = 100*Z& - 25
A& = H&\3652425 'whole centuries
B& = A& - A&\4 'adjustment to find the Julian days in whole centuries
year = (100*B&+H&) \ 36525
C& = B& + Z& - 365 * year - year\4 'days in the year
month = (5 * C& + 456) \ 153
day = C& - (153 * month - 457) \ 5 + R#
IF month > 12 THEN 'convert to year that starts January 1
year = year + 1
month = month - 12
END IF 'convert to year that starts January 1
END SUB

1. In Astronomical Algorithms, 1991, page 63, Jean Meeus (essentially) gives the following algorithm. This can be shown to be an instance of our derived algorithm provided the Julian Day numbers is greater than or equal to 1867215.75, that is, for dates from February 29.25, 400 in the proleptic Gregorian calendar.

Z = FIX(JD +0.5)
R = JD + 0.5 - Z
G = FIX((Z - 1867216.25)/36524.25)
A = Z + 1 + G - FIX(G/4)
B = A + 1524
C = FIX((B - 122.1)/365.25)
D = FIX(365.25*C)
E = FIX((B - D)/30.6001)
Day of month = B - D - FIX(30.6001*E) + R
If E<14 then >
Month = E - 1
Year = C - 4716
else
Month = E - 13
Year = C - 4715
end if

• This algorithm is only valid for Julian Day numbers greater than or equal to 1867216.25, that is, dates from February 29.75, 400 in the proleptic Gregorian calendar. Note that Meeus states that his algorithm is valid for all non-negative Julian Day numbers but, in fact, his algorithm switches to another form that finds the Julian Date rather than the Gregorian date if the Julian Day Number represents a date before the Gregorian Reform.
• If FIX is replaced with the greatest integer function, the algorithm is valid for all Julian Day Numbers within the range of the word size.
• Meeus states that the 30.6001 in the algorithm can't be replaced by 30.6. An algorithm could be developed that uses a slope of 1/30.6 = 0.03267973856209151 by using a linear function with a Y intercept within the range of 2.980392156862745 to 2.986928104575163.

7.      For dates in the Gregorian calendar at noon, The Explanatory Supplement to the Astronomical Almanac,1992, page 604, gives an algorithm by Fliegel and Van Flandern that calculates dates after November 23, -4713, given an integral Julian Day Number. This algorithm can be shown to be an instance of the general form described in the algorithm development section.

L = JD + 68569
N = FIX((4*L)/146097)
L = L - FIX((146097 * N + 3)/4)
I = FIX(4000 *(L + 1)/1461001)
L = L - FIX((1461*I)/4) + 31
J = FIX((80*L)/2447)
D = L - FIX((2447*J)/80)
L=FIX(J/11)
M = J + 2 - 12*L
Y = 100*(N-49) + I + L

• The algorithm is not valid for dates before November 23, -4713 (negative JD numbers).
• The algorithm could be easily modified to handle Julian Day Numbers with a non-zero fractional part. The other algorithms in this section show how this can be done.
• The algorithm is designed so that it can be directly implemented using integer arithmetic and the usual integer division.
• This algorithm uses the alternative method of determining the year given the number of whole centuries as was described in section 3.1.2.5.

### 3.3.2 Julian Day Number to Julian date - Implementation Examples

1. The following sequence calculates Julian year Y, month M, and day D from Julian Day Number JD. It uses real arithmetic.

Z = INT(JD - 1721116.5)
R = JD - 1721116.5 - Z
year = INT((Z - 0.25) / 365.25)
C = Z - INT(365.25 * year)
month = FIX((5 * C + 456) / 153)
day = C - FIX((153 * month - 457) / 5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• The range of years that are supported is only limited by the word size of the implementation.
• Although FIX((5*C + 456)/ 153) and FIX((153*M - 457)/5) are elegant expressions, the use of indexed arrays are usually a faster implementation.
• Some languages only implement, within the language proper, the greatest integer function for a real argument. One can, of course, always create this function as part of the program itself.

2.      The following sequence calculates Julian year Y, month M, and day D from Julian Day Number JD. It uses integer arithmetic except for the values of JD, R, and Day since the Julian Day Number may be fractional.

Z = INT(JD - 1721116.5)
R = JD - 1721116.5 - Z
year = INT((100*Z - 25) / 36525)
C = Z - 365 * year - INT( year/4)
month = FIX((5 * C + 456) / 153)
day = C - FIX((153 * month - 457) / 5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• The range of years that are supported is only limited by the word size of the implementation.
• The greatest integer function can be replaced by integer division if JD > April 29 of the year zero.
• Although FIX((5*C + 456)/ 153) and FIX((153*M - 457)/5) are elegant expressions, the use of indexed arrays are usually a faster implementation.
• Some languages only implement the greatest integer function for a real argument.

3.      The following sequence calculates Julian year Y, month M, and day D from Julian Day Number JD. It uses integer arithmetic except for the values of JD, R, and Day since the Julian Day Number may be fractional. It uses integer division and the shift right operator to effect integer division by powers of 2.

****WARNING*** Only valid for dates greater than or equal to 1721116.25 (February 28.75 of the year zero).

Z = INT(JD - 1721116.5)
R = JD - 1721116.5 - Z
year = FIX((100*Z - 25)) / 36525)
C = Z - 365 * year - SHIFTRIGHT( year,2)
month = SHIFTRIGHT((535*C + 48950),14)
day = C - SHIFTRIGHT( (979*M-2918),5) + R
IF month > 12 THEN
year = year + 1
month = month - 12
END IF

• Only valid for dates greater than or equal to 1721116.25 (February 28.75 of the year zero).
• Although SHIFTRIGHT((535*C + 48950),14) and SHIFTRIGHT( (979*M-2918),5) are elegant expressions, the use of indexed arrays are usually a faster implementation.

4.      QBASIC Implementation as a subroutine - using real arithmetic:

Note: & indicates 32-bit (long) integer and # indicates double precision real

SUB jdtoj1 (jd AS DOUBLE, year AS LONG, month AS INTEGER, day AS DOUBLE)
'INPUT: jd = Julian Day Number
'OUTPUT: Julian year, month, and day
Z& = INT(jd - 1721116.5#) 'Day 1 is on March 1 of the year 0
R# = jd - 1721116.5# - Z& 'the fractional part of the day
year = INT((Z& - 0.25#) / 365.25#)
C& = Z& - INT(365.25 * year) 'days in the year
month = (5 * C& + 456) \ 153
day = C& - ((153 * month - 457) \ 5) + R#
IF month > 12 THEN 'convert to year that starts January 1
year = year + 1
month = month - 12
END IF 'convert to year that starts January 1
END SUB

5.      QBASIC Implementation as a subroutine - Integer arithmetic version:

SUB jdtoj2 (JD AS DOUBLE, year AS LONG, month AS INTEGER, day AS DOUBLE)
'***WARNING*** ONLY VALID IF JD > 1721116.5 (April 29 of day zero or greater)
'INPUT: jd = Julian Day Number
'OUTPUT: Julian year, month, and day
Z& = INT(JD - 1721116.5) 'Day 1 is on March 1 of the year 0
R# = JD - 1721116.5 - Z& 'the fractional part of the day
year = (100*Z& - 25) \ 36525
C& = Z& - 365 * year - year\4 'days in the year
month = (5 * C& + 456) \ 153
day = C& - (153 * month - 457) \ 5 + R#
IF month > 12 THEN 'convert to year that starts January 1
year = year + 1
month = month - 12
END IF 'convert to year that starts January 1
END SUB

1. In Astronomical Algorithms, 1991, page 63, Jean Meeus (essentially) gives the following algorithm. This can be shown to be an instance of the previously derived algorithm provided the Julian Day numbers is greater than or equal to 1867215.75, that is, for dates from February 29.25, 400 in the proleptic Gregorian calendar.

Z = FIX(JD +0.5)
R = JD + 0.5 - Z
B = Z + 1524
C = FIX((B - 122.1)/365.25)
D = FIX(365.25*C)
E = FIX((B - D)/30.6001)
Day of month = B - D - FIX(30.6001*E) + R
If E<14 then >
Month = E - 1
Year = C - 4716
else
Month = E - 13
Year = C - 4715
end if