jewish.c 26 KB

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