PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/calendar - jewish.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 173 184 94.0 %
Date: 2014-09-27 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:06 +0000 (3 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.