DAYDATE: Computing Days between Dates, the Day of the Week, etc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
by Prof. W. Kahan
Elect. Eng. & Computer Science, Univ. of Calif. at Berkeley
16 Sept. 1992
What is desired is a program that can tell how many days elapse between
any two given dates, or on what day of the week a given date falls, or
what date comes a specified number of days past a given date. To write
such a program, a programmer must understand the Gregorian calendar.
The calendar promulgated by Julius Caesar in 45 B.C. had slipped out
of step with the seasons so far by 4 Oct. 1582 that Pope Gregory XIII
declared the next day to be 15 Oct. 1582 and promulgated the calendar
that now bears his name. Obedient Catholics accepted the new calendar
hoping to enter Heaven ten days sooner. But adherents to the Church
of England declined to do likewise, keeping Julius Caesar's calendar
in force throughout the British Empire. Finally, Parliament decided
to rejoin Western Europe and declared the day after 2 Sept. 1752 to
be 14 Sept. 1752. That day riots broke out among Englishmen who
resented the loss of eleven days from their lives. Russia adopted the
Gregorian calendar only after the October revolution in 1917.
Why so much fuss over a calendar? The trouble is that a solar year has
about 365.2422 days on average. Julius Caesar approximated that with
a 365 day year plus an extra 366th day, Feb. 29, every fourth year
( called a " leap-year "). His years lasted a little too long, 365.25
days on average, causing his calendar to lag farther behind the seasons
every fourth year. Gregory XIII accepted the best advice available at
the time, which was to deny leap-year status to any century year not
divisible by 400 as well as 100. Hence, 1600 was a leap-year, and
2000 will be another; but 1700, 1800 and 1900 were not leap-years.
Gregory's years last 355.2425 days on average; they last a tiny bit
too long. A better scheme would deny leap-year status to millennial
years divisible by 4000 too. If this better scheme is adopted, the
years 2000 and 6000 will be leap-years but not 3000, 4000, 5000,
7000, 8000, 9000 . Then a year will last 365.24225 days on average,
which should keep seasons in their places for at least 16,000 years.
How many days pass in the course of some number, say y , of years?
To account properly for leap-years, we number the years from a notional
year numbered 0 , and count the days d from the end of year number
0 to the end of year number y thus:
Julius Caesar's Calendar: d = 365 y + floor(y/4) .
Gregory XIII's Calendar:
d = 365 y + floor(y/4) - floor(y/100) + floor(y/400)
so ... d - 18/25 ó 365.2425 y ó d + 591/400 .
16,000 year Calendar:
d = 365 y + floor(y/4) - floor(y/100) + floor(y/400) - floor(y/4000)
so ... d - 411/250 ó 365.24225 y ó d + 5607/4000 .
Another inheritance from Julius Caesar's calendar is a somewhat ragged
allocation of days to months, memorized in schools thus:
" 30 days hath September, April, June and November; the rest
have 31 except for February's 28, or 29 in leap-years."
To understand this, one should know that, before Julius Caesar, the
Romans used a Vernal calendar that began with Spring on March 1 .
Let us number the months with m = 0 for March, m = 1 for April,
m = 2 for May, ..., m = 10 for January and m = 11 for February
in this Vernal calendar. Then the number d of days in the Vernal
year that precede the first day of Vernal month m turns out to be
d = floor( 30.6 m + 0.5 ) for 0 ó m ó 11 .
Conversely, day number D of the Vernal year, starting with D = 1
on the first of March ( m = 0 ), occurs in Vernal month number
m = floor( (D - 0.5)/30.6 ) for 1 ó D ó 366 .
( How can you confirm these formulas? Must you check 12+366 cases? )
These formulas are very little known; most programmers use instead two
tables, one that tells how many days each month possesses, another
that tells which days of the non leap-year mark the end of each month.
Astronomers mark the days with a serial number called a " Julian Day
Number " that counts days from a notional date, 1 Jan. 4713 B.C., on
which certain astrologically significant cycles coincided. ( " Julian "
here honors not Julius Caesar but another soldier and scholar, Julius
Caesar Scaliger (1484-1558); his son, Joseph Justus Scaliger (1540-
1609), the pre-eminent Protestant scholar of the sixteenth century,
invented Julian day numbers to synchronize the chronology of ancient
Roman, Greek, Persian, Egyptian and Babylonian history in order
that classical scholars could ascertain the priorities for ideas among
those civilizations.) The Julian day number for Sat. 1 Jan. 1600
happens to be 2,305,448 , and all other dates can be counted forward
or back from that one. To count days between two dates, subtract their
Julian day numbers. How can a date's day of the week be determined?
Given the foregoing information, you should now be able to program your
computer or programmable calculator to count days between dates, to
find what date follows another by a specified number of days, and to
determine the day of the week for any date in the Gregorian calendar.
The crucial parts of such a program are procedures that convert a given
Gregorian calendar date's Day-Month-Year into a Julian day number,
and vice-versa. Not every triple of numbers purporting to be a date is
legitimate; for example 29-2-1900 and 13-13-1992 are invalid dates.
Programs that convert invalid data into plausible results are deceitful.
Therefore, check the validity of any alleged Day-Month-Year date by
converting it to a Julian day number and then converting that back to
a Day-Month-Year date to see whether the original date is recovered.
This will circumvent the need for a battery of tests: Is Day < 1 ? Is
Day too big for Month ? Is Month < 1 ? Is Month > 12 ? However,
Julian day numbers do have to be scrutinized to reject or re-process
dates preceding the adoption of the Gregorian calendar in those
jurisdictions for which the program is intended.
Do not be dismayed if your program produces results different from what
you may find in some other computer systems for dates not between 1800
and 2100. Many computer systems use Julius Caesar's calendar shifted
to align with 1900 plus a special test to deny it leap-year status. No
computer has been programmed for correct dates after 28 Feb. 4000 A.D.
because there is no consensus on whether that year will be a leap-year.
The HP-12C financial calculator thinks it will, and recognizes dates
from 15 Oct. 1582 until Sun. 25 Nov. 4046 ; will the world end then?
IBM PCs and clones accept dates from 1 Jan. 1980 , the year IBM's
PC was introduced, until 31 Dec. 2099 ; what will happen after that?
Conversion Formulas: Can you confirm them?
~~~~~~~~~~~~~~~~~~~~
Day D of Vernal year <--> Day d of Vernal month m
( D = 1, 2, 3, ..., 366 ) ( d = 1, 2, 3, ..., 31 and
m = 0, 1, 2, ..., 11 )
m = floor( (D - 0.5)/30.6 )
d = D - floor( 30.6 m + 0.5 ) D = d + floor( 30.6 m + 0.5 )
Calendar year Y month M <--> Vernal year y month m
( M = 1, 2, 3, ..., 12 for ( m = 0, 1, 2, ..., 11 for
Jan., Feb., Mar., ..., Dec.) Mar., Apr., May, ..., Feb.)
If M < 3 then If m < 10 then
m = M+9 M = m+3
y = Y-1 Y = y
else else
m = M-3 M = m-9
y = Y Y = y+1
end if. end if.
Note that Calendar and Vernal years match for March - December,
but February of Calendar year Y lies in Vernal year y = Y-1 ,
so Vernal year Y-1 is a leap-year when Calendar year Y is.
Nov Dec Jan Feb Mar Apr ... Nov Dec Jan Feb Mar Apr
C# = Y-1 <---------- C# = Y ------------> <--- C# = Y+1 ---
--- V# = Y-1 ---> <---------- V# = Y ------------> V# = Y+1
Day D of Vernal year y <--> Pseudo-Julian Day number j
( 1 ó D ó 366 , 0 < y ) ( Differs by a constant from
true Julian Day number.)
For the Gregorian calendar, let
f(y) := 365 y + floor(y/4) - floor(y/100) + floor(y/400) ,
g(j) := floor( (j + 0.48)/365.2425 )
For the 16,000 year calendar, let
f(y) := 365 y + floor(y/4) - floor(y/100) + floor(y/400) - floor(y/4000)
g(j) := floor( (j + 0.402)/365.24225 ) .
j = D + f(y) u = g(j)
if j > f(u) then
y = u
else
y = u-1
end if
D = j - f(y)
The constants given above have been adjusted to compensate for most
rounding errors, but not in divisions by 4 , 100 , 400 and 4000 ,
so roundoff may interfere with dates in years y beyond a few million.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
From: "W. Kahan"
Subject: 16000 year calendar
To: asb@eci2.ucsb.edu
Date: Tue, 8 Jul 1997 20:20:25 -0700 (PDT)
In-Reply-To: a query from from "Aaron Brown" at Jun 12, 97 04:02:59 pm
>
> Hi. I came across your web page
> http://HTTP.CS.Berkeley.EDU/~wkahan/daydate/daydate.doc. I very much
> enjoyed reading it. It was informative, as well as interesting. I
> particularly enjoyed reading about the reactions of the people when the
> calendar skipped 10 or 11 days.
>
> I think I may have found an error. You say, "A better scheme would deny
> leap-year status to millennial years divisible by 4000 too. If this
> better scheme is adopted, the years 2000 and 6000 will be leap-years
> but not 3000, 4000, 5000, 7000, 8000, 9000 ."
>
> I don't follow that statement. It seems that you want to say that the
> years 4000 and 8000 will not be leap years, but that 5000, 6000, and 7000
> would be leap years. Please let me know if I am mistaken or if I am not
> understanding this.
>
> Thanks.
>
> Aaron
> http://eci.ucsb.edu/~asb
> http://www.csua.berkeley.edu/~asb
>
I'm sorry the statement was unclear. Perhaps this will help:
Let the year number be IJKL . This year has
I = 1 , J = K = 9 , L = 7 .
In Julius Caesar's calendar, the leap years were all those and
only those with IJKL divisible by 4 . In effect that meant that
if KL was divisible by 4 the year IJKL was a leap year, and
otherwise not.
The Gregorian calendar differs from Caesar's only in century
years IJ00 ; Pope Gregory decreed that these were to be leap
years just when divisible by 400 ; in other words, IJ00 was
to be a leap year just when IJ was divisible by 4 . That's
what we've been doing for about 400 years or, in some jurisdictions,
somewhat fewer. And millennial years I000 would be leap years just
when I is even, if Gregory's decree were followed for them too.
My proposal differs from Pope Gregory's only in millennial years
I000 ; the proposal would let these be leap years just when I000
is divisible by 400 but NOT divisible by 4000 ; in other words,
I000 is to be a leap year just when I0 is divisible by 4 but I
is not, which is the same as saying I is even but I/2 isn't.
Now let's consider which millennial years are to be leap years under
the two schemes:
Gregory's: 2000, 4000, 6000, 8000, 10000, 12000, 14000, ...
Mine: 2000, 6000, 10000, 14000, ...
The year 4000 is the first that would be different, but neither of
us will be around to see which way it goes.
W. Kahan