[comp.lang.pascal] Day-of-the-week algorithm, part 94

ken@aiai.ed.ac.uk (Ken Johnson) (10/11/89)

I don't speak much Pascal, so this is in `C'. I am posting it here
because you might find it interesting and it would be straightforward to
reconvert it to Pascal.

While someone doing homework would probably come up with an algorithm,
they would be unlikely to think this one up from first principles.  This
is Zeller's congruence, an algorithm which dates from the early Pliocene
period :-)

I have tested this with the Unix C compiler.  Note that the argument
sequence is a British date e.g.  today is 11 10 1989 (11 Oct) not the
other way around.

Happy Hacking!

Cut here -------------------- 8< -------------------- 8< --------------------
/* This algorithm, `Zeller's congruence', is the usual - and fairly
 * efficient - method of finding out on which day of the week a date
 * will fall. Note that the year is not a 20th century year, but the
 * full year number, e.g. `1989'.
 * Example:
 * day(15,5,1989)
 * returns "monday"
 * This algorithm is fully in the public domain.
 */

#include <stdio.h>

/* Pascal programmers won't understand this bit: that does not matter
 * tuppence -- just ignore this bit and start reading at the next
 * paragraph
 */

main(argc,argv)
int argc;
char **argv;
{
	if (argc != 4)
	{
		fprintf(stderr,"Usage: zeller <day> <month> <year>\n");
	}
	else
	{
		char *day( );
		int d, m, y;

		d = atoi(*++argv);
		m = atoi(*++argv);
		y = atoi(*++argv);
		printf("%d-%d-%d was a %s\n",d,m,y,day(d,m,y));
	}
}

/* If you can't read `C' then start reading here */

char *day(d,m,y)
int d, m, y;
{
	char *name_of_day( );
	int day_0( );

	return name_of_day(day_0(d,m,y),day);
}

/* This procedure and its subroutine day_1 return a number 0 to 6
 * according to whether the day in questionm was a Sunday, Monday etc.
 * 0 means Sunday, 1 Monday and so forth
 */

int day_0(d,m,y)
int d, m, y;
{
	if (m < 3)
	{
		return day_1(d,m + 12,y - 1);
	}
	else
	{
		return day_1(d,m,y);
	}
}

int day_1(d,m,y)
int d, m, y;
{
	/* Note: this is integer division, and the % symbol means
	 * modulus here.
	 */

	return (d + (13*m-27)/5 + y + y/4 - y/100 + y/400) % 7;
}

/* Attach an English meaning to the integer that is returned */

char *name_of_day(d)
int d;
{
	switch (d)
	{
	case 0:
		return "sunday";

	case 1:
		return "monday";

	case 2:
		return "tuesday";

	case 3:
		return "wednesday";

	case 4:
		return "thursday";

	case 5:
		return "friday" ;

	case 6:
		return "saturday" ;
	}
}
-- 
Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212
`I have read your article, Mr Johnson, and I am no wiser now than when I
started'.  -- `Possibly not, sir, but far better informed.'