File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / calendar / jewish.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:31:38 2013 UTC (11 years ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, v5_4_17, HEAD
5.4.17

    1: /* $selId: jewish.c,v 2.0 1995/10/24 01:13:06 lees Exp $
    2:  * Copyright 1993-1995, Scott E. Lee, all rights reserved.
    3:  * Permission granted to use, copy, modify, distribute and sell so long as
    4:  * the above copyright and this permission statement are retained in all
    5:  * copies.  THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
    6:  */
    7: 
    8: /**************************************************************************
    9:  *
   10:  * These are the externally visible components of this file:
   11:  *
   12:  *     void
   13:  *     SdnToJewish(
   14:  *         long int sdn,
   15:  *         int *pYear,
   16:  *         int *pMonth,
   17:  *         int *pDay);
   18:  *
   19:  * Convert a SDN to a Jewish calendar date.  If the input SDN is before the
   20:  * first day of year 1, the three output values will all be set to zero,
   21:  * otherwise *pYear will be > 0; *pMonth will be in the range 1 to 13
   22:  * inclusive; *pDay will be in the range 1 to 30 inclusive.  Note that Adar
   23:  * II is assigned the month number 7 and Elul is always 13.
   24:  *
   25:  *     long int
   26:  *     JewishToSdn(
   27:  *         int year,
   28:  *         int month,
   29:  *         int day);
   30:  *
   31:  * Convert a Jewish calendar date to a SDN.  Zero is returned when the
   32:  * input date is detected as invalid or out of the supported range.  The
   33:  * return value will be > 0 for all valid, supported dates, but there are
   34:  * some invalid dates that will return a positive value.  To verify that a
   35:  * date is valid, convert it to SDN and then back and compare with the
   36:  * original.
   37:  *
   38:  *     char *JewishMonthName[14];
   39:  *
   40:  * Convert a Jewish month number (1 to 13) to the name of the Jewish month
   41:  * (null terminated).  An index of zero will return a zero length string.
   42:  *
   43:  * VALID RANGE
   44:  *
   45:  *     Although this software can handle dates all the way back to the year
   46:  *     1 (3761 B.C.), such use may not be meaningful.
   47:  *
   48:  *     The Jewish calendar has been in use for several thousand years, but
   49:  *     in the early days there was no formula to determine the start of a
   50:  *     month.  A new month was started when the new moon was first
   51:  *     observed.
   52:  *
   53:  *     It is not clear when the current rule based calendar replaced the
   54:  *     observation based calendar.  According to the book "Jewish Calendar
   55:  *     Mystery Dispelled" by George Zinberg, the patriarch Hillel II
   56:  *     published these rules in 358 A.D.  But, according to The
   57:  *     Encyclopedia Judaica, Hillel II may have only published the 19 year
   58:  *     rule for determining the occurrence of leap years.
   59:  *
   60:  *     I have yet to find a specific date when the current set of rules
   61:  *     were known to be in use.
   62:  *
   63:  * CALENDAR OVERVIEW
   64:  *
   65:  *     The Jewish calendar is based on lunar as well as solar cycles.  A
   66:  *     month always starts on or near a new moon and has either 29 or 30
   67:  *     days (a lunar cycle is about 29 1/2 days).  Twelve of these
   68:  *     alternating 29-30 day months gives a year of 354 days, which is
   69:  *     about 11 1/4 days short of a solar year.
   70:  *
   71:  *     Since a month is defined to be a lunar cycle (new moon to new moon),
   72:  *     this 11 1/4 day difference cannot be overcome by adding days to a
   73:  *     month as with the Gregorian calendar, so an entire month is
   74:  *     periodically added to the year, making some years 13 months long.
   75:  *
   76:  *     For astronomical as well as ceremonial reasons, the start of a new
   77:  *     year may be delayed until a day or two after the new moon causing
   78:  *     years to vary in length.  Leap years can be from 383 to 385 days and
   79:  *     common years can be from 353 to 355 days.  These are the months of
   80:  *     the year and their possible lengths:
   81:  *
   82:  *                       COMMON YEAR          LEAP YEAR
   83:  *          1 Tishri    30   30   30         30   30   30
   84:  *          2 Heshvan   29   29   30         29   29   30 (variable)
   85:  *          3 Kislev    29   30   30         29   30   30 (variable)
   86:  *          4 Tevet     29   29   29         29   29   29
   87:  *          5 Shevat    30   30   30         30   30   30
   88:  *          6 Adar I    29   29   29         30   30   30 (variable)
   89:  *          7 Adar II   --   --   --         29   29   29 (optional)
   90:  *          8 Nisan     30   30   30         30   30   30
   91:  *          9 Iyyar     29   29   29         29   29   29
   92:  *         10 Sivan     30   30   30         30   30   30
   93:  *         11 Tammuz    29   29   29         29   29   29
   94:  *         12 Av        30   30   30         30   30   30
   95:  *         13 Elul      29   29   29         29   29   29
   96:  *                     ---  ---  ---        ---  ---  ---
   97:  *                     353  354  355        383  384  385
   98:  *
   99:  *     Note that the month names and other words that appear in this file
  100:  *     have multiple possible spellings in the Roman character set.  I have
  101:  *     chosen to use the spellings found in the Encyclopedia Judaica.
  102:  *
  103:  *     Adar II, the month added for leap years, is sometimes referred to as
  104:  *     the 13th month, but I have chosen to assign it the number 7 to keep
  105:  *     the months in chronological order.  This may not be consistent with
  106:  *     other numbering schemes.
  107:  *
  108:  *     Leap years occur in a fixed pattern of 19 years called the metonic
  109:  *     cycle.  The 3rd, 6th, 8th, 11th, 14th, 17th and 19th years of this
  110:  *     cycle are leap years.  The first metonic cycle starts with Jewish
  111:  *     year 1, or 3761/60 B.C.  This is believed to be the year of
  112:  *     creation.
  113:  *
  114:  *     To construct the calendar for a year, you must first find the length
  115:  *     of the year by determining the first day of the year (Tishri 1, or
  116:  *     Rosh Ha-Shanah) and the first day of the following year.  This
  117:  *     selects one of the six possible month length configurations listed
  118:  *     above.
  119:  *
  120:  *     Finding the first day of the year is the most difficult part.
  121:  *     Finding the date and time of the new moon (or molad) is the first
  122:  *     step.  For this purpose, the lunar cycle is assumed to be 29 days 12
  123:  *     hours and 793 halakim.  A halakim is 1/1080th of an hour or 3 1/3
  124:  *     seconds.  (This assumed value is only about 1/2 second less than the
  125:  *     value used by modern astronomers -- not bad for a number that was
  126:  *     determined so long ago.)  The first molad of year 1 occurred on
  127:  *     Sunday at 11:20:11 P.M.  This would actually be Monday, because the
  128:  *     Jewish day is considered to begin at sunset.
  129:  *
  130:  *     Since sunset varies, the day is assumed to begin at 6:00 P.M.  for
  131:  *     calendar calculation purposes.  So, the first molad was 5 hours 793
  132:  *     halakim after the start of Tishri 1, 0001 (which was Monday
  133:  *     September 7, 4761 B.C. by the Gregorian calendar).  All subsequent
  134:  *     molads can be calculated from this starting point by adding the
  135:  *     length of a lunar cycle.
  136:  *
  137:  *     Once the molad that starts a year is determined the actual start of
  138:  *     the year (Tishri 1) can be determined.  Tishri 1 will be the day of
  139:  *     the molad unless it is delayed by one of the following four rules
  140:  *     (called dehiyyot).  Each rule can delay the start of the year by one
  141:  *     day, and since rule #1 can combine with one of the other rules, it
  142:  *     can be delayed as much as two days.
  143:  *
  144:  *         1.  Tishri 1 must never be Sunday, Wednesday or Friday.  (This
  145:  *             is largely to prevent certain holidays from occurring on the
  146:  *             day before or after the Sabbath.)
  147:  *
  148:  *         2.  If the molad occurs on or after noon, Tishri 1 must be
  149:  *             delayed.
  150:  *
  151:  *         3.  If it is a common (not leap) year and the molad occurs on
  152:  *             Tuesday at or after 3:11:20 A.M., Tishri 1 must be delayed.
  153:  *
  154:  *         4.  If it is the year following a leap year and the molad occurs
  155:  *             on Monday at or after 9:32:43 and 1/3 sec, Tishri 1 must be
  156:  *             delayed.
  157:  *
  158:  * GLOSSARY
  159:  *
  160:  *     dehiyyot         The set of 4 rules that determine when the new year
  161:  *                      starts relative to the molad.
  162:  *
  163:  *     halakim          1/1080th of an hour or 3 1/3 seconds.
  164:  *
  165:  *     lunar cycle      The period of time between mean conjunctions of the
  166:  *                      sun and moon (new moon to new moon).  This is
  167:  *                      assumed to be 29 days 12 hours and 793 halakim for
  168:  *                      calendar purposes.
  169:  *
  170:  *     metonic cycle    A 19 year cycle which determines which years are
  171:  *                      leap years and which are common years.  The 3rd,
  172:  *                      6th, 8th, 11th, 14th, 17th and 19th years of this
  173:  *                      cycle are leap years.
  174:  *
  175:  *     molad            The date and time of the mean conjunction of the
  176:  *                      sun and moon (new moon).  This is the approximate
  177:  *                      beginning of a month.
  178:  *
  179:  *     Rosh Ha-Shanah   The first day of the Jewish year (Tishri 1).
  180:  *
  181:  *     Tishri           The first month of the Jewish year.
  182:  *
  183:  * ALGORITHMS
  184:  *
  185:  *     SERIAL DAY NUMBER TO JEWISH DATE
  186:  *
  187:  *     The simplest approach would be to use the rules stated above to find
  188:  *     the molad of Tishri before and after the given day number.  Then use
  189:  *     the molads to find Tishri 1 of the current and following years.
  190:  *     From this the length of the year can be determined and thus the
  191:  *     length of each month.  But this method is used as a last resort.
  192:  *
  193:  *     The first 59 days of the year are the same regardless of the length
  194:  *     of the year.  As a result, only the day number of the start of the
  195:  *     year is required.
  196:  *
  197:  *     Similarly, the last 6 months do not change from year to year.  And
  198:  *     since it can be determined whether the year is a leap year by simple
  199:  *     division, the lengths of Adar I and II can be easily calculated.  In
  200:  *     fact, all dates after the 3rd month are consistent from year to year
  201:  *     (once it is known whether it is a leap year).
  202:  *
  203:  *     This means that if the given day number falls in the 3rd month or on
  204:  *     the 30th day of the 2nd month the length of the year must be found,
  205:  *     but in no other case.
  206:  *
  207:  *     So, the approach used is to take the given day number and round it
  208:  *     to the closest molad of Tishri (first new moon of the year).  The
  209:  *     rounding is not really to the *closest* molad, but is such that if
  210:  *     the day number is before the middle of the 3rd month the molad at
  211:  *     the start of the year is found, otherwise the molad at the end of
  212:  *     the year is found.
  213:  *
  214:  *     Only if the day number is actually found to be in the ambiguous
  215:  *     period of 29 to 31 days is the other molad calculated.
  216:  *
  217:  *     JEWISH DATE TO SERIAL DAY NUMBER
  218:  *
  219:  *     The year number is used to find which 19 year metonic cycle contains
  220:  *     the date and which year within the cycle (this is a division and
  221:  *     modulus).  This also determines whether it is a leap year.
  222:  *
  223:  *     If the month is 1 or 2, the calculation is simple addition to the
  224:  *     first of the year.
  225:  *
  226:  *     If the month is 8 (Nisan) or greater, the calculation is simple
  227:  *     subtraction from beginning of the following year.
  228:  *
  229:  *     If the month is 4 to 7, it is considered whether it is a leap year
  230:  *     and then simple subtraction from the beginning of the following year
  231:  *     is used.
  232:  *
  233:  *     Only if it is the 3rd month is both the start and end of the year
  234:  *     required.
  235:  *
  236:  * TESTING
  237:  *
  238:  *     This algorithm has been tested in two ways.  First, 510 dates from a
  239:  *     table in "Jewish Calendar Mystery Dispelled" were calculated and
  240:  *     compared to the table.  Second, the calculation algorithm described
  241:  *     in "Jewish Calendar Mystery Dispelled" was coded and used to verify
  242:  *     all dates from the year 1 (3761 B.C.) to the year 13760 (10000
  243:  *     A.D.).
  244:  *
  245:  *     The source code of the verification program is included in this
  246:  *     package.
  247:  *
  248:  * REFERENCES
  249:  *
  250:  *     The Encyclopedia Judaica, the entry for "Calendar"
  251:  *
  252:  *     The Jewish Encyclopedia
  253:  *
  254:  *     Jewish Calendar Mystery Dispelled by George Zinberg, Vantage Press,
  255:  *     1963
  256:  *
  257:  *     The Comprehensive Hebrew Calendar by Arthur Spier, Behrman House
  258:  *
  259:  *     The Book of Calendars [note that this work contains many typos]
  260:  *
  261:  **************************************************************************/
  262: 
  263: #if defined(PHP_WIN32) && _MSC_VER >= 1200
  264: #pragma setlocale("english")
  265: #endif
  266: 
  267: #include "sdncal.h"
  268: 
  269: #define HALAKIM_PER_HOUR 1080
  270: #define HALAKIM_PER_DAY 25920
  271: #define HALAKIM_PER_LUNAR_CYCLE ((29 * HALAKIM_PER_DAY) + 13753)
  272: #define HALAKIM_PER_METONIC_CYCLE (HALAKIM_PER_LUNAR_CYCLE * (12 * 19 + 7))
  273: 
  274: #define JEWISH_SDN_OFFSET 347997
  275: #define JEWISH_SDN_MAX 324542846L /* 12/13/887605, greater value raises interger overflow */
  276: #define NEW_MOON_OF_CREATION 31524
  277: 
  278: #define SUNDAY    0
  279: #define MONDAY    1
  280: #define TUESDAY   2
  281: #define WEDNESDAY 3
  282: #define THURSDAY  4
  283: #define FRIDAY    5
  284: #define SATURDAY  6
  285: 
  286: #define NOON (18 * HALAKIM_PER_HOUR)
  287: #define AM3_11_20 ((9 * HALAKIM_PER_HOUR) + 204)
  288: #define AM9_32_43 ((15 * HALAKIM_PER_HOUR) + 589)
  289: 
  290: static int monthsPerYear[19] =
  291: {
  292: 12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 13
  293: };
  294: 
  295: static int yearOffset[19] =
  296: {
  297: 	0, 12, 24, 37, 49, 61, 74, 86, 99, 111, 123,
  298: 	136, 148, 160, 173, 185, 197, 210, 222
  299: };
  300: 
  301: char *JewishMonthName[14] =
  302: {
  303: 	"",
  304: 	"Tishri",
  305: 	"Heshvan",
  306: 	"Kislev",
  307: 	"Tevet",
  308: 	"Shevat",
  309: 	"AdarI",
  310: 	"AdarII",
  311: 	"Nisan",
  312: 	"Iyyar",
  313: 	"Sivan",
  314: 	"Tammuz",
  315: 	"Av",
  316: 	"Elul"
  317: };
  318: 
  319: char *JewishMonthHebName[14] =
  320: {
  321: 	"",
  322: 	"תשרי",
  323: 	"חשון",
  324: 	"כסלו",
  325: 	"טבת",
  326: 	"שבט",
  327: 	"אדר",
  328: 	"'אדר ב",
  329: 	"ניסן",
  330: 	"אייר",
  331: 	"סיון",
  332: 	"תמוז",
  333: 	"אב",
  334: 	"אלול"
  335: };
  336: 
  337: /************************************************************************
  338:  * Given the year within the 19 year metonic cycle and the time of a molad
  339:  * (new moon) which starts that year, this routine will calculate what day
  340:  * will be the actual start of the year (Tishri 1 or Rosh Ha-Shanah).  This
  341:  * first day of the year will be the day of the molad unless one of 4 rules
  342:  * (called dehiyyot) delays it.  These 4 rules can delay the start of the
  343:  * year by as much as 2 days.
  344:  */
  345: static long int Tishri1(
  346: 						   int metonicYear,
  347: 						   long int moladDay,
  348: 						   long int moladHalakim)
  349: {
  350: 	long int tishri1;
  351: 	int dow;
  352: 	int leapYear;
  353: 	int lastWasLeapYear;
  354: 
  355: 	tishri1 = moladDay;
  356: 	dow = tishri1 % 7;
  357: 	leapYear = metonicYear == 2 || metonicYear == 5 || metonicYear == 7
  358: 		|| metonicYear == 10 || metonicYear == 13 || metonicYear == 16
  359: 		|| metonicYear == 18;
  360: 	lastWasLeapYear = metonicYear == 3 || metonicYear == 6
  361: 		|| metonicYear == 8 || metonicYear == 11 || metonicYear == 14
  362: 		|| metonicYear == 17 || metonicYear == 0;
  363: 
  364: 	/* Apply rules 2, 3 and 4. */
  365: 	if ((moladHalakim >= NOON) ||
  366: 		((!leapYear) && dow == TUESDAY && moladHalakim >= AM3_11_20) ||
  367: 		(lastWasLeapYear && dow == MONDAY && moladHalakim >= AM9_32_43)) {
  368: 		tishri1++;
  369: 		dow++;
  370: 		if (dow == 7) {
  371: 			dow = 0;
  372: 		}
  373: 	}
  374: 	/* Apply rule 1 after the others because it can cause an additional
  375: 	 * delay of one day. */
  376: 	if (dow == WEDNESDAY || dow == FRIDAY || dow == SUNDAY) {
  377: 		tishri1++;
  378: 	}
  379: 	return (tishri1);
  380: }
  381: 
  382: /************************************************************************
  383:  * Given a metonic cycle number, calculate the date and time of the molad
  384:  * (new moon) that starts that cycle.  Since the length of a metonic cycle
  385:  * is a constant, this is a simple calculation, except that it requires an
  386:  * intermediate value which is bigger that 32 bits.  Because this
  387:  * intermediate value only needs 36 to 37 bits and the other numbers are
  388:  * constants, the process has been reduced to just a few steps.
  389:  */
  390: static void MoladOfMetonicCycle(
  391: 								   int metonicCycle,
  392: 								   long int *pMoladDay,
  393: 								   long int *pMoladHalakim)
  394: {
  395: 	register unsigned long int r1, r2, d1, d2;
  396: 
  397: 	/* Start with the time of the first molad after creation. */
  398: 	r1 = NEW_MOON_OF_CREATION;
  399: 
  400: 	/* Calculate metonicCycle * HALAKIM_PER_METONIC_CYCLE.  The upper 32
  401: 	 * bits of the result will be in r2 and the lower 16 bits will be
  402: 	 * in r1. */
  403: 	r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF);
  404: 	r2 = r1 >> 16;
  405: 	r2 += metonicCycle * ((HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF);
  406: 
  407: 	/* Calculate r2r1 / HALAKIM_PER_DAY.  The remainder will be in r1, the
  408: 	 * upper 16 bits of the quotient will be in d2 and the lower 16 bits
  409: 	 * will be in d1. */
  410: 	d2 = r2 / HALAKIM_PER_DAY;
  411: 	r2 -= d2 * HALAKIM_PER_DAY;
  412: 	r1 = (r2 << 16) | (r1 & 0xFFFF);
  413: 	d1 = r1 / HALAKIM_PER_DAY;
  414: 	r1 -= d1 * HALAKIM_PER_DAY;
  415: 
  416: 	*pMoladDay = (d2 << 16) | d1;
  417: 	*pMoladHalakim = r1;
  418: }
  419: 
  420: /************************************************************************
  421:  * Given a day number, find the molad of Tishri (the new moon at the start
  422:  * of a year) which is closest to that day number.  It's not really the
  423:  * *closest* molad that we want here.  If the input day is in the first two
  424:  * months, we want the molad at the start of the year.  If the input day is
  425:  * in the fourth to last months, we want the molad at the end of the year.
  426:  * If the input day is in the third month, it doesn't matter which molad is
  427:  * returned, because both will be required.  This type of "rounding" allows
  428:  * us to avoid calculating the length of the year in most cases.
  429:  */
  430: static void FindTishriMolad(
  431: 							   long int inputDay,
  432: 							   int *pMetonicCycle,
  433: 							   int *pMetonicYear,
  434: 							   long int *pMoladDay,
  435: 							   long int *pMoladHalakim)
  436: {
  437: 	long int moladDay;
  438: 	long int moladHalakim;
  439: 	int metonicCycle;
  440: 	int metonicYear;
  441: 
  442: 	/* Estimate the metonic cycle number.  Note that this may be an under
  443: 	 * estimate because there are 6939.6896 days in a metonic cycle not
  444: 	 * 6940, but it will never be an over estimate.  The loop below will
  445: 	 * correct for any error in this estimate. */
  446: 	metonicCycle = (inputDay + 310) / 6940;
  447: 
  448: 	/* Calculate the time of the starting molad for this metonic cycle. */
  449: 	MoladOfMetonicCycle(metonicCycle, &moladDay, &moladHalakim);
  450: 
  451: 	/* If the above was an under estimate, increment the cycle number until
  452: 	 * the correct one is found.  For modern dates this loop is about 98.6%
  453: 	 * likely to not execute, even once, because the above estimate is
  454: 	 * really quite close. */
  455: 	while (moladDay < inputDay - 6940 + 310) {
  456: 		metonicCycle++;
  457: 		moladHalakim += HALAKIM_PER_METONIC_CYCLE;
  458: 		moladDay += moladHalakim / HALAKIM_PER_DAY;
  459: 		moladHalakim = moladHalakim % HALAKIM_PER_DAY;
  460: 	}
  461: 
  462: 	/* Find the molad of Tishri closest to this date. */
  463: 	for (metonicYear = 0; metonicYear < 18; metonicYear++) {
  464: 		if (moladDay > inputDay - 74) {
  465: 			break;
  466: 		}
  467: 		moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
  468: 		moladDay += moladHalakim / HALAKIM_PER_DAY;
  469: 		moladHalakim = moladHalakim % HALAKIM_PER_DAY;
  470: 	}
  471: 
  472: 	*pMetonicCycle = metonicCycle;
  473: 	*pMetonicYear = metonicYear;
  474: 	*pMoladDay = moladDay;
  475: 	*pMoladHalakim = moladHalakim;
  476: }
  477: 
  478: /************************************************************************
  479:  * Given a year, find the number of the first day of that year and the date
  480:  * and time of the starting molad.
  481:  */
  482: static void FindStartOfYear(
  483: 							   int year,
  484: 							   int *pMetonicCycle,
  485: 							   int *pMetonicYear,
  486: 							   long int *pMoladDay,
  487: 							   long int *pMoladHalakim,
  488: 							   int *pTishri1)
  489: {
  490: 	*pMetonicCycle = (year - 1) / 19;
  491: 	*pMetonicYear = (year - 1) % 19;
  492: 	MoladOfMetonicCycle(*pMetonicCycle, pMoladDay, pMoladHalakim);
  493: 
  494: 	*pMoladHalakim += HALAKIM_PER_LUNAR_CYCLE * yearOffset[*pMetonicYear];
  495: 	*pMoladDay += *pMoladHalakim / HALAKIM_PER_DAY;
  496: 	*pMoladHalakim = *pMoladHalakim % HALAKIM_PER_DAY;
  497: 
  498: 	*pTishri1 = Tishri1(*pMetonicYear, *pMoladDay, *pMoladHalakim);
  499: }
  500: 
  501: /************************************************************************
  502:  * Given a serial day number (SDN), find the corresponding year, month and
  503:  * day in the Jewish calendar.  The three output values will always be
  504:  * modified.  If the input SDN is before the first day of year 1, they will
  505:  * all be set to zero, otherwise *pYear will be > 0; *pMonth will be in the
  506:  * range 1 to 13 inclusive; *pDay will be in the range 1 to 30 inclusive.
  507:  */
  508: void SdnToJewish(
  509: 					long int sdn,
  510: 					int *pYear,
  511: 					int *pMonth,
  512: 					int *pDay)
  513: {
  514: 	long int inputDay;
  515: 	long int day;
  516: 	long int halakim;
  517: 	int metonicCycle;
  518: 	int metonicYear;
  519: 	int tishri1;
  520: 	int tishri1After;
  521: 	int yearLength;
  522: 
  523: 	if (sdn <= JEWISH_SDN_OFFSET || sdn > JEWISH_SDN_MAX) {
  524: 		*pYear = 0;
  525: 		*pMonth = 0;
  526: 		*pDay = 0;
  527: 		return;
  528: 	}
  529: 	inputDay = sdn - JEWISH_SDN_OFFSET;
  530: 
  531: 	FindTishriMolad(inputDay, &metonicCycle, &metonicYear, &day, &halakim);
  532: 	tishri1 = Tishri1(metonicYear, day, halakim);
  533: 
  534: 	if (inputDay >= tishri1) {
  535: 		/* It found Tishri 1 at the start of the year. */
  536: 		*pYear = metonicCycle * 19 + metonicYear + 1;
  537: 		if (inputDay < tishri1 + 59) {
  538: 			if (inputDay < tishri1 + 30) {
  539: 				*pMonth = 1;
  540: 				*pDay = inputDay - tishri1 + 1;
  541: 			} else {
  542: 				*pMonth = 2;
  543: 				*pDay = inputDay - tishri1 - 29;
  544: 			}
  545: 			return;
  546: 		}
  547: 		/* We need the length of the year to figure this out, so find
  548: 		 * Tishri 1 of the next year. */
  549: 		halakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
  550: 		day += halakim / HALAKIM_PER_DAY;
  551: 		halakim = halakim % HALAKIM_PER_DAY;
  552: 		tishri1After = Tishri1((metonicYear + 1) % 19, day, halakim);
  553: 	} else {
  554: 		/* It found Tishri 1 at the end of the year. */
  555: 		*pYear = metonicCycle * 19 + metonicYear;
  556: 		if (inputDay >= tishri1 - 177) {
  557: 			/* It is one of the last 6 months of the year. */
  558: 			if (inputDay > tishri1 - 30) {
  559: 				*pMonth = 13;
  560: 				*pDay = inputDay - tishri1 + 30;
  561: 			} else if (inputDay > tishri1 - 60) {
  562: 				*pMonth = 12;
  563: 				*pDay = inputDay - tishri1 + 60;
  564: 			} else if (inputDay > tishri1 - 89) {
  565: 				*pMonth = 11;
  566: 				*pDay = inputDay - tishri1 + 89;
  567: 			} else if (inputDay > tishri1 - 119) {
  568: 				*pMonth = 10;
  569: 				*pDay = inputDay - tishri1 + 119;
  570: 			} else if (inputDay > tishri1 - 148) {
  571: 				*pMonth = 9;
  572: 				*pDay = inputDay - tishri1 + 148;
  573: 			} else {
  574: 				*pMonth = 8;
  575: 				*pDay = inputDay - tishri1 + 178;
  576: 			}
  577: 			return;
  578: 		} else {
  579: 			if (monthsPerYear[(*pYear - 1) % 19] == 13) {
  580: 				*pMonth = 7;
  581: 				*pDay = inputDay - tishri1 + 207;
  582: 				if (*pDay > 0)
  583: 					return;
  584: 				(*pMonth)--;
  585: 				(*pDay) += 30;
  586: 				if (*pDay > 0)
  587: 					return;
  588: 				(*pMonth)--;
  589: 				(*pDay) += 30;
  590: 			} else {
  591: 				*pMonth = 6;
  592: 				*pDay = inputDay - tishri1 + 207;
  593: 				if (*pDay > 0)
  594: 					return;
  595: 				(*pMonth)--;
  596: 				(*pDay) += 30;
  597: 			}
  598: 			if (*pDay > 0)
  599: 				return;
  600: 			(*pMonth)--;
  601: 			(*pDay) += 29;
  602: 			if (*pDay > 0)
  603: 				return;
  604: 
  605: 			/* We need the length of the year to figure this out, so find
  606: 			 * Tishri 1 of this year. */
  607: 			tishri1After = tishri1;
  608: 			FindTishriMolad(day - 365,
  609: 							&metonicCycle, &metonicYear, &day, &halakim);
  610: 			tishri1 = Tishri1(metonicYear, day, halakim);
  611: 		}
  612: 	}
  613: 
  614: 	yearLength = tishri1After - tishri1;
  615: 	day = inputDay - tishri1 - 29;
  616: 	if (yearLength == 355 || yearLength == 385) {
  617: 		/* Heshvan has 30 days */
  618: 		if (day <= 30) {
  619: 			*pMonth = 2;
  620: 			*pDay = day;
  621: 			return;
  622: 		}
  623: 		day -= 30;
  624: 	} else {
  625: 		/* Heshvan has 29 days */
  626: 		if (day <= 29) {
  627: 			*pMonth = 2;
  628: 			*pDay = day;
  629: 			return;
  630: 		}
  631: 		day -= 29;
  632: 	}
  633: 
  634: 	/* It has to be Kislev. */
  635: 	*pMonth = 3;
  636: 	*pDay = day;
  637: }
  638: 
  639: /************************************************************************
  640:  * Given a year, month and day in the Jewish calendar, find the
  641:  * corresponding serial day number (SDN).  Zero is returned when the input
  642:  * date is detected as invalid.  The return value will be > 0 for all valid
  643:  * dates, but there are some invalid dates that will return a positive
  644:  * value.  To verify that a date is valid, convert it to SDN and then back
  645:  * and compare with the original.
  646:  */
  647: long int JewishToSdn(
  648: 						int year,
  649: 						int month,
  650: 						int day)
  651: {
  652: 	long int sdn;
  653: 	int metonicCycle;
  654: 	int metonicYear;
  655: 	int tishri1;
  656: 	int tishri1After;
  657: 	long int moladDay;
  658: 	long int moladHalakim;
  659: 	int yearLength;
  660: 	int lengthOfAdarIAndII;
  661: 
  662: 	if (year <= 0 || day <= 0 || day > 30) {
  663: 		return (0);
  664: 	}
  665: 	switch (month) {
  666: 		case 1:
  667: 		case 2:
  668: 			/* It is Tishri or Heshvan - don't need the year length. */
  669: 			FindStartOfYear(year, &metonicCycle, &metonicYear,
  670: 							&moladDay, &moladHalakim, &tishri1);
  671: 			if (month == 1) {
  672: 				sdn = tishri1 + day - 1;
  673: 			} else {
  674: 				sdn = tishri1 + day + 29;
  675: 			}
  676: 			break;
  677: 
  678: 		case 3:
  679: 			/* It is Kislev - must find the year length. */
  680: 
  681: 			/* Find the start of the year. */
  682: 			FindStartOfYear(year, &metonicCycle, &metonicYear,
  683: 							&moladDay, &moladHalakim, &tishri1);
  684: 
  685: 			/* Find the end of the year. */
  686: 			moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
  687: 			moladDay += moladHalakim / HALAKIM_PER_DAY;
  688: 			moladHalakim = moladHalakim % HALAKIM_PER_DAY;
  689: 			tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim);
  690: 
  691: 			yearLength = tishri1After - tishri1;
  692: 
  693: 			if (yearLength == 355 || yearLength == 385) {
  694: 				sdn = tishri1 + day + 59;
  695: 			} else {
  696: 				sdn = tishri1 + day + 58;
  697: 			}
  698: 			break;
  699: 
  700: 		case 4:
  701: 		case 5:
  702: 		case 6:
  703: 			/* It is Tevet, Shevat or Adar I - don't need the year length. */
  704: 
  705: 			FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
  706: 							&moladDay, &moladHalakim, &tishri1After);
  707: 
  708: 			if (monthsPerYear[(year - 1) % 19] == 12) {
  709: 				lengthOfAdarIAndII = 29;
  710: 			} else {
  711: 				lengthOfAdarIAndII = 59;
  712: 			}
  713: 
  714: 			if (month == 4) {
  715: 				sdn = tishri1After + day - lengthOfAdarIAndII - 237;
  716: 			} else if (month == 5) {
  717: 				sdn = tishri1After + day - lengthOfAdarIAndII - 208;
  718: 			} else {
  719: 				sdn = tishri1After + day - lengthOfAdarIAndII - 178;
  720: 			}
  721: 			break;
  722: 
  723: 		default:
  724: 			/* It is Adar II or later - don't need the year length. */
  725: 			FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
  726: 							&moladDay, &moladHalakim, &tishri1After);
  727: 
  728: 			switch (month) {
  729: 				case 7:
  730: 					sdn = tishri1After + day - 207;
  731: 					break;
  732: 				case 8:
  733: 					sdn = tishri1After + day - 178;
  734: 					break;
  735: 				case 9:
  736: 					sdn = tishri1After + day - 148;
  737: 					break;
  738: 				case 10:
  739: 					sdn = tishri1After + day - 119;
  740: 					break;
  741: 				case 11:
  742: 					sdn = tishri1After + day - 89;
  743: 					break;
  744: 				case 12:
  745: 					sdn = tishri1After + day - 60;
  746: 					break;
  747: 				case 13:
  748: 					sdn = tishri1After + day - 30;
  749: 					break;
  750: 				default:
  751: 					return (0);
  752: 			}
  753: 	}
  754: 	return (sdn + JEWISH_SDN_OFFSET);
  755: }
  756: 
  757: /*
  758:  * Local variables:
  759:  * tab-width: 4
  760:  * c-basic-offset: 4
  761:  * End:
  762:  * vim600: sw=4 ts=4 fdm=marker
  763:  * vim<600: sw=4 ts=4
  764:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>