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

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
1.1.1.2 ! misho     275: #define JEWISH_SDN_MAX 324542846L /* 12/13/887605, greater value raises interger overflow */
1.1       misho     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: 
1.1.1.2 ! misho     523:        if (sdn <= JEWISH_SDN_OFFSET || sdn > JEWISH_SDN_MAX) {
1.1       misho     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>