Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help! Why negative return on Zeller Congruence?

207 views
Skip to first unread message

flip...@my-deja.com

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
Hello,

I am using the Zeller Congruence and am getting some strange behavoir
and washoping someone here had coded this and could explain my problem.

This is not my code (think of it as pseudocode for now), but will serve
the purpose for this discussion.

int zeller(mo, dy, yyyy)
int yyyy;
int mm;
int dy;

if (mm < 3){
mn += 10;
yyyy -= 1;}
else
mn -= 2;

year = yyyy%100;
cent = yyyy/100;

z = ((26*mm-2)/10 + dy + year +(year/4) + (cent/4) -2*cent)

return(z%7) /*add 1 to this after return to get normal day numbering 1
= sunday */

zeller(2,28,2000) gives 1 (monday, correct)
zeller(2,29,2000) gives 2 (tuesday, correct)
zeller(3,1,2000) gives -4 (what?)
zeller(3,2,2000) gives -3 (what?)
zeller(1,1,1901) gives -5 (what?)

Is there some date normalization or correction that needs to be added
when the results are negative?

Please help. Thanks,

Wilson


Sent via Deja.com http://www.deja.com/
Before you buy.

flip...@my-deja.com

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
Actually,

Only the following is giving a negative result which I have verified.

zeller(1,1,1901) gives -5 (what?)
I posted the others, but haven't verified them yet on the computer yet.

Why the negative result? Please help.


In article <84annl$4du$1...@nnrp1.deja.com>,

Steve Summit

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
In article <84annl$4du$1...@nnrp1.deja.com>, flip...@my-deja.com writes:
> I am using the Zeller Congruence and am getting some strange behavoir
> and was hoping someone here had coded this and could explain my problem.
> This is not my code...

I hope not! (I was wondering about the three different spellings
of your "month" variable...)

> (think of it as pseudocode for now), but will serve
> the purpose for this discussion.

Okay.

>...


> z = ((26*mm-2)/10 + dy + year +(year/4) + (cent/4) -2*cent)

>...


> zeller(2,29,2000) gives 2 (tuesday, correct)
> zeller(3,1,2000) gives -4 (what?)
>

> Is there some date normalization or correction that needs to be added
> when the results are negative?

Part of the problem is that it's pretty easy, I think, for the
final, -2*cent term to pull the whole thing negative, and C89
doesn't say exactly what happens when you take a negative number
modulo a positive number. (C99 seems to provide more guarantees,
but I haven't studied the implications, and anyway few of us have
C99 compilers yet.)

There are a lot of funky implementations of Zeller's Congruence
floating around; among other things they tend to have problems in
(heavy sigh) the year 2000. It looks like you might have started
with one of those, because your (26*mm-2)/10 term does not match
Zeller's formulation.

Here's a code fragment I can stand behind, along with some
commentary. This is taken from the book-length version of the
FAQ list. (The first half is a direct paraphrase of Zeller's
original article.)

...Zeller's congruence... says that if

J is the number of the century [i.e. the year / 100],
K the year within the century [i.e. the year % 100],
m the month,
q the day of the month,
h the day of the week [where 1 is Sunday];

and if January and February are taken as months 13 and 14
of the previous year [affecting both J and K]; then h for
the Gregorian calendar is the remainder when the sum

q + 26(m + 1) / 10 + K + K/4 + J/4 - 2J

is divided by 7, and where all intermediate remainders are
discarded. The translation into C is straightforward:

h = (q + 26 * (m + 1) / 10 + K + K/4 + J/4 + 5*J) % 7;

(where we use +5*J instead of -2*J to make sure that both
operands of the modulus operator % are positive; this bias
totaling 7*J will obviously not change the final value of
h, modulo 7).

One of these days I've really got to get around to posting my
copy of Zeller's original article to the web, or something.

Steve Summit
s...@eskimo.com

flip...@my-deja.com

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
In article <84av4l$em8$1...@eskinews.eskimo.com>,

Steve,

thanks for the input. I coded it up and it did indeed get rid of the
negative numbers.

Unfortunately, it also introduces a new error. Here is the modified
code (excuse my coding as I am just learning C).
/*
** Perform necessary calculations for the Zeller Congruence
*/

if (month == 1){
month = 13;
year -= 1;
}
else if (month == 2){
month = 14;
year -= 1;
}

century = year/100;
yr = year % 100;

wd = (26*(month+1)/10 + day + yr + (yr/4) + (century/4) +5*century)%7;

printf("weekday is: %d\n", wd);


Here is the undesired consequence: Take a date such as May 2, 1403.
(5/2/1403).

The program outputs the day as "2" for Monday and the correct day
is "4" (Wednesday).

Any ideas as to why we get this undesired result?

Thanks for the input.

Wilson
fl...@safebunch.com

raw...@my-deja.com

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
In article <84b8gh$gk9$1...@nnrp1.deja.com>,

flip...@my-deja.com wrote:
> In article <84av4l$em8$1...@eskinews.eskimo.com>,
> s...@eskimo.com (Steve Summit) wrote:
> >
> > ...Zeller's congruence... says that if
> >
> > J is the number of the century [i.e. the year / 100],
> > K the year within the century [i.e. the year % 100],
> > m the month,
> > q the day of the month,
> > h the day of the week [where 1 is Sunday];
> >
> > and if January and February are taken as months 13 and 14
> > of the previous year [affecting both J and K]; then h for
> > the Gregorian calendar is the remainder when the sum
> >
> > q + 26(m + 1) / 10 + K + K/4 + J/4 - 2J
> >
> > is divided by 7, and where all intermediate remainders are
> > discarded.
>
> Here is the undesired consequence: Take a date such as May 2, 1403.
> (5/2/1403).
>
> The program outputs the day as "2" for Monday and the correct day
> is "4" (Wednesday).
>
> Any ideas as to why we get this undesired result?

Perhaps because 1403 is pre-Gregorian calendar? (How do you know that
the correct day is Wednesday? Does the calendar that tells you that
have Oct 4, 1582 right before Oct 15, 1582? Mine does.)

--
MJSR

Dann Corbit

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
/***********************************************************************

Day of Week:

The result is an integer in the range 0-6,
where 0=Monday and 6=Sunday (for the Zeller formula)

Reference:
- Chr. Zeller, Kalender-Formeln, Acta Mathematica, 9 (1887) 131-136

- The Day of the Week for Gregorian Calendars (A. D. Bradley) ?? 82-87

- Keith & Craver; The ultimate perpetual calendar?, JoRM 22:4 (1990)
280-282
day of the week as a 44 character expression in C. (illegal use of --)
The following 45 character C expression by Keith is correct.
dow(y,m,d) { return (d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7; }

- A. W. Butkewitsch, M. S. Selikson - Ewige Kalender, Teubner (Leipzig)
1974
Kleine Naturwissenschaftliche Bibliothek, Bd. 23, p98-113

- Heinz Bachmann, Kalenderarithmetik, 2nd Ed.,
Juris Verlag, Z"urich, 1984, ISBN 3-260-05035-0, p26-42
-----------------------------------------------------------------------
mailto:Torsten...@uni-bielefeld.de 1999-03-15
***********************************************************************/

int
dayofweek (int day, int month, int year)
{
/** Zeller's congruence for the Gregorian calendar. **/
/** With 0=Monday, ... 5=Saturday, 6=Sunday **/
if (month < 3)
{
month += 12;
year--;
}
return ((13 * month + 3) / 5 + day + year + year / 4 - year / 100 + year /
400) % 7;
}


int
dayofweek0 (int d, int m, int y)
{
/** a 45 character C expression by Keith **/
/** With 0=Sunday, 1=Monday, ... 6=Saturday **/
return (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y
/ 400) % 7;
}


int
dayofweek1 (int day, int month, int year)
{
/** Variation of Sillke for the Gregorian calendar. **/
/** With 0=Sunday, 1=Monday, ... 6=Saturday **/
if ((month -= 2) <= 0)
{
month += 12;
year--;
}
return (83 * month / 32 + day + year + year / 4 - year / 100 + year / 400)
% 7;
}


#include <stdio.h>
int
main ()
{
int m;
for (m = 1; m <= 12; m++)
printf ("%3d %3d %3d\n",
dayofweek (0, m, 0),
dayofweek0 (0, m, 0),
dayofweek1 (0, m, 0));
return 0;
}
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. Newsgroup http://www.dejanews.com/~c_a_p
C.A.P. FAQ: ftp://38.168.214.175/pub/Chess%20Analysis%20Project%20FAQ.htm


flip...@my-deja.com

unread,
Dec 28, 1999, 3:00:00 AM12/28/99
to
Use the UNIX cal command.

For example cal 1403 yields:

1403

Jan Feb Mar
S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
1 2 3 4 5 6 1 2 3 1 2 3
7 8 9 10 11 12 13 4 5 6 7 8 9 10 4 5 6 7 8 9 10
14 15 16 17 18 19 20 11 12 13 14 15 16 17 11 12 13 14 15 16 17
21 22 23 24 25 26 27 18 19 20 21 22 23 24 18 19 20 21 22 23 24
28 29 30 31 25 26 27 28 25 26 27 28 29 30 31

Apr May Jun
S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
1 2 3 4 5 6 7 1 2 3 4 5 1 2
8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9
15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16
22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23
29 30 27 28 29 30 31 24 25 26 27 28 29 30

Jul Aug Sep
S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
1 2 3 4 5 6 7 1 2 3 4 1
8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8
15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15
22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22
29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29
30
Oct Nov Dec
S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
1 2 3 4 5 6 1 2 3 1
7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8
14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15
21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22
28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29
30 31

In article <84be6k$kse$1...@nnrp1.deja.com>,

raw...@my-deja.com

unread,
Dec 29, 1999, 3:00:00 AM12/29/99
to
In article <84beps$l9q$1...@nnrp1.deja.com>,

flip...@my-deja.com wrote:
> Use the UNIX cal command.
>
> For example cal 1403 yields:
[snip of cal output]

> In article <84be6k$kse$1...@nnrp1.deja.com>,
> raw...@my-deja.com wrote:
> > In article <84b8gh$gk9$1...@nnrp1.deja.com>,
> > flip...@my-deja.com wrote:
> > > In article <84av4l$em8$1...@eskinews.eskimo.com>,
> > > s...@eskimo.com (Steve Summit) wrote:
> > > > ... for
> > > > the Gregorian calendar ...

> > >
> > > Here is the undesired consequence: Take a date such as May 2,
1403.
> > > (5/2/1403).
> > >
> > > The program outputs the day as "2" for Monday and the correct day
> > > is "4" (Wednesday).
> > >
> > > Any ideas as to why we get this undesired result?
> >
> > Perhaps because 1403 is pre-Gregorian calendar? (How do you know
that
> > the correct day is Wednesday? Does the calendar that tells you that
> > have Oct 4, 1582 right before Oct 15, 1582? Mine does.)

Your calendar result is the same as mine; it is not the result of
applying the Gregorian calendar backward from its date of adoption,
but rather the actual calendar used in 1403. (You can check whether
there's a leap day in 1400 or 1500, for example; there should be,
because the Julian calendar was in effect, not the Gregorian calendar.)

Try cal 1752 or cal 1582 to see where the changeover occurs; in
Oracle, which I used, the change is in October 1582, but I think
Unix cal follows Britain (and the American colonies?) that converted
in 1752; some other countries converted even later. Look at the
man page for cal; FCOL, as Dann Corbit would say.

0 new messages