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;
}