Article View: comp.lang.c.moderated
Article #2310Re: BEST date <=> daynum converter?
From: Kevin Miller
Date: Sat, 16 Mar 1996 17:39
Date: Sat, 16 Mar 1996 17:39
86 lines
4281 bytes
4281 bytes
heading_anthony@jpmorgan.com (Anthony Heading) writes:
> What's the speediest algorithm for conversion between day-month-year
>dates and "days since 1janXX"? I'd like to find something really fast
>which only need cope with dates between say 1970 and 2100.
>One rather nice thing I found was the method ascribed to Fliegel
>and Van Flandern (CACM 1968); an (untested) implementation attached.
>It avoids using floating point, which is nice. Many other routines
>seem to, but I always worry about doing essentially discrete maths with
>floats. Is that paranoid?
Using floating-point arithmetic for this problem would be idiotic.
The inputs and outputs are inherently integral, and floating-point
arithmetic is not as standardized as integer arithmetic.
>But perhaps the lack of any conditionals below is excessive. There must
>be something faster/simpler.
>Any thoughts?
How about the following? On a DEC-Station 5000 it was able to
convert 72,684 dates in about one second, as timed by my wristwatch.
That is all the dates there are in the 199-year time span to which
it can be applied.
/* --------------------------------------------------------------------- */
/* DEFINITION OF DayOrd */
/* This function returns the ordinal number corresponding to a given */
/* date between January 1, 1901 and December 31, 2099, inclusive. */
/* The ordinal number is defined to 1 for January 1, 1901, and */
/* increases by 1 each day thereafter. If the date is not in the */
/* range given above, the function returns -1 as an error code. */
/* It assumes the calendar in use is the Gregorian, which is the */
/* calendar in general use in America and western Europe in the */
/* twentieth century. The algorithm will not work without */
/* modification outside the range of years given above, due to the */
/* fact that three out of every four century years are not leap */
/* years. */
long int DayOrd (int Year, int Month, int Day) {
const static int S [] = {-31,
0,
31,
31+28,
31+28+31,
31+28+31+30,
31+28+31+30+31,
31+28+31+30+31+30,
31+28+31+30+31+30+31,
31+28+31+30+31+30+31+31,
31+28+31+30+31+30+31+31+30,
31+28+31+30+31+30+31+31+30+31,
31+28+31+30+31+30+31+31+30+31+30,
31+28+31+30+31+30+31+31+30+31+30+31};
int L;
long int A, N;
if (Year < 1901 || Year > 2099) return -1;
A = Year - 1900;
L = Month <= 2 && ! (A%4);
N = 365 * (A - 1) + (A/4) - L + S[Month] + Day;
return N; }
/* --------------------------------------------------------------------- */
This algorithm is very easy to understand and maintain. It is obvious
where all of the numbers come from. On any decent compiler, the work
of adding up the number of days in the first n months will be done at
compile time. I had no trouble modifying this so it would work for
all years from the beginning of the Gregorian calendar (sixteenth
century, I believe) up to any year for which the answer can be held
in a "long int", but that would make it a little slower, so I am
posting this form given here.
The algorithm you posted by Fliegel and Van Flandern looks very
clever, but it also looks like it would be very hard to understand.
- Kevin Jay Miller
`
Technical Details
Message-ID:
<4ieud4$b9f@solutions.solon.com>Path:
arc1-ca.pugleaf.net!solon.com!not-for-mailReferences:
<4hv04d$j80@solutions.solon.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail From: kjm@sbphy.physics.ucsb.edu ( Kevin Miller) Newsgroups: comp.lang.c.moderated Subject: Re: BEST date <=> daynum converter? Date: 16 Mar 1996 11:39:48 -0600 Organization: University of California, Santa Barbara Sender: clc@solutions.solon.com Approved: clc@solutions.solon.com Message-ID: <4ieud4$b9f@solutions.solon.com> References: <4hv04d$j80@solutions.solon.com> NNTP-Posting-Host: solutions.solon.com