root/ext/calendar/jewish.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Tishri1
  2. MoladOfMetonicCycle
  3. FindTishriMolad
  4. FindStartOfYear
  5. SdnToJewish
  6. JewishToSdn

   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)
 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 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         tishri1 = moladDay;
 396         dow = tishri1 % 7;
 397         leapYear = metonicYear == 2 || metonicYear == 5 || metonicYear == 7
 398                 || metonicYear == 10 || metonicYear == 13 || metonicYear == 16
 399                 || metonicYear == 18;
 400         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         if ((moladHalakim >= NOON) ||
 406                 ((!leapYear) && dow == TUESDAY && moladHalakim >= AM3_11_20) ||
 407                 (lastWasLeapYear && dow == MONDAY && moladHalakim >= AM9_32_43)) {
 408                 tishri1++;
 409                 dow++;
 410                 if (dow == 7) {
 411                         dow = 0;
 412                 }
 413         }
 414         /* Apply rule 1 after the others because it can cause an additional
 415          * delay of one day. */
 416         if (dow == WEDNESDAY || dow == FRIDAY || dow == SUNDAY) {
 417                 tishri1++;
 418         }
 419         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 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         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         r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF);
 444         r2 = r1 >> 16;
 445         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         d2 = r2 / HALAKIM_PER_DAY;
 451         r2 -= d2 * HALAKIM_PER_DAY;
 452         r1 = (r2 << 16) | (r1 & 0xFFFF);
 453         d1 = r1 / HALAKIM_PER_DAY;
 454         r1 -= d1 * HALAKIM_PER_DAY;
 455 
 456         *pMoladDay = (d2 << 16) | d1;
 457         *pMoladHalakim = r1;
 458 }
 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 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         metonicCycle = (inputDay + 310) / 6940;
 487 
 488         /* Calculate the time of the starting molad for this metonic cycle. */
 489         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         while (moladDay < inputDay - 6940 + 310) {
 496                 metonicCycle++;
 497                 moladHalakim += HALAKIM_PER_METONIC_CYCLE;
 498                 moladDay += moladHalakim / HALAKIM_PER_DAY;
 499                 moladHalakim = moladHalakim % HALAKIM_PER_DAY;
 500         }
 501 
 502         /* Find the molad of Tishri closest to this date. */
 503         for (metonicYear = 0; metonicYear < 18; metonicYear++) {
 504                 if (moladDay > inputDay - 74) {
 505                         break;
 506                 }
 507                 moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
 508                 moladDay += moladHalakim / HALAKIM_PER_DAY;
 509                 moladHalakim = moladHalakim % HALAKIM_PER_DAY;
 510         }
 511 
 512         *pMetonicCycle = metonicCycle;
 513         *pMetonicYear = metonicYear;
 514         *pMoladDay = moladDay;
 515         *pMoladHalakim = moladHalakim;
 516 }
 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 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         *pMetonicCycle = (year - 1) / 19;
 531         *pMetonicYear = (year - 1) % 19;
 532         MoladOfMetonicCycle(*pMetonicCycle, pMoladDay, pMoladHalakim);
 533 
 534         *pMoladHalakim += HALAKIM_PER_LUNAR_CYCLE * yearOffset[*pMetonicYear];
 535         *pMoladDay += *pMoladHalakim / HALAKIM_PER_DAY;
 536         *pMoladHalakim = *pMoladHalakim % HALAKIM_PER_DAY;
 537 
 538         *pTishri1 = Tishri1(*pMetonicYear, *pMoladDay, *pMoladHalakim);
 539 }
 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 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         if (sdn <= JEWISH_SDN_OFFSET || sdn > JEWISH_SDN_MAX) {
 564                 *pYear = 0;
 565                 *pMonth = 0;
 566                 *pDay = 0;
 567                 return;
 568         }
 569         inputDay = sdn - JEWISH_SDN_OFFSET;
 570 
 571         FindTishriMolad(inputDay, &metonicCycle, &metonicYear, &day, &halakim);
 572         tishri1 = Tishri1(metonicYear, day, halakim);
 573 
 574         if (inputDay >= tishri1) {
 575                 /* It found Tishri 1 at the start of the year. */
 576                 *pYear = metonicCycle * 19 + metonicYear + 1;
 577                 if (inputDay < tishri1 + 59) {
 578                         if (inputDay < tishri1 + 30) {
 579                                 *pMonth = 1;
 580                                 *pDay = inputDay - tishri1 + 1;
 581                         } else {
 582                                 *pMonth = 2;
 583                                 *pDay = inputDay - tishri1 - 29;
 584                         }
 585                         return;
 586                 }
 587                 /* We need the length of the year to figure this out, so find
 588                  * Tishri 1 of the next year. */
 589                 halakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
 590                 day += halakim / HALAKIM_PER_DAY;
 591                 halakim = halakim % HALAKIM_PER_DAY;
 592                 tishri1After = Tishri1((metonicYear + 1) % 19, day, halakim);
 593         } else {
 594                 /* It found Tishri 1 at the end of the year. */
 595                 *pYear = metonicCycle * 19 + metonicYear;
 596                 if (inputDay >= tishri1 - 177) {
 597                         /* It is one of the last 6 months of the year. */
 598                         if (inputDay > tishri1 - 30) {
 599                                 *pMonth = 13;
 600                                 *pDay = inputDay - tishri1 + 30;
 601                         } else if (inputDay > tishri1 - 60) {
 602                                 *pMonth = 12;
 603                                 *pDay = inputDay - tishri1 + 60;
 604                         } else if (inputDay > tishri1 - 89) {
 605                                 *pMonth = 11;
 606                                 *pDay = inputDay - tishri1 + 89;
 607                         } else if (inputDay > tishri1 - 119) {
 608                                 *pMonth = 10;
 609                                 *pDay = inputDay - tishri1 + 119;
 610                         } else if (inputDay > tishri1 - 148) {
 611                                 *pMonth = 9;
 612                                 *pDay = inputDay - tishri1 + 148;
 613                         } else {
 614                                 *pMonth = 8;
 615                                 *pDay = inputDay - tishri1 + 178;
 616                         }
 617                         return;
 618                 } else {
 619                         if (monthsPerYear[(*pYear - 1) % 19] == 13) {
 620                                 *pMonth = 7;
 621                                 *pDay = inputDay - tishri1 + 207;
 622                                 if (*pDay > 0)
 623                                         return;
 624                                 (*pMonth)--;
 625                                 (*pDay) += 30;
 626                                 if (*pDay > 0)
 627                                         return;
 628                                 (*pMonth)--;
 629                                 (*pDay) += 30;
 630                         } else {
 631                                 *pMonth = 7;
 632                                 *pDay = inputDay - tishri1 + 207;
 633                                 if (*pDay > 0)
 634                                         return;
 635                                 (*pMonth) -= 2;
 636                                 (*pDay) += 30;
 637                         }
 638                         if (*pDay > 0)
 639                                 return;
 640                         (*pMonth)--;
 641                         (*pDay) += 29;
 642                         if (*pDay > 0)
 643                                 return;
 644 
 645                         /* We need the length of the year to figure this out, so find
 646                          * Tishri 1 of this year. */
 647                         tishri1After = tishri1;
 648                         FindTishriMolad(day - 365,
 649                                                         &metonicCycle, &metonicYear, &day, &halakim);
 650                         tishri1 = Tishri1(metonicYear, day, halakim);
 651                 }
 652         }
 653 
 654         yearLength = tishri1After - tishri1;
 655         day = inputDay - tishri1 - 29;
 656         if (yearLength == 355 || yearLength == 385) {
 657                 /* Heshvan has 30 days */
 658                 if (day <= 30) {
 659                         *pMonth = 2;
 660                         *pDay = day;
 661                         return;
 662                 }
 663                 day -= 30;
 664         } else {
 665                 /* Heshvan has 29 days */
 666                 if (day <= 29) {
 667                         *pMonth = 2;
 668                         *pDay = day;
 669                         return;
 670                 }
 671                 day -= 29;
 672         }
 673 
 674         /* It has to be Kislev. */
 675         *pMonth = 3;
 676         *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 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         if (year <= 0 || day <= 0 || day > 30) {
 703                 return (0);
 704         }
 705         switch (month) {
 706                 case 1:
 707                 case 2:
 708                         /* It is Tishri or Heshvan - don't need the year length. */
 709                         FindStartOfYear(year, &metonicCycle, &metonicYear,
 710                                                         &moladDay, &moladHalakim, &tishri1);
 711                         if (month == 1) {
 712                                 sdn = tishri1 + day - 1;
 713                         } else {
 714                                 sdn = tishri1 + day + 29;
 715                         }
 716                         break;
 717 
 718                 case 3:
 719                         /* It is Kislev - must find the year length. */
 720 
 721                         /* Find the start of the year. */
 722                         FindStartOfYear(year, &metonicCycle, &metonicYear,
 723                                                         &moladDay, &moladHalakim, &tishri1);
 724 
 725                         /* Find the end of the year. */
 726                         moladHalakim += HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear];
 727                         moladDay += moladHalakim / HALAKIM_PER_DAY;
 728                         moladHalakim = moladHalakim % HALAKIM_PER_DAY;
 729                         tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim);
 730 
 731                         yearLength = tishri1After - tishri1;
 732 
 733                         if (yearLength == 355 || yearLength == 385) {
 734                                 sdn = tishri1 + day + 59;
 735                         } else {
 736                                 sdn = tishri1 + day + 58;
 737                         }
 738                         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                         FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
 746                                                         &moladDay, &moladHalakim, &tishri1After);
 747 
 748                         if (monthsPerYear[(year - 1) % 19] == 12) {
 749                                 lengthOfAdarIAndII = 29;
 750                         } else {
 751                                 lengthOfAdarIAndII = 59;
 752                         }
 753 
 754                         if (month == 4) {
 755                                 sdn = tishri1After + day - lengthOfAdarIAndII - 237;
 756                         } else if (month == 5) {
 757                                 sdn = tishri1After + day - lengthOfAdarIAndII - 208;
 758                         } else {
 759                                 sdn = tishri1After + day - lengthOfAdarIAndII - 178;
 760                         }
 761                         break;
 762 
 763                 default:
 764                         /* It is Adar II or later - don't need the year length. */
 765                         FindStartOfYear(year + 1, &metonicCycle, &metonicYear,
 766                                                         &moladDay, &moladHalakim, &tishri1After);
 767 
 768                         switch (month) {
 769                                 case 7:
 770                                         sdn = tishri1After + day - 207;
 771                                         break;
 772                                 case 8:
 773                                         sdn = tishri1After + day - 178;
 774                                         break;
 775                                 case 9:
 776                                         sdn = tishri1After + day - 148;
 777                                         break;
 778                                 case 10:
 779                                         sdn = tishri1After + day - 119;
 780                                         break;
 781                                 case 11:
 782                                         sdn = tishri1After + day - 89;
 783                                         break;
 784                                 case 12:
 785                                         sdn = tishri1After + day - 60;
 786                                         break;
 787                                 case 13:
 788                                         sdn = tishri1After + day - 30;
 789                                         break;
 790                                 default:
 791                                         return (0);
 792                         }
 793         }
 794         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  */

/* [<][>][^][v][top][bottom][index][help] */