[net.religion.jewish] A Jewish Calendar Algorithm

rjh@ihuxj.UUCP (Randolph J. Herber) (03/08/84)

The following algorithm has been checked against several sources
but I can give no absolute warranty that it is correct. I am currently
in the process of checking it against some material I obtained from the
Library of Congress (there seems to be only three detailed descriptions
known to the LC).

The following is a PL/1 Optimizer program fragment giving the algorithm
for computing the Jewish calendars that occur during a specified
Georgian/Julian year:
 
Please note, the following variables are not defined in this fragment:
     YEAR - the specified Georgian/Julian year in full with
            negative values indicating B.C. (or, B.C.E., if you prefer).
            Zero is an invalid YEAR specification.
     YR   - If YEAR>0 then  YR=YEAR; else YR=YEAR+1;
 
         DCL 1 METONIC STATIC,
               2(DAYS  INIT(    0,   354,   708,  1092,
                             1446,  1801,  2185,  2539,
                             2923,  3277,  3632,  4016,
                             4370,  4724,  5108,  5463,
                             5817,  6201,  6555),
                 PARTS INIT(    0,  9516, 19032, 16381,
                            25897,  9493,  6842, 16358,
                            13707, 23223,  6819,  4168,
                            13684, 23200, 20549,  4145,
                            13661, 11010, 20526),
                 TYPE  INIT(    3,     2,     1,     3,
                                2,     1,     4,     1,
                                3,     2,     1,     3,
                                2,     1,     3,     2,
                                1,     4,     1)) (0:18);
         DCL JEWISH_TABLE_1 (4,0:8) FIXED(31) STATIC INIT(
                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)
                ;
         DCL JEWISH_TABLE_2 (0:1,2,0:8) STATIC INIT(
                1,    3,    2,    2,     3,     1,     3,     1,     0,
                1,    1,    2,    4,     4,     6,     6,     1,     0,
                1,    3,    2,    1,     3,     1,     3,     1,     0,
                1,    1,    2,    4,     4,     6,     6,     1,     0)
                ;
         DCL JEWISH_MONTH_NAME(2,13) CHAR(6) VAR INIT(
                'Tishri','Chshvn','Kislev','Tebet',
                'Shebat','','','Nisan',
                'Iyar','Sivan','Tammuz','Ab','Elul',
                'Tishri','Chshvn','Kislev','Tebet',
                'Shebat','','','Nisan',
                'Iyar','Sivan','Tammuz','Ab','Elul');
         DCL JEWISH_MONTH_LENGTH(2,13) INIT(
                30,29,30,29,30,30,29,30,29,30,29,30,29,
                30,29,30,29,30,30,29,30,29,30,29,30,29);
         DCL (JEWISH, JEWISH_LEAP(2)) BIT;
         DCL (JEWISH_YEAR,JEWISH_YEAR_TYPE,JEWISH_YEAR_LENGTH,
              JEWISH_YEAR_START FIXED(31))(2);
         DCL JNAME CHAR(6) VAR;
         JEWISH=JEWISH&(YEAR>=-3761);
         JEWISH_YEAR(1)=YR+3760;
         JEWISH_YEAR(2)=YR+3761;
         IF JEWISH
            THEN DO;
               DO I=1 TO 2;
                  YR=JEWISH_YEAR(I)-1;
                  #CYCLE=TRUNC(YR/19);
                  #YEAR=MOD(YR,19);
                  #TYPE=METONIC.TYPE(#YEAR);
                  JEWISH_LEAP(I)=#TYPE=1;
                  #PART=17875*#CYCLE+
                     METONIC.PARTS(#YEAR)+
                     25044;
                  #DAY=6939*#CYCLE+
                     METONIC.DAYS(#YEAR)+
                     347998+
                     TRUNC(#PART/25920);
                  #PART=MOD(#PART,25920);
                  #ARG=MOD(#DAY,7)*25920+#PART;
 JEW_SCAN:        DO J=0 TO 7;
                     IF (JEWISH_TABLE_1(#TYPE,J)<=#ARG)&
                        (#ARG<JEWISH_TABLE_1(#TYPE,J+1))
                        THEN DO;
                           K=J;
                           LEAVE JEW_SCAN;
                           END;
                     END;
                  JEWISH_YEAR_TYPE(I)=
                     JEWISH_TABLE_2(JEWISH_LEAP(I),1,K);
                  JEWISH_YEAR_START(I)=
                     #DAY+
                     MOD(2+
                         JEWISH_TABLE_2(JEWISH_LEAP(I),2,K)-
                         #DAY,7)
                     -3;
                  SELECT(JEWISH_YEAR_TYPE(I));
                     WHEN(1) JEWISH_MONTH_LENGTH(I,3)=29;
                     WHEN(2) ;
                     WHEN(3) JEWISH_MONTH_LENGTH(I,2)=30;
                     OTHERWISE SIGNAL ERROR;
                     END;
                  IF JEWISH_LEAP(I)
                     THEN DO;
                       JEWISH_MONTH_NAME(I,6)='Adar';
                       JEWISH_MONTH_NAME(I,7)='VeAdar';
                       END;
                     ELSE DO;
                       JEWISH_MONTH_LENGTH(I,6)=0;
                       JEWISH_MONTH_NAME(I,6)='';
                       JEWISH_MONTH_NAME(I,7)='Adar';
                       END;
                  JEWISH_YEAR_LENGTH(I)=SUM(JEWISH_MONTH_LENGTH(I,*));
                  N=JEWISH_YEAR_START(I)-1;
                  /*  TISHRI    */
                  CALL FIXED(-1,N+1,'Rosh Hashana');
                  CALL FIXED(-1,N+3+(MOD(N+3,7)=5),'Fast of Gedalia');
                  CALL FIXED(-1,N+10,'Yom Kippur');
                  CALL FIXED(-1,N+15,'Sukkoth');
                  N=N+JEWISH_MONTH_LENGTH(I,1);
                  /*  CHSHVN    */
                  N=N+JEWISH_MONTH_LENGTH(I,2);
                  /*  KISLEV    */
                  CALL FIXED(-1,N+25,'Hanukkah');
                  N=N+JEWISH_MONTH_LENGTH(I,3);
                  /*  TEBET     */
                  CALL FIXED(-1,N+10+(MOD(N+10,7)=5),
                             'Fast of Tebet');
                  N=N+JEWISH_MONTH_LENGTH(I,4);
                  /*  SHEBAT    */
                  N=N+JEWISH_MONTH_LENGTH(I,5);
                  /*  ADAR 1    */
                  N=N+JEWISH_MONTH_LENGTH(I,6);
                  /*  ADAR 2    */
                  CALL FIXED(-1,N+13-2*(MOD(N+13,7)=5),
                             'Fast of Esther');
                  CALL FIXED(-1,N+14,'Purim');
                  N=N+JEWISH_MONTH_LENGTH(I,7);
                  /*  NISAN     */
                  CALL FIXED(-1,N+14,'Erev Pasach');
                  CALL FIXED(-1,N+15,'Pasach');
                  N=N+JEWISH_MONTH_LENGTH(I,8);
                  /*  IYAR      */
                  CALL FIXED(-1,N+18,'Lag B''Omer');
                  N=N+JEWISH_MONTH_LENGTH(I,9);
                  /*  SIVAN     */
                  CALL FIXED(-1,N+6,'Shavu''oth');
                  N=N+JEWISH_MONTH_LENGTH(I,10);
                  /*  TAMMUZ    */
                  CALL FIXED(-1,N+17+(MOD(N+17,7)=5),
                             'Fast of Tammuz');
                  N=N+JEWISH_MONTH_LENGTH(I,11);
                  /*  AB        */
                  CALL FIXED(-1,N+9+(MOD(N+9,7)=5),'Tish''ah Be''Ab');
                  N=N+JEWISH_MONTH_LENGTH(I,12);
                  /*  ELUL      */
                  END;
               #MONTH=1;
               #YEAR=1;
               #ARG=JEWISH_YEAR_START(1);
               DO WHILE((#ARG+JEWISH_MONTH_LENGTH(#YEAR,#MONTH))<JD);
                  #ARG=#ARG+JEWISH_MONTH_LENGTH(#YEAR,#MONTH);
                  #MONTH=#MONTH+1;
                  IF #MONTH>=14
                     THEN DO;
                        #YEAR=#YEAR+1;
                        IF #YEAR>2 THEN SIGNAL ERROR;
                        #MONTH=1;
                        END;
                  END;
               JNAME=JEWISH_MONTH_NAME(#YEAR,#MONTH);
               #DAY=JD-#ARG+1;
               END;

BTW, my interest in this subject is calendars; I am not Jewish.

	Randolph J. Herber, Amdahl Systems Engineer,
	..!ihnp4!ihuxj!rjh,
	c/o IH 1C220, AT&T Bell Labs, Naperville, IL 60566,
	    (312) 979-6554 or AT&T Cornet 8-367-6554,
	 or Amdahl Corp., Suite 250, 6400 Shafer, Rosemont, IL 60018,
	    (312) 692-7520