Captured from a message in a public CompuServe Forum
Note from the author from the PL/1 version
Julian (sense 1) date routines, handling Julian (sense 2) and Gregorian calendars. Algorithm is valid from 4713 B.C. to 19,999 A.D. This version is known to be free of errors.
Based on Pascal code copyright 1985 by Michael A. Covington, published in P.C. Tech Journal, December 1985, based on formulae appearing in Astronomical Formulae for Calculators by Jean Meeus. Reconversion to normal Julian epoch, integer arithmetic, 4000-year correction, and translation to PL/I by John W. Kennedy
Historical exceptions _not_ allowed for in this module:
Until Julius Caesar established the Julian calendar in 45 B.C., calendars
were irregular.
This module assumes the Julian calendar back to 4713 B.C.
The Julian calendar was altered in 8 B.C. From 45 B.C. to 8 B.C., the months
were Jan=31, Feb=29(30), Mar=31, Apr=30, May=31, Jun=30, Jul=31, Aug=30,
Sep=31, Oct=30, Nov=31, Dec=30
This module assumes the month lengths as we know them. Leap years from 45
B.C. to 8 A.D. were miscalculated: (45, 42, 39, 36, 33, 30, 27, 24, 21,
18, 15, 12, 9, then none at all until 8 A.D.) This module assumes leap years
every four years, as they were meant to have been. January 1 was not always
the first day of the year. The United Kingdom, in particular, started the
year on March 25 until 1752. (However, the year ended on December 31, leaving
the days between in limbo.) This module assumes January 1 is the first day
of the year. Leap-year day was originally done by having February 24 (25
from 45 to 8 B.C.) twice. This module assumes Leap-year day is February
29.
The "Transition" argument is the first Julian date to be considered as belonging
to the Gregorian calendar. Usual values are:
2299161 = October 5/15, 1582, as in Rome, or 2361222 = September 3/14,
1752, as in the United Kingdom and the American colonies
/* sample routines to convert dates */
call Charout , "Enter a date in the format dd.mm.yyyy: "
curDMYDate = lineIn()
curJulianDate = DMYToJulian( curDMYDate )
say "DMYToJulian(" || curDMYDate || ") is " || curJulianDate
say "JulianToDMY(" || curJulianDate || ") is " || ,
JulianToDMY( curJulianDate )
exit 0
/* ------------------------------------------------------------------ */
/* function: Convert a date from Julian to DMY */
/* */
/* call: JulianToDMY julianDate {trans} */
/* */
/* where: julianDate - the date in julian format */
/* trans - see note above */
/* */
/* returns: the date in the format dd.mm.yyyy */
/* */
/* */
JulianToDMY: PROCEDURE
Arg J Trans
if Trans = "" then
Trans = 2299161
if J < Trans then
A = J
Else
do
AA = J - 1721120
AC = Trunc(AA / 1460969)
AB = 31 * AC
AA = AA - AC * 1460969
AC = Trunc(AA / 146097)
AB = AB + 3 * AC
AA = AA - AC * 146097
if AA = 146096 then
AB = AB + 3
Else
AB = AB + Trunc(AA / 36524)
A = J + (AB - 2)
end
B = A + 1524
C = Trunc((20 * B - 2442) / 7305)
D = Trunc(1461 * C / 4)
EE = B - D
E = Trunc(10000 * EE / 306001)
YMDD = EE - Trunc(306001 * E / 10000)
if E >= 14 then
YMDM = E - 13
else
YMDM = E - 1
if YMDM > 2 then
Y = C - 4716
else
Y = C - 4715
if Y < 1 then
YMDY = Y - 1
else
YMDY = Y
RETURN YMDD || '.' || YMDM || '.' || YMDY
/* ------------------------------------------------------------------ */
/* function: Convert a date from DMY to Julian */
/* */
/* call: DMYToJulian dmyDate {trans} */
/* trans - see note above */
/* */
/* where: dmyDate - the date in the format dd.mm.yyyy */
/* */
/* returns: the date in Julian format */
/* */
/* */
DMYToJulian: PROCEDURE
parse arg dmyDate trans
parse var dmyDate YMDD "." YMDM "." YMDY
if Trans = "" then
Trans = 2299161
AY = YMDY
if YMDY < 0 then
Y = YMDY + 4717
else
Y = YMDY + 4716
if YMDM < 3 then
do
M = YMDM + 12
Y = Y - 1
AY = AY - 1
end
else
M = YMDM
D = Trunc((1461 * Y) / 4) + Trunc((153 * (M + 1)) / 5) + YMDD - 1524
G = D + 2 - Trunc(AY / 100) + Trunc(AY / 400) - Trunc(AY / 4000)
if G >= Trans then
thisRC = G
else
thisRC = D
RETURN thisRC