[net.religion.jewish] Question about Jewish calendar

rjh@ihlpa.UUCP (Randolph J. Herber) (07/03/85)

Shalom!
I have enclosed with this item a proposed algorithm for converting
a Julian (on or before Oct 4, 1582) or Georgian (on or after Oct 15, 1582)
calendar date to the coresponding Jewish calendar date. I am asking
whether or not the algorithm does an accurate job.

Randolph J. Herber, ...ihnp4!ihlpa!rjh, 312-979-6553 (U.S.A.)
U.S.Mail address Amdahl Corp, C/O Room IH1C220, AT&T Bell Labs, Naperville, IL,
60566-1005

#include <stdio.h>
#include <time.h>
/*
This program writes a date (to stdout) according to the Jewish
Calendar.  If no argument is specified, it calls a "ctime"
function to use today's date.  Otherwise, it may be invoked
with 3 arguments -- month, day, year (4-digit negative for BC(E)).
*/

static char *copyright = {
"(C) 1985 Randolph J. Herber  Usage is unrestricted with retention of notice."
};

#define TRUE     1
#define FALSE    0

static int mlen[] = {
	0,31,28,31,30,31,30,31,31,30,31,30,31
};

static int jmlen[] = {
	0,30,29,30,29,30,30,29,30,29,30,29,30,29
};

static char *mname[] = {
	"",
	"Tishri",
	"Chshvn",
	"Kislev",
	"Tebet",
	"Shebat",
	"Adar",
	"VeAdar",
	"Nisan",
	"Iyar",
	"Sivan",
	"Tammuz",
	"Ab",
	"Elul"
};

static short mdays[] = {
	0,   354,   708,  1092,
	1446,  1801,  2185,  2539,
	2923,  3277,  3632,  4016,
	4370,  4724,  5108,  5463,
	5817,  6201,  6555
};

static short mparts[] = {
	0,  9516, 19032, 16381,
	25897,  9493,  6842, 16358,
	13703, 23223,  6819,  4168,
	13684, 23200, 20549,  4145,
	13661, 11010, 20526
};

static short mtype[] = {
	2,     1,     0,     2,
	1,     0,     3,     0,
	2,     1,     0,     2,
	1,     0,     2,     1,
	0,     3,     0
};

static long table1[4][9] = {
	{0,15611,38880,64800, 83855,116640,145211,168480,181440},
	{0, 3444,38880,55284,107124,116640,133044,168480,181440},
	{0, 3444,36229,55284,107124,116640,123528,168480,181440},
	{0, 3444,36229,55284,107124,116640,133044,168480,181440}
};



static short table2[2][9] = {
	{1,3,2,2,3,1,3,1,0},
	{1,3,2,1,3,1,3,1,0}
};



static short table3[] = {
	1,1,2,4,4,6,6,1,0
};

static char *jkind1[] = {
	"", "defective", "normal", "complete"
};

static char *jkind2[] = {
	"", " leap"
};

main(argc,argv)
int argc;
char **argv;
{

	long secs, time();
	struct tm *tbuf, *localtime();
	void exit();
	int year, yr, mo, da, unit(), jyr, jcycle;
	long jdate, jpart, jday, jarg, jstart;
	short yrm1, n, jyear;
	char style, leap, jtype, jleap;

	if (argc > 1 && argc != 4) {
		(void) printf("Usage:  No arguments for today's date,");
		(void) printf(" or '%s <mo> <da> <yr>'.\n", *argv);
		(void) exit(1);
	}
	else if (argc == 1) {
		secs = time((long *)0);
		tbuf = localtime(&secs);
		mo = tbuf->tm_mon + 1;
		da = tbuf->tm_mday;
		year = tbuf->tm_year + 1900;
	}
	else {
		mo = atoi(argv[1]);
		da = atoi(argv[2]);
		year = atoi(argv[3]);
	}

	if (year != 0 && year >= -3761 && year < 10000) {
		yr = year > 0 ? year : year + 1;
		style = year > 1582;
		leap = style
		    ? (((yr % 4) == 0) && ((yr % 100) != 0)) ||
			((yr % 400) == 0)
		    : ((yr % 4) == 0);
		mlen[2] = leap ? 29 : 28;
		if (mo >=1 && mo <= 12 && da >= 1 && da <= mlen[mo] &&
		    !(year == 1582 && (mo == 1 || mo == 2 ||
		    (mo == 10 && da >= 5 && da <= 14)))) {
			if (year == 1582 && mo == 10) {
				mlen[10] = 21;
				if (da >= 15) da -= 10;
			} else {
				mlen[10] = 31;
			}
			yrm1 = yr - 1;
			jdate = 1721423l+yrm1*365+unit(yrm1,4)+da;
			for (n=1;n<mo;++n) {
				jdate += mlen[n];
			}
			if (style) {
				jdate -= 10 + (yrm1-1500)/100 - (yrm1-1200)/400;
			}
			if (jdate < 347998) {
				(void) printf("%s: Date of range!\n",*argv);
				(void) exit(2);
			}
			jyr = yr + 3761;
			do {
				jyr -= 1;
				jcycle = unit(jyr,19);
				jyear = rmdr(jyr,19);
				jtype = mtype[jyear];
				jleap = jtype == 0;
				jpart = 17875l*jcycle+mparts[jyear]+25044l;
				jday = lunit(jpart,25920l);
				jpart -= jday * 25920l;
				jday += 6939l*jcycle+mdays[jyear]+347998l;
				jarg = lrmdr(jday,7l)*25920l+jpart;
				for(n=0;n<=7;++n) {
					if (table1[jtype][n]<=jarg &&
					    jarg<table1[jtype][n+1]) break;
				}
				jtype = table2[jleap][n];
				jstart = jday+lrmdr(2l+table3[n]-jday,7l)-3l;
			} while (jdate < jstart);
			jyr += 1;
			jday = (jdate - jstart) + 1;
			switch (jtype) {
				case 1: jmlen[3] = 29; break;
				case 2: break;
				case 3: jmlen[2] = 30; break;
				default:
					printf("%s: Internal error 1\n",*argv);
					exit(3);
					break;
			}
			if (!jleap) {
				mname[7] = mname[6];
				mname[6] = mname[0];
				jmlen[6] = 0;
			}
			for(n=1;n<=13;++n) {
				if(jday<=jmlen[n]) break;
				jday -= jmlen[n];
			}
			(void) printf("%s %d, %d %s%s\n",
				mname[n],jday,jyr,
				jkind1[jtype],jkind2[jleap]);
			(void) exit(0);
		} else {
			(void) printf("%s: Invalid date!\n",*argv);
			(void) exit(2);
		}
	}
	(void) printf("%s: Date out of range!\n",*argv);
	(void) exit(2);
}

int unit(f1,f2)
	int f1, f2;
{
	int rmdr;
	rmdr = f1 % f2;
	if (rmdr < 0) rmdr += f2;
	return (f1 - rmdr) / f2;
}


long lunit(f1,f2)
	long f1, f2;
{
	long rmdr;
	rmdr = f1 % f2;
	if (rmdr < 0) rmdr += f2;
	return (f1 - rmdr) / f2;
}


int rmdr(f1,f2)
	int f1, f2;
{
	int rmdrx;
	rmdrx = f1 % f2;
	if (rmdrx < 0) rmdrx += f2;
	return rmdrx;
}


long lrmdr(f1,f2)
	long f1, f2;
{
	long rmdrx;
	rmdrx = f1 % f2;
	if (rmdrx < 0) rmdrx += f2;
	return rmdrx;
}