Annotation of embedaddon/php/ext/calendar/jewish.c, revision 1.1

1.1     ! misho       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 NEW_MOON_OF_CREATION 31524
        !           276: 
        !           277: #define SUNDAY    0
        !           278: #define MONDAY    1
        !           279: #define TUESDAY   2
        !           280: #define WEDNESDAY 3
        !           281: #define THURSDAY  4
        !           282: #define FRIDAY    5
        !           283: #define SATURDAY  6
        !           284: 
        !           285: #define NOON (18 * HALAKIM_PER_HOUR)
        !           286: #define AM3_11_20 ((9 * HALAKIM_PER_HOUR) + 204)
        !           287: #define AM9_32_43 ((15 * HALAKIM_PER_HOUR) + 589)
        !           288: 
        !           289: static int monthsPerYear[19] =
        !           290: {
        !           291: 12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 13
        !           292: };
        !           293: 
        !           294: static int yearOffset[19] =
        !           295: {
        !           296:        0, 12, 24, 37, 49, 61, 74, 86, 99, 111, 123,
        !           297:        136, 148, 160, 173, 185, 197, 210, 222
        !           298: };
        !           299: 
        !           300: char *JewishMonthName[14] =
        !           301: {
        !           302:        "",
        !           303:        "Tishri",
        !           304:        "Heshvan",
        !           305:        "Kislev",
        !           306:        "Tevet",
        !           307:        "Shevat",
        !           308:        "AdarI",
        !           309:        "AdarII",
        !           310:        "Nisan",
        !           311:        "Iyyar",
        !           312:        "Sivan",
        !           313:        "Tammuz",
        !           314:        "Av",
        !           315:        "Elul"
        !           316: };
        !           317: 
        !           318: char *JewishMonthHebName[14] =
        !           319: {
        !           320:        "",
        !           321:        "תשרי",
        !           322:        "חשון",
        !           323:        "כסלו",
        !           324:        "טבת",
        !           325:        "שבט",
        !           326:        "אדר",
        !           327:        "'אדר ב",
        !           328:        "ניסן",
        !           329:        "אייר",
        !           330:        "סיון",
        !           331:        "תמוז",
        !           332:        "אב",
        !           333:        "אלול"
        !           334: };
        !           335: 
        !           336: /************************************************************************
        !           337:  * Given the year within the 19 year metonic cycle and the time of a molad
        !           338:  * (new moon) which starts that year, this routine will calculate what day
        !           339:  * will be the actual start of the year (Tishri 1 or Rosh Ha-Shanah).  This
        !           340:  * first day of the year will be the day of the molad unless one of 4 rules
        !           341:  * (called dehiyyot) delays it.  These 4 rules can delay the start of the
        !           342:  * year by as much as 2 days.
        !           343:  */
        !           344: static long int Tishri1(
        !           345:                                                   int metonicYear,
        !           346:                                                   long int moladDay,
        !           347:                                                   long int moladHalakim)
        !           348: {
        !           349:        long int tishri1;
        !           350:        int dow;
        !           351:        int leapYear;
        !           352:        int lastWasLeapYear;
        !           353: 
        !           354:        tishri1 = moladDay;
        !           355:        dow = tishri1 % 7;
        !           356:        leapYear = metonicYear == 2 || metonicYear == 5 || metonicYear == 7
        !           357:                || metonicYear == 10 || metonicYear == 13 || metonicYear == 16
        !           358:                || metonicYear == 18;
        !           359:        lastWasLeapYear = metonicYear == 3 || metonicYear == 6
        !           360:                || metonicYear == 8 || metonicYear == 11 || metonicYear == 14
        !           361:                || metonicYear == 17 || metonicYear == 0;
        !           362: 
        !           363:        /* Apply rules 2, 3 and 4. */
        !           364:        if ((moladHalakim >= NOON) ||
        !           365:                ((!leapYear) && dow == TUESDAY && moladHalakim >= AM3_11_20) ||
        !           366:                (lastWasLeapYear && dow == MONDAY && moladHalakim >= AM9_32_43)) {
        !           367:                tishri1++;
        !           368:                dow++;
        !           369:                if (dow == 7) {
        !           370:                        dow = 0;
        !           371:                }
        !           372:        }
        !           373:        /* Apply rule 1 after the others because it can cause an additional
        !           374:         * delay of one day. */
        !           375:        if (dow == WEDNESDAY || dow == FRIDAY || dow == SUNDAY) {
        !           376:                tishri1++;
        !           377:        }
        !           378:        return (tishri1);
        !           379: }
        !           380: 
        !           381: /************************************************************************
        !           382:  * Given a metonic cycle number, calculate the date and time of the molad
        !           383:  * (new moon) that starts that cycle.  Since the length of a metonic cycle
        !           384:  * is a constant, this is a simple calculation, except that it requires an
        !           385:  * intermediate value which is bigger that 32 bits.  Because this
        !           386:  * intermediate value only needs 36 to 37 bits and the other numbers are
        !           387:  * constants, the process has been reduced to just a few steps.
        !           388:  */
        !           389: static void MoladOfMetonicCycle(
        !           390:                                                                   int metonicCycle,
        !           391:                                                                   long int *pMoladDay,
        !           392:                                                                   long int *pMoladHalakim)
        !           393: {
        !           394:        register unsigned long int r1, r2, d1, d2;
        !           395: 
        !           396:        /* Start with the time of the first molad after creation. */
        !           397:        r1 = NEW_MOON_OF_CREATION;
        !           398: 
        !           399:        /* Calculate metonicCycle * HALAKIM_PER_METONIC_CYCLE.  The upper 32
        !           400:         * bits of the result will be in r2 and the lower 16 bits will be
        !           401:         * in r1. */
        !           402:        r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF);
        !           403:        r2 = r1 >> 16;
        !           404:        r2 += metonicCycle * ((HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF);
        !           405: 
        !           406:        /* Calculate r2r1 / HALAKIM_PER_DAY.  The remainder will be in r1, the
        !           407:         * upper 16 bits of the quotient will be in d2 and the lower 16 bits
        !           408:         * will be in d1. */
        !           409:        d2 = r2 / HALAKIM_PER_DAY;
        !           410:        r2 -= d2 * HALAKIM_PER_DAY;
        !           411:        r1 = (r2 << 16) | (r1 & 0xFFFF);
        !           412:        d1 = r1 / HALAKIM_PER_DAY;
        !           413:        r1 -= d1 * HALAKIM_PER_DAY;
        !           414: 
        !           415:        *pMoladDay = (d2 << 16) | d1;
        !           416:        *pMoladHalakim = r1;
        !           417: }
        !           418: 
        !           419: /************************************************************************
        !           420:  * Given a day number, find the molad of Tishri (the new moon at the start
        !           421:  * of a year) which is closest to that day number.  It's not really the
        !           422:  * *closest* molad that we want here.  If the input day is in the first two
        !           423:  * months, we want the molad at the start of the year.  If the input day is
        !           424:  * in the fourth to last months, we want the molad at the end of the year.
        !           425:  * If the input day is in the third month, it doesn't matter which molad is
        !           426:  * returned, because both will be required.  This type of "rounding" allows
        !           427:  * us to avoid calculating the length of the year in most cases.
        !           428:  */
        !           429: static void FindTishriMolad(
        !           430:                                                           long int inputDay,
        !           431:                                                           int *pMetonicCycle,
        !           432:                                                           int *pMetonicYear,
        !           433:                                                           long int *pMoladDay,
        !           434:                                                           long int *pMoladHalakim)
        !           435: {
        !           436:        long int moladDay;
        !           437:        long int moladHalakim;
        !           438:        int metonicCycle;
        !           439:        int metonicYear;
        !           440: 
        !           441:        /* Estimate the metonic cycle number.  Note that this may be an under
        !           442:         * estimate because there are 6939.6896 days in a metonic cycle not
        !           443:         * 6940, but it will never be an over estimate.  The loop below will
        !           444:         * correct for any error in this estimate. */
        !           445:        metonicCycle = (inputDay + 310) / 6940;
        !           446: 
        !           447:        /* Calculate the time of the starting molad for this metonic cycle. */
        !           448:        MoladOfMetonicCycle(metonicCycle, &moladDay, &moladHalakim);
        !           449: 
        !           450:        /* If the above was an under estimate, increment the cycle number until
        !           451:         * the correct one is found.  For modern dates this loop is about 98.6%
        !           452:         * likely to not execute, even once, because the above estimate is
        !           453:         * really quite close. */
        !           454:        while (moladDay < inputDay - 6940 + 310) {
        !           455:                metonicCycle++;
        !           456:                moladHalakim += HALAKIM_PER_METONIC_CYCLE;
        !           457:                moladDay += moladHalakim / HALAKIM_PER_DAY;
        !           458:                moladHalakim = moladHalakim % HALAKIM_PER_DAY;
        !           459:        }
        !           460: 
        !           461:        /* Find the molad of Tishri closest to this date. */
        !           462:        for (metonicYear = 0; metonicYear < 18; metonicYear++) {
        !           463:                if (moladDay > inputDay - 74) {
        !           464:                        break;
        !           465:                }
        !           466:                moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
        !           467:                moladDay += moladHalakim / HALAKIM_PER_DAY;
        !           468:                moladHalakim = moladHalakim % HALAKIM_PER_DAY;
        !           469:        }
        !           470: 
        !           471:        *pMetonicCycle = metonicCycle;
        !           472:        *pMetonicYear = metonicYear;
        !           473:        *pMoladDay = moladDay;
        !           474:        *pMoladHalakim = moladHalakim;
        !           475: }
        !           476: 
        !           477: /************************************************************************
        !           478:  * Given a year, find the number of the first day of that year and the date
        !           479:  * and time of the starting molad.
        !           480:  */
        !           481: static void FindStartOfYear(
        !           482:                                                           int year,
        !           483:                                                           int *pMetonicCycle,
        !           484:                                                           int *pMetonicYear,
        !           485:                                                           long int *pMoladDay,
        !           486:                                                           long int *pMoladHalakim,
        !           487:                                                           int *pTishri1)
        !           488: {
        !           489:        *pMetonicCycle = (year - 1) / 19;
        !           490:        *pMetonicYear = (year - 1) % 19;
        !           491:        MoladOfMetonicCycle(*pMetonicCycle, pMoladDay, pMoladHalakim);
        !           492: 
        !           493:        *pMoladHalakim += HALAKIM_PER_LUNAR_CYCLE * yearOffset[*pMetonicYear];
        !           494:        *pMoladDay += *pMoladHalakim / HALAKIM_PER_DAY;
        !           495:        *pMoladHalakim = *pMoladHalakim % HALAKIM_PER_DAY;
        !           496: 
        !           497:        *pTishri1 = Tishri1(*pMetonicYear, *pMoladDay, *pMoladHalakim);
        !           498: }
        !           499: 
        !           500: /************************************************************************
        !           501:  * Given a serial day number (SDN), find the corresponding year, month and
        !           502:  * day in the Jewish calendar.  The three output values will always be
        !           503:  * modified.  If the input SDN is before the first day of year 1, they will
        !           504:  * all be set to zero, otherwise *pYear will be > 0; *pMonth will be in the
        !           505:  * range 1 to 13 inclusive; *pDay will be in the range 1 to 30 inclusive.
        !           506:  */
        !           507: void SdnToJewish(
        !           508:                                        long int sdn,
        !           509:                                        int *pYear,
        !           510:                                        int *pMonth,
        !           511:                                        int *pDay)
        !           512: {
        !           513:        long int inputDay;
        !           514:        long int day;
        !           515:        long int halakim;
        !           516:        int metonicCycle;
        !           517:        int metonicYear;
        !           518:        int tishri1;
        !           519:        int tishri1After;
        !           520:        int yearLength;
        !           521: 
        !           522:        if (sdn <= JEWISH_SDN_OFFSET) {
        !           523:                *pYear = 0;
        !           524:                *pMonth = 0;
        !           525:                *pDay = 0;
        !           526:                return;
        !           527:        }
        !           528:        inputDay = sdn - JEWISH_SDN_OFFSET;
        !           529: 
        !           530:        FindTishriMolad(inputDay, &metonicCycle, &metonicYear, &day, &halakim);
        !           531:        tishri1 = Tishri1(metonicYear, day, halakim);
        !           532: 
        !           533:        if (inputDay >= tishri1) {
        !           534:                /* It found Tishri 1 at the start of the year. */
        !           535:                *pYear = metonicCycle * 19 + metonicYear + 1;
        !           536:                if (inputDay < tishri1 + 59) {
        !           537:                        if (inputDay < tishri1 + 30) {
        !           538:                                *pMonth = 1;
        !           539:                                *pDay = inputDay - tishri1 + 1;
        !           540:                        } else {
        !           541:                                *pMonth = 2;
        !           542:                                *pDay = inputDay - tishri1 - 29;
        !           543:                        }
        !           544:                        return;
        !           545:                }
        !           546:                /* We need the length of the year to figure this out, so find
        !           547:                 * Tishri 1 of the next year. */
        !           548:                halakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
        !           549:                day += halakim / HALAKIM_PER_DAY;
        !           550:                halakim = halakim % HALAKIM_PER_DAY;
        !           551:                tishri1After = Tishri1((metonicYear + 1) % 19, day, halakim);
        !           552:        } else {
        !           553:                /* It found Tishri 1 at the end of the year. */
        !           554:                *pYear = metonicCycle * 19 + metonicYear;
        !           555:                if (inputDay >= tishri1 - 177) {
        !           556:                        /* It is one of the last 6 months of the year. */
        !           557:                        if (inputDay > tishri1 - 30) {
        !           558:                                *pMonth = 13;
        !           559:                                *pDay = inputDay - tishri1 + 30;
        !           560:                        } else if (inputDay > tishri1 - 60) {
        !           561:                                *pMonth = 12;
        !           562:                                *pDay = inputDay - tishri1 + 60;
        !           563:                        } else if (inputDay > tishri1 - 89) {
        !           564:                                *pMonth = 11;
        !           565:                                *pDay = inputDay - tishri1 + 89;
        !           566:                        } else if (inputDay > tishri1 - 119) {
        !           567:                                *pMonth = 10;
        !           568:                                *pDay = inputDay - tishri1 + 119;
        !           569:                        } else if (inputDay > tishri1 - 148) {
        !           570:                                *pMonth = 9;
        !           571:                                *pDay = inputDay - tishri1 + 148;
        !           572:                        } else {
        !           573:                                *pMonth = 8;
        !           574:                                *pDay = inputDay - tishri1 + 178;
        !           575:                        }
        !           576:                        return;
        !           577:                } else {
        !           578:                        if (monthsPerYear[(*pYear - 1) % 19] == 13) {
        !           579:                                *pMonth = 7;
        !           580:                                *pDay = inputDay - tishri1 + 207;
        !           581:                                if (*pDay > 0)
        !           582:                                        return;
        !           583:                                (*pMonth)--;
        !           584:                                (*pDay) += 30;
        !           585:                                if (*pDay > 0)
        !           586:                                        return;
        !           587:                                (*pMonth)--;
        !           588:                                (*pDay) += 30;
        !           589:                        } else {
        !           590:                                *pMonth = 6;
        !           591:                                *pDay = inputDay - tishri1 + 207;
        !           592:                                if (*pDay > 0)
        !           593:                                        return;
        !           594:                                (*pMonth)--;
        !           595:                                (*pDay) += 30;
        !           596:                        }
        !           597:                        if (*pDay > 0)
        !           598:                                return;
        !           599:                        (*pMonth)--;
        !           600:                        (*pDay) += 29;
        !           601:                        if (*pDay > 0)
        !           602:                                return;
        !           603: 
        !           604:                        /* We need the length of the year to figure this out, so find
        !           605:                         * Tishri 1 of this year. */
        !           606:                        tishri1After = tishri1;
        !           607:                        FindTishriMolad(day - 365,
        !           608:                                                        &metonicCycle, &metonicYear, &day, &halakim);
        !           609:                        tishri1 = Tishri1(metonicYear, day, halakim);
        !           610:                }
        !           611:        }
        !           612: 
        !           613:        yearLength = tishri1After - tishri1;
        !           614:        day = inputDay - tishri1 - 29;
        !           615:        if (yearLength == 355 || yearLength == 385) {
        !           616:                /* Heshvan has 30 days */
        !           617:                if (day <= 30) {
        !           618:                        *pMonth = 2;
        !           619:                        *pDay = day;
        !           620:                        return;
        !           621:                }
        !           622:                day -= 30;
        !           623:        } else {
        !           624:                /* Heshvan has 29 days */
        !           625:                if (day <= 29) {
        !           626:                        *pMonth = 2;
        !           627:                        *pDay = day;
        !           628:                        return;
        !           629:                }
        !           630:                day -= 29;
        !           631:        }
        !           632: 
        !           633:        /* It has to be Kislev. */
        !           634:        *pMonth = 3;
        !           635:        *pDay = day;
        !           636: }
        !           637: 
        !           638: /************************************************************************
        !           639:  * Given a year, month and day in the Jewish calendar, find the
        !           640:  * corresponding serial day number (SDN).  Zero is returned when the input
        !           641:  * date is detected as invalid.  The return value will be > 0 for all valid
        !           642:  * dates, but there are some invalid dates that will return a positive
        !           643:  * value.  To verify that a date is valid, convert it to SDN and then back
        !           644:  * and compare with the original.
        !           645:  */
        !           646: long int JewishToSdn(
        !           647:                                                int year,
        !           648:                                                int month,
        !           649:                                                int day)
        !           650: {
        !           651:        long int sdn;
        !           652:        int metonicCycle;
        !           653:        int metonicYear;
        !           654:        int tishri1;
        !           655:        int tishri1After;
        !           656:        long int moladDay;
        !           657:        long int moladHalakim;
        !           658:        int yearLength;
        !           659:        int lengthOfAdarIAndII;
        !           660: 
        !           661:        if (year <= 0 || day <= 0 || day > 30) {
        !           662:                return (0);
        !           663:        }
        !           664:        switch (month) {
        !           665:                case 1:
        !           666:                case 2:
        !           667:                        /* It is Tishri or Heshvan - don't need the year length. */
        !           668:                        FindStartOfYear(year, &metonicCycle, &metonicYear,
        !           669:                                                        &moladDay, &moladHalakim, &tishri1);
        !           670:                        if (month == 1) {
        !           671:                                sdn = tishri1 + day - 1;
        !           672:                        } else {
        !           673:                                sdn = tishri1 + day + 29;
        !           674:                        }
        !           675:                        break;
        !           676: 
        !           677:                case 3:
        !           678:                        /* It is Kislev - must find the year length. */
        !           679: 
        !           680:                        /* Find the start of the year. */
        !           681:                        FindStartOfYear(year, &metonicCycle, &metonicYear,
        !           682:                                                        &moladDay, &moladHalakim, &tishri1);
        !           683: 
        !           684:                        /* Find the end of the year. */
        !           685:                        moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
        !           686:                        moladDay += moladHalakim / HALAKIM_PER_DAY;
        !           687:                        moladHalakim = moladHalakim % HALAKIM_PER_DAY;
        !           688:                        tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim);
        !           689: 
        !           690:                        yearLength = tishri1After - tishri1;
        !           691: 
        !           692:                        if (yearLength == 355 || yearLength == 385) {
        !           693:                                sdn = tishri1 + day + 59;
        !           694:                        } else {
        !           695:                                sdn = tishri1 + day + 58;
        !           696:                        }
        !           697:                        break;
        !           698: 
        !           699:                case 4:
        !           700:                case 5:
        !           701:                case 6:
        !           702:                        /* It is Tevet, Shevat or Adar I - don't need the year length. */
        !           703: 
        !           704:                        FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
        !           705:                                                        &moladDay, &moladHalakim, &tishri1After);
        !           706: 
        !           707:                        if (monthsPerYear[(year - 1) % 19] == 12) {
        !           708:                                lengthOfAdarIAndII = 29;
        !           709:                        } else {
        !           710:                                lengthOfAdarIAndII = 59;
        !           711:                        }
        !           712: 
        !           713:                        if (month == 4) {
        !           714:                                sdn = tishri1After + day - lengthOfAdarIAndII - 237;
        !           715:                        } else if (month == 5) {
        !           716:                                sdn = tishri1After + day - lengthOfAdarIAndII - 208;
        !           717:                        } else {
        !           718:                                sdn = tishri1After + day - lengthOfAdarIAndII - 178;
        !           719:                        }
        !           720:                        break;
        !           721: 
        !           722:                default:
        !           723:                        /* It is Adar II or later - don't need the year length. */
        !           724:                        FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
        !           725:                                                        &moladDay, &moladHalakim, &tishri1After);
        !           726: 
        !           727:                        switch (month) {
        !           728:                                case 7:
        !           729:                                        sdn = tishri1After + day - 207;
        !           730:                                        break;
        !           731:                                case 8:
        !           732:                                        sdn = tishri1After + day - 178;
        !           733:                                        break;
        !           734:                                case 9:
        !           735:                                        sdn = tishri1After + day - 148;
        !           736:                                        break;
        !           737:                                case 10:
        !           738:                                        sdn = tishri1After + day - 119;
        !           739:                                        break;
        !           740:                                case 11:
        !           741:                                        sdn = tishri1After + day - 89;
        !           742:                                        break;
        !           743:                                case 12:
        !           744:                                        sdn = tishri1After + day - 60;
        !           745:                                        break;
        !           746:                                case 13:
        !           747:                                        sdn = tishri1After + day - 30;
        !           748:                                        break;
        !           749:                                default:
        !           750:                                        return (0);
        !           751:                        }
        !           752:        }
        !           753:        return (sdn + JEWISH_SDN_OFFSET);
        !           754: }
        !           755: 
        !           756: /*
        !           757:  * Local variables:
        !           758:  * tab-width: 4
        !           759:  * c-basic-offset: 4
        !           760:  * End:
        !           761:  * vim600: sw=4 ts=4 fdm=marker
        !           762:  * vim<600: sw=4 ts=4
        !           763:  */

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