001 /*
002 * Zmanim Java API
003 * Copyright (C) 2011 Eliyahu Hershfeld
004 * Copyright (C) September 2002 Avrom Finkelstien
005 *
006 * This program is free software; you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
011 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License along with this program; if
015 * not, write to the Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA
016 * 02111-1307, USA or connect to: http://www.fsf.org/copyleft/gpl.html
017 */
018 package net.sourceforge.zmanim.hebrewcalendar;
019
020 import java.util.*;
021
022 /**
023 * The JewishDate class allows one to maintain an instance of a Gregorian date
024 * along with the corresponding Jewish date. This class can use the standard
025 * Java Date and Calendar classes for setting it, but does not subclass these
026 * classes or use them internally to any extensive use. This class also does not
027 * have a concept of a time (which the Date class does). If you are looking for
028 * a class that implements a Jewish calendar version of the Calendar class, one
029 * is available from <a
030 * href="http://oss.software.ibm.com/developerworks/opensource/icu4j/"
031 * >developerWorks</a> by IBM.
032 *
033 * This open source Java code was written by <a
034 * href="http://www.facebook.com/avromf">Avrom Finkelstien</a> from his C++
035 * code. it was adapted to the KosherJava Zmanim API with simplification of the
036 * non-core code. The original algorithms were untouched.
037 *
038 * Some of Avrom's original C++ code was translated from <a
039 * href="http://emr.cs.uiuc.edu/~reingold/calendar.C">C/C++ code</a> in <a
040 * href="http://www.calendarists.com">Calendrical Calculations</a> by Nachum
041 * Dershowitz and Edward M. Reingold, Software-- Practice & Experience, vol. 20,
042 * no. 9 (September, 1990), pp. 899- 928. Any method with the mark "ND+ER"
043 * indicates that the method was taken from this source with minor
044 * modifications.
045 *
046 * The methods used to obtain the parsha were derived from the source code of <a
047 * href="http://www.sadinoff.com/hebcal/">HebCal</a> by Danny Sadinoff and JCal
048 * for the Mac by Frank Yellin. Both based their code on routines by Nachum
049 * Dershowitz and Edward M. Reingold. The class allows setting whether the
050 * parsha and holiday scheme follows the Israel scheme or outside Israel scheme.
051 *
052 * <b>TODO:</b> Some do not belong in this class, but here is a partial list of what should still be implementted in some form:
053 * <ol>
054 * <li>Add special parshiyos (shekalim, parah, zachor and hachodesh</li>
055 * <li>Molad / shabbos mevarchim)</li>
056 * <li>Haftorah (various minhagim)</li>
057 * <li>Daf Yomi (bavli, yerushalmi, mishna yomis etc)</li>
058 * <li>Support showing the upcoming parsha for the middle of the week</li>
059 * </ol>
060 *
061 * @see java.util.Date
062 * @see java.util.Calendar
063 * @author © Avrom Finkelstien 2002
064 * @author © Eliyahu Hershfeld 2011
065 * @version 0.2.5
066 */
067 public class JewishDate implements Comparable, Cloneable {
068 private static final int JEWISH_EPOCH = -1373429;
069
070 private int jewishMonth;
071 private int jewishDay;
072 private int jewishYear;
073
074 private int gregorianMonth;
075 private int gregorianDayOfMonth;
076 private int gregorianYear;
077
078 private int dayOfWeek;
079
080 private int gregorianAbsDate;
081
082 /**
083 * Use the formatting class for formatting Ashkenazi VS Sephardi English
084 * transliteration. Using the default will use the Ashkenazi pronounciation.
085 */
086 private static final String[] parshios = { "Bereshis", "Noach",
087 "Lech Lecha", "Vayera", "Chayei Sara", "Toldos", "Vayetzei",
088 "Vayishlach", "Vayeshev", "Miketz", "Vayigash", "Vayechi",
089 "Shemos", "Vaera", "Bo", "Beshalach", "Yisro", "Mishpatim",
090 "Terumah", "Tetzaveh", "Ki Sisa", "Vayakhel", "Pekudei", "Vayikra",
091 "Tzav", "Shmini", "Tazria", "Metzora", "Achrei Mos", "Kedoshim",
092 "Emor", "Behar", "Bechukosai", "Bamidbar", "Nasso", "Beha'aloscha",
093 "Sh'lach", "Korach", "Chukas", "Balak", "Pinchas", "Matos",
094 "Masei", "Devarim", "Vaeschanan", "Eikev", "Re'eh", "Shoftim",
095 "Ki Seitzei", "Ki Savo", "Nitzavim", "Vayeilech", "Ha'Azinu",
096 "Vayakhel Pekudei", "Tazria Metzora", "Achrei Mos Kedoshim",
097 "Behar Bechukosai", "Chukas Balak", "Matos Masei",
098 "Nitzavim Vayeilech" };
099 private boolean inIsrael = false;
100
101 /**
102 * Returns the number of days in a given month in a given year.
103 *
104 * @param month
105 * the month
106 * @param year
107 * the year (only impacts February)
108 * @return the number of days in the month in the given year
109 */
110 private static int getLastDayOfGregorianMonth(int month, int year) {
111 switch (month) {
112 case 2:
113 if ((((year % 4) == 0) && ((year % 100) != 0))
114 || ((year % 400) == 0)) {
115 return 29;
116 } else {
117 return 28;
118 }
119 case 4:
120 case 6:
121 case 9:
122 case 11:
123 return 30;
124 default:
125 return 31;
126 }
127 }
128
129 /**
130 * Returns the number of days in a given month for the current year.
131 * Will likely turn into a private method in the future.
132 * @param month
133 * the month
134 * @return the number of days in the month
135 */
136 int getLastDayOfGregorianMonth(int month) {
137 return getLastDayOfGregorianMonth(month, gregorianYear);
138 }
139
140 /**
141 * Computes the Gregorian date from the absolute date. ND+ER
142 */
143 private void absDateToDate() {
144 // Search forward year by year from approximate year
145 gregorianYear = gregorianAbsDate / 366;
146 while (gregorianAbsDate >= gregorianDateToAbsDate(gregorianYear + 1, 1,
147 1)) {
148 gregorianYear++;
149 }
150 // Search forward month by month from January
151 gregorianMonth = 1;
152 while (gregorianAbsDate > gregorianDateToAbsDate(gregorianYear,
153 gregorianMonth, getLastDayOfGregorianMonth(gregorianMonth))) {
154 gregorianMonth++;
155 }
156 gregorianDayOfMonth = gregorianAbsDate
157 - gregorianDateToAbsDate(gregorianYear, gregorianMonth, 1) + 1;
158 }
159
160 /**
161 * Returns the absolute date (days since January 1, 0001 on the Gregorian
162 * calendar).
163 *
164 * @return the number of days since January 1, 1
165 */
166 private int getAbsDate() {
167 return gregorianAbsDate;
168 }
169
170 /**
171 * Computes the absolute date from a Gregorian date. ND+ER
172 *
173 * @param year
174 * the Gregorian year
175 * @param month
176 * the Gregorian month. Unlike the Java Calendar where January
177 * has the value of 0,This expects a 1 for January
178 * @param absDate
179 * the Gregorian day of month. If this is > the number of days in
180 * the month/year, the last valid date of the month will be set
181 * @return the absolute Gregorian day
182 */
183 private static int gregorianDateToAbsDate(int year, int month,
184 int dayOfMonth) {
185 int absDate = 0; //dayOfMonth
186 for (int m = month - 1; m > 0; m--) {
187 // days in prior months of the year
188 absDate = dayOfMonth + getLastDayOfGregorianMonth(m, year);
189 }
190 return (absDate // days this year //
191 + 365 * (year - 1) // days in previous years ignoring leap days
192 + (year - 1) / 4 // Julian leap days before this year...
193 - (year - 1) / 100 // ...minus prior century years...
194 + (year - 1) / 400); // ...plus prior years divisible by 400
195 }
196
197 /**
198 * Returns if the year is a Jewish leap year.
199 *
200 * @param year
201 * the Jewish year.
202 * @return true if it is a leap year
203 */
204 public static boolean isJewishLeapYear(int year) {
205 if ((((7 * year) + 1) % 19) < 7) {
206 return true;
207 } else {
208 return false;
209 }
210 }
211
212 /**
213 * Returns the last month of a given Jewish year.
214 *
215 * @param year
216 * the Jewish year.
217 * @return 12 on a non leap-year or 13 on a leap-year
218 */
219 private static int getLastMonthOfJewishYear(int year) {
220 return isJewishLeapYear(year) ? 13 : 12;
221 }
222
223 /**
224 * Returns the number of days elapsed from the Sunday prior to the start of
225 * the Jewish calendar to the mean conjunction of Tishri of the Jewish
226 * year.ND+ER
227 *
228 * @param year
229 * the Jewish year
230 * @return the number of days elapsed from the Sunday prior to the start of
231 * the Jewish calendar to the mean conjunction of Tishri of Jewish
232 * year.
233 */
234 private static int getJewishCalendarElapsedDays(int year) {
235 int monthsElapsed = (235 * ((year - 1) / 19)) // Months in complete
236 // cycles so far
237 + (12 * ((year - 1) % 19)) // Regular months in this cycle
238 + (7 * ((year - 1) % 19) + 1) / 19; // Leap months this cycle
239 int partsElapsed = 204 + 793 * (monthsElapsed % 1080);
240 int hoursElapsed = 5 + 12 * monthsElapsed + 793
241 * (monthsElapsed / 1080) + partsElapsed / 1080;
242 int conjunctionDay = 1 + 29 * monthsElapsed + hoursElapsed / 24;
243 int conjunctionParts = 1080 * (hoursElapsed % 24) + partsElapsed % 1080;
244 int alternativeDay;
245 if ((conjunctionParts >= 19440) // If new moon is at or after midday,
246 || (((conjunctionDay % 7) == 2) // ...or is on a Tuesday...
247 && (conjunctionParts >= 9924) // at 9 hours, 204 parts
248 // or later...
249 && !isJewishLeapYear(year)) // ...of a common year,
250 || (((conjunctionDay % 7) == 1) // ...or is on a Monday at...
251 && (conjunctionParts >= 16789) // 15 hours, 589 parts or
252 // later...
253 && (isJewishLeapYear(year - 1)))) { // at the end of a leap year
254 // Then postpone Rosh HaShanah one day
255 alternativeDay = conjunctionDay + 1;
256 } else {
257 alternativeDay = conjunctionDay;
258 }
259 if (((alternativeDay % 7) == 0)// If Rosh HaShanah would occur on
260 // Sunday,
261 || ((alternativeDay % 7) == 3) // or Wednesday,
262 || ((alternativeDay % 7) == 5)) { // or Friday
263 // Then postpone it one (more) day
264 return (1 + alternativeDay);
265 } else {
266 return alternativeDay;
267 }
268 }
269
270 /**
271 * Returns the number of days for a given Jewish year. ND+ER
272 *
273 * @param year
274 * the Jewish year
275 * @return the number of days for a given Jewish year.
276 */
277 private static int getDaysInJewishYear(int year) {
278 return getJewishCalendarElapsedDays(year + 1)
279 - getJewishCalendarElapsedDays(year);
280 }
281
282 /**
283 * Returns if Cheshvan is long in a given Jewish year. ND+ER
284 *
285 * @param year
286 * the year
287 * @return true if Cheshvan is long in Jewish year.
288 */
289 public static boolean isCheshvanLong(int year) {
290 return getDaysInJewishYear(year) % 10 == 5;
291 }
292
293 /**
294 * Returns if the day is Rosh Chodesh.
295 *
296 * @return true if it is Rosh Chodesh. Rosh Hashana will return false
297 */
298 public boolean isRoshChodesh() {
299 // Rosh Hashana is not rosh chodesh. Elul never has 30 days
300 return (jewishDay == 1 && jewishMonth != 7) || jewishDay == 30;
301 }
302
303 /**
304 * Returns if Kislev is short in a given Jewish year. ND+ER
305 *
306 * @param year
307 * the Jewish year
308 * @return true if Kislev is short for the given Jewish year.
309 */
310 public static boolean isKislevShort(int year) {
311 return getDaysInJewishYear(year) % 10 == 3;
312 }
313
314 /**
315 * Returns the number of days of a Jewish month for a given month and year.
316 *
317 * @param month
318 * the Jewish month
319 * @param year
320 * the Jewish Year
321 * @return the number of days for a given Jewish month
322 */
323 public static int getDaysInJewishMonth(int month, int year) {
324 if ((month == 2) || (month == 4) || (month == 6)
325 || ((month == 8) && !(isCheshvanLong(year)))
326 || ((month == 9) && isKislevShort(year)) || (month == 10)
327 || ((month == 12) && !(isJewishLeapYear(year)))
328 || (month == 13)) {
329 return 29;
330 } else {
331 return 30;
332 }
333 }
334
335 /**
336 * Computes the Jewish date from the absolute date. ND+ER
337 */
338 private void absDateToJewishDate() {
339 // Approximation from below
340 jewishYear = (gregorianAbsDate + JEWISH_EPOCH) / 366;
341 // Search forward for year from the approximation
342 while (gregorianAbsDate >= jewishDateToAbsDate(jewishYear + 1, 7, 1)) {
343 jewishYear++;
344 }
345 // Search forward for month from either Tishri or Nisan.
346 if (gregorianAbsDate < jewishDateToAbsDate(jewishYear, 1, 1)) {
347 jewishMonth = 7;// Start at Tishri
348 } else {
349 jewishMonth = 1;// Start at Nisan
350 }
351 while (gregorianAbsDate > jewishDateToAbsDate(jewishYear, jewishMonth,
352 getDaysInJewishMonth(jewishMonth, jewishYear))) {
353 jewishMonth++;
354 }
355 // Calculate the day by subtraction
356 jewishDay = gregorianAbsDate
357 - jewishDateToAbsDate(jewishYear, jewishMonth, 1) + 1;
358 }
359
360 /**
361 * Computes the absolute date of Jewish date. Default is current Jewish
362 * date. ND+ER
363 */
364 // private int hebrewDateToAbsDateBROKEN(int month, int date, int year) {
365 // int m;
366 //
367 // // Before Tishri, so add days in prior months//
368 // if (month < 7) {
369 // // this year before and after Nisan.//
370 // for (m = 7; m <= getLastMonthOfHebrewYear(hebrewYear); m++) {
371 // date = date + getLastDayOfHebrewMonth(m, year);
372 // }
373 // for (m = 1; m < month; m++) {
374 // date = date + getLastDayOfHebrewMonth(m, year);
375 // }
376 // } else { // Add days in prior months this year//
377 // for (m = 7; m < month; m++) {
378 // date = date + getLastDayOfHebrewMonth(m, year);
379 // }
380 // }
381 // // Days in prior years + Days elapsed before absolute date 1
382 // return (date + getHebrewCalendarElapsedDays(year) + HEBREW_EPOCH);
383 // }
384
385 /**
386 * Returns the absolute date of Jewish date. ND+ER
387 *
388 * @param year
389 * the Jewish year. The year can't be negative
390 * @param month
391 * the Jewish month starting with Nisan. Nisan expects a value of
392 * 1 etc till Adar with a value of 12. For a leap year, 13 will
393 * be the expected value for Adar II.
394 * @param dayOfMonth
395 * the Jewish day of month. valid values are 1-30. If the day of
396 * month is set to 30 for a month that only has 29 days, the day
397 * will be set as 29.
398 * @return the absolute date of the Jewish date.
399 */
400 private static int jewishDateToAbsDate(int year, int month, int dayOfMonth) {
401 int m;
402 // Before Tishri, so add days in prior months
403 if (month < 7) {
404 // this year before and after Nisan.
405 for (m = 7; m <= getLastMonthOfJewishYear(year); m++) {
406 dayOfMonth = dayOfMonth + getDaysInJewishMonth(m, year);
407 }
408 for (m = 1; m < month; m++) {
409 dayOfMonth = dayOfMonth + getDaysInJewishMonth(m, year);
410 }
411 } else { // Add days in prior months this year
412 for (m = 7; m < month; m++) {
413 dayOfMonth = dayOfMonth + getDaysInJewishMonth(m, year);
414 }
415 }
416 // Days in prior years + Days elapsed before absolute date 1
417 return (dayOfMonth + getJewishCalendarElapsedDays(year) + JEWISH_EPOCH);
418 }
419
420 /**
421 * Creates a Jewish date based on a Gregorian date
422 *
423 * @param gregorianYear
424 * the Gregorian year
425 * @param gregorianMonth
426 * the Gregorian month. Unlike the Java Calendar where January
427 * has the value of 0,This expects a 1 for January
428 * @param gregorianDayOfMonth
429 * the Gregorian day of month. If this is > the number of days in
430 * the month/year, the last valid date of the month will be set
431 *
432 */
433 public JewishDate(int gregorianYear, int gregorianMonth,
434 int gregorianDayOfMonth) {
435 setGregorianDate(gregorianYear, gregorianMonth, gregorianDayOfMonth);
436 }
437
438 /**
439 * Creates a Jewish date based on Gregorian date and whether in Israel
440 *
441 * @param gregorianYear
442 * the Gregorian year
443 * @param gregorianMonth
444 * the Gregorian month. Unlike the Java Calendar where January
445 * has the value of 0,This expects a 1 for January
446 * @param gregorianDayOfMonth
447 * the Gregorian day of month. If this is > the number of days in
448 * the month/year, the last valid date of the month will be set
449 * @param inIsrael
450 * whether in Israel. This affects Yom Tov and Parsha
451 * calculations
452 */
453 public JewishDate(int gregorianYear, int gregorianMonth,
454 int gregorianDayOfMonth, boolean inIsrael) {
455 this(gregorianYear, gregorianMonth, gregorianDayOfMonth);
456 setInIsrael(inIsrael);
457 }
458
459 /**
460 * Default constructor will set a default date to the current system date.
461 */
462 public JewishDate() {
463 resetDate();
464 }
465
466 /**
467 * A constructor that initializes the date to the {@link java.util.Date
468 * Date} paremeter.
469 *
470 * @param date
471 * the <code>Date</code> to set the calendar to
472 */
473 public JewishDate(Date date) {
474 setDate(date);
475 }
476
477 /**
478 * A constructor that initializes the date to the {@link java.util.Calendar
479 * Calendar} paremeter.
480 *
481 * @param calendar
482 * the <code>Calendar</code> to set the calendar to
483 */
484 public JewishDate(Calendar calendar) {
485 setDate(calendar);
486 }
487
488 /**
489 * Sets the date based on a {@link java.util.Calendar Calendar} object.
490 * Modifies the Jewish date as well.
491 *
492 * @param calendar
493 * the <code>Calendar</code> to set the calendar to
494 */
495 public void setDate(Calendar calendar) {
496 gregorianMonth = calendar.get(Calendar.MONTH) + 1;
497 gregorianDayOfMonth = calendar.get(Calendar.DATE);
498 gregorianYear = calendar.get(Calendar.YEAR);
499
500 // init the date
501 gregorianAbsDate = gregorianDateToAbsDate(gregorianYear,
502 gregorianMonth, gregorianDayOfMonth);
503 absDateToJewishDate();
504
505 // set day of week
506 dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1;
507 }
508
509 /**
510 * Sets the date based on a {@link java.util.Date Date} object. Modifies the
511 * Jewish date as well.
512 *
513 * @param date
514 * the <code>Date</code> to set the calendar to
515 */
516 public void setDate(Date date) {
517 Calendar cal = Calendar.getInstance();
518 cal.setTime(date);
519 setDate(cal);
520 }
521
522 /**
523 * Sets the Gregorian Date, and updates the Jewish date accordingly.
524 * Confusingly unlike the Java Calendar where January has the value of
525 * 0,This expects a 1 for January this uses a
526 *
527 * @param year
528 * the Gregorian year
529 * @param month
530 * the Gregorian month. Unlike the Java Calendar where January
531 * has the value of 0,This expects a 1 for January
532 * @param dayOfMonth
533 * the Gregorian day of month. If this is > the number of days in
534 * the month/year, the last valid date of the month will be set
535 */
536 public void setGregorianDate(int year, int month, int dayOfMonth) {
537 // precondition should be 1->12 anyways, but just in case... //
538 if (month > 12 || month < 1) {
539 throw new IllegalArgumentException(
540 "The Gregorian month has to be between 1 - 12. " + month
541 + " is invalid.");
542 }
543 if (dayOfMonth <= 0) {
544 throw new IllegalArgumentException(
545 "The day of month can't be less than 1. " + dayOfMonth
546 + " is invalid.");
547 }
548
549 // make sure date is a valid date for the given month, if not, set to
550 // last day of month
551 if (dayOfMonth > getLastDayOfGregorianMonth(month, year)) {
552 dayOfMonth = getLastDayOfGregorianMonth(month, year);
553 }
554 if (year < 0) {
555 throw new IllegalArgumentException(
556 "Years < 0 can't be claculated. " + year + " is invalid.");
557 }
558 // init month, date, year
559 gregorianMonth = month;
560 gregorianDayOfMonth = dayOfMonth;
561 gregorianYear = year;
562
563 // init date
564 gregorianAbsDate = gregorianDateToAbsDate(gregorianYear,
565 gregorianMonth, gregorianDayOfMonth);
566 absDateToJewishDate();
567
568 // set day of week
569 dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1;
570 }
571
572 /**
573 * Sets the Jewish Date and updates the Gregorian date accordingly.
574 *
575 * @param year
576 * the Jewish year. The year can't be negative
577 * @param month
578 * the Jewish month starting with Nisan. Nisan expects a value of
579 * 1 etc till Adar with a value of 12. For a leap year, 13 will
580 * be the expected value for Adar II.
581 * @param dayOfMonth
582 * the Jewish day of month. valid values are 1-30. If the day of
583 * month is set to 30 for a month that only has 29 days, the day
584 * will be set as 29.
585 */
586 public void setJewishDate(int year, int month, int dayOfMonth) {
587 if (month < 1 || month > getLastMonthOfJewishYear(year)) {
588 throw new IllegalArgumentException(
589 "The Jewish month has to be between 1 and 12 (or 13 on a leap year). "
590 + month + " is invalid for the year " + year + ".");
591 }
592 if (dayOfMonth < 1) {
593 throw new IllegalArgumentException(
594 "The Jewish day of month can't be < 1. " + dayOfMonth
595 + " is invalid.");
596 }
597
598 if (dayOfMonth > 30) {
599 throw new IllegalArgumentException(
600 "The Jewish day of month can't be > 30. " + dayOfMonth
601 + " is invalid.");
602 }
603
604 // if 30 is passed for a month that only has 29 days (for example by
605 // rolling the month from a month that had 30 days to a month that only
606 // has 29) set the date to 29th
607 if (dayOfMonth > getDaysInJewishMonth(month, year)) {
608 dayOfMonth = getDaysInJewishMonth(month, year);
609 }
610
611 if (year < 0) {
612 throw new IllegalArgumentException(
613 "A Jewish years < 0 can't be set. " + year + " is invalid.");
614 }
615
616 jewishMonth = month;
617 jewishDay = dayOfMonth;
618 jewishYear = year;
619
620 // reset Gregorian date
621 gregorianAbsDate = jewishDateToAbsDate(jewishYear, jewishMonth,
622 jewishDay);
623 absDateToDate();
624
625 // reset day of week
626 dayOfWeek = Math.abs(gregorianAbsDate % 7) + 1;
627 }
628
629 /**
630 * Returns this object's date as a java.util.Date object. <b>Note</b>: This
631 * class does not have a concept of time.
632 *
633 * @return The <code>Date</code>
634 */
635 public Date getTime() {
636 Calendar cal = Calendar.getInstance();
637 cal.set(gregorianYear, gregorianMonth - 1, gregorianDayOfMonth);
638 return cal.getTime();
639 }
640
641 /**
642 * Resets this date to the current system date.
643 */
644 public void resetDate() {
645 Calendar calendar = Calendar.getInstance();
646 setDate(calendar);
647 }
648
649 /**
650 * Returns a string containing the Jewish date in the form,
651 * "day Month, year" e.g. "21 Shevat, 5729". For more complex formatting,
652 * use the formatter classes.
653 *
654 * @return the Jewish date in the form "day Month, year" e.g.
655 * "21 Shevat, 5729"
656 */
657 public String toString() {
658 return HebrewDateFormatter.getHebrewDateAsString(this);
659 }
660
661 /**
662 * Rolls the date forward by 1. It modifies both the Gregorian and Jewish
663 * dates accordingly.
664 */
665 public void forward() {
666 // Change Gregorian date
667 if (gregorianDayOfMonth == getLastDayOfGregorianMonth(gregorianMonth)) {
668 // if last day of year
669 if (gregorianMonth == 12) {
670 gregorianYear++;
671 gregorianMonth = 1;
672 gregorianDayOfMonth = 1;
673 } else {
674 gregorianMonth++;
675 gregorianDayOfMonth = 1;
676 }
677 } else { // if not last day of month
678 gregorianDayOfMonth++;
679 }
680
681 // Change the Jewish Date
682 if (jewishDay == getDaysInJewishMonth(jewishMonth, jewishYear)) {
683 // if it last day of elul (i.e. last day of Jewish year)
684 if (jewishMonth == 6) {
685 jewishYear++;
686 jewishMonth++;
687 jewishDay = 1;
688 } else if (jewishMonth == getLastMonthOfJewishYear(jewishYear)) {
689 // if it is the last day of Adar, or Adar II as case may be
690 jewishMonth = 1;
691 jewishDay = 1;
692 } else {
693 jewishMonth++;
694 jewishDay = 1;
695 }
696 } else { // if not last date of month
697 jewishDay++;
698 }
699 // if last day of week, loop back to Sunday
700 if (dayOfWeek == 7) {
701 dayOfWeek = 1;
702 } else {
703 dayOfWeek++;
704 }
705 // increment the absolute date
706 gregorianAbsDate++;
707 }
708
709 /**
710 * Rolls the date back by 1. It modifies both the Gregorian and Jewish dates
711 * accordingly
712 */
713 public void back() {
714 // Change Gregorian date
715 // if first day of month
716 if (gregorianDayOfMonth == 1) {
717 // if first day of year
718 if (gregorianMonth == 1) {
719 gregorianMonth = 12;
720 gregorianYear--;
721 } else {
722 gregorianMonth--;
723 }
724 // change to last day of previous month
725 gregorianDayOfMonth = getLastDayOfGregorianMonth(gregorianMonth);
726 } else {
727 gregorianDayOfMonth--;
728 }
729 // change Jewish date
730 // if first day of the Jewish month
731 if (jewishDay == 1) {
732 // if Nissan
733 if (jewishMonth == 1) {
734 jewishMonth = getLastMonthOfJewishYear(jewishYear);
735 } else if (jewishMonth == 7) { // if Rosh Hashana
736 jewishYear--;
737 jewishMonth--;
738 } else {
739 jewishMonth--;
740 }
741 jewishDay = getDaysInJewishMonth(jewishMonth, jewishYear);
742 } else {
743 jewishDay--;
744 }
745 // if first day of week, loop back to Saturday
746 if (dayOfWeek == 1) {
747 dayOfWeek = 7;
748 } else {
749 dayOfWeek--;
750 }
751 // change the absolute date
752 gregorianAbsDate--;
753 }
754
755 /**
756 * Compares two dates to see if they are equal
757 */
758 public boolean equals(Object object) {
759 JewishDate hebDate = (JewishDate) object;
760 if (gregorianAbsDate != hebDate.getAbsDate()) {
761 return false;
762 } else {
763 return true;
764 }
765 }
766
767 /**
768 * Compares two dates as per the compareTo() method in the Comparable
769 * interface. Returns a value less than 0 if this date is "less than"
770 * (before) the date, greater than 0 if this date is "greater than" (after)
771 * the date, or 0 if they are equal.
772 */
773 public int compareTo(Object o) {
774 JewishDate hebDate = (JewishDate) o;
775 if (gregorianAbsDate < hebDate.getAbsDate()) {
776 return -1;
777 } else if (gregorianAbsDate > hebDate.getAbsDate()) {
778 return 1;
779 } else {
780 return 0;
781 }
782 }
783
784 /**
785 * Returns the Gregorian month (between 1-12).
786 *
787 * @return the Gregorian month (between 1-12). Unlike the
788 * java.util.Calendar, this will be 1 based and not 0 based.
789 */
790 public int getGregorianMonth() {
791 return gregorianMonth;
792 }
793
794 /**
795 * Returns the Gregorian day of the month.
796 *
797 * @return the Gregorian day of the mont
798 */
799 public int getGregorianDayOfMonth() {
800 return gregorianDayOfMonth;
801 }
802
803 /**
804 * Returns the Gregotian year.
805 *
806 * @return the Gregorian year
807 */
808 public int getGregorianYear() {
809 return gregorianYear;
810 }
811
812 /**
813 * Returns the Jewish month (1-12 or 13).
814 *
815 * @return the Jewish month from 1 to 12 (or 13 years in a leap year). The
816 * month count starts with 1 for Nisan and goes to 13 for Adar II
817 */
818 public int getJewishMonth() {
819 return jewishMonth;
820 }
821
822 /**
823 * Returns the Jewish day of month.
824 *
825 * @return the Jewish day of the month
826 */
827 public int getJewishDayOfMonth() {
828 return jewishDay;
829 }
830
831 /**
832 * Returns the Jewish year.
833 *
834 * @return the Jewish year
835 */
836 public int getJewishYear() {
837 return jewishYear;
838 }
839
840 /**
841 * Returns the day of the week as a number between 1-7.
842 *
843 * @return the day of the week as a number between 1-7.
844 */
845 public int getDayOfWeek() {
846 return dayOfWeek;
847 }
848
849 /**
850 * Sets the Gregorian month.
851 *
852 * @param month
853 * the Gregorian month
854 *
855 */
856 public void setGregorianMonth(int month) {
857 setGregorianDate(gregorianYear, month, gregorianDayOfMonth);
858 }
859
860 /**
861 * sets the Gregorian year.
862 *
863 * @param year
864 * the Gregorian year.
865 */
866 public void setGregorianYear(int year) {
867 setGregorianDate(year, gregorianMonth, gregorianDayOfMonth);
868 }
869
870 /**
871 * sets the Gregorian Day of month.
872 *
873 * @param dayOfMonth
874 * the Gregorian Day of month.
875 */
876 public void setGregorianDayOfMonth(int dayOfMonth) {
877 setGregorianDate(gregorianYear, gregorianMonth, dayOfMonth);
878 }
879
880 /**
881 * sets the Jewish month.
882 *
883 * @param month
884 * the Jewish month from 1 to 12 (or 13 years in a leap year).
885 * The month count starts with 1 for Nisan and goes to 13 for
886 * Adar II
887 */
888 public void setJewishMonth(int month) {
889 setJewishDate(jewishYear, month, jewishDay);
890 }
891
892 /**
893 * sets the Jewish year.
894 *
895 * @param year
896 * the Jewish year
897 */
898 public void setJewishYear(int year) {
899 setJewishDate(year, jewishMonth, jewishDay);
900 }
901
902 /**
903 * sets the Jewish day of month.
904 *
905 * @param dayOfMonth
906 * the Jewish day of month
907 */
908 public void setJewishDayOfMonth(int dayOfMonth) {
909 setJewishDate(jewishYear, jewishMonth, dayOfMonth);
910 }
911
912 /**
913 * Returns the int value of the Omer day or {@link Integer#MIN_VALUE} if the
914 * day is not in the omer
915 *
916 * @return The Omer count as an int or {@link Integer#MIN_VALUE} if it is
917 * not a day of the Omer.
918 */
919 public int getDayOfOmer() {
920 // int omer = 0;
921 // better to use MIN_VALUE that is a better equivalent to null
922 int omer = Integer.MIN_VALUE;
923
924 // if Nissan and second day of Pesach and on
925 if (jewishMonth == 1 && jewishDay >= 16) {
926 omer = jewishDay - 15;
927 // if Iyar
928 } else if (jewishMonth == 2) {
929 omer = jewishDay + 15;
930 // if Sivan and before Shavuos
931 } else if (jewishMonth == 3 && jewishDay < 6)
932 omer = jewishDay + 44;
933
934 return omer;
935 }
936
937 /**
938 * Returns a String of the Jewish holiday or fast day for the current day,
939 * or a null if there is no holiday for this day. Has no "modern" holidays.
940 *
941 * @return A String containing the holiday name or an empty string if it is
942 * not a holiday.
943 */
944 public String getHoliday() {
945 // check by month (starts from Nissan)
946 switch (jewishMonth) {
947 case 1:
948 if (jewishDay == 14) {
949 return "Erev Pesach";
950 } else if (jewishDay == 15 || jewishDay == 21
951 || (!inIsrael && (jewishDay == 16 || jewishDay == 22))) {
952 return "Pesach";
953 } else if (jewishDay >= 17 && jewishDay <= 20
954 || (jewishDay == 16 && inIsrael)) {
955 return "Chol Hamoed Pesach";
956 }
957 break;
958 case 2:
959 if (jewishDay == 14) {
960 return "Pesach Sheni";
961 }
962 break;
963 case 3:
964 if (jewishDay == 5) {
965 return "Erev Shavuos";
966 // if (ashkenaz) {
967 // return "Erev Shavuos";
968 // } else {
969 // return "Erev Shavuot";
970 // }
971 } else if (jewishDay == 6 || (jewishDay == 7 && !inIsrael)) {
972 return "Shavuos";
973 // if (ashkenaz) {
974 // return "Shavuos";
975 // } else {
976 // return "Shavuot";
977 // }
978 }
979 break;
980 case 4:
981 // push off the fast day if it falls on Shabbos
982 if ((jewishDay == 17 && dayOfWeek != 7)
983 || (jewishDay == 18 && dayOfWeek == 1)) {
984 return "Tzom Tammuz";
985 }
986 break;
987 case 5:
988 // if Tisha B'av falls on Shabbos, push off until Sunday
989 if ((dayOfWeek == 1 && jewishDay == 10)
990 || (dayOfWeek != 7 && jewishDay == 9)) {
991 return "Tisha B'av";
992 } else if (jewishDay == 15) {
993 return "Tu B'Av";
994 }
995 break;
996 case 6:
997 if (jewishDay == 29) {
998 return "Erev Rosh Hashanah";
999 }
1000 break;
1001 case 7:
1002 if (jewishDay == 1 || jewishDay == 2) {
1003 return "Rosh Hashanah";
1004 } else if ((jewishDay == 3 && dayOfWeek != 7)
1005 || (jewishDay == 4 && dayOfWeek == 1)) { // push off Tzom
1006 // Gedalia
1007 // if it falls on
1008 // Shabbos
1009 return "Tzom Gedalia";
1010 } else if (jewishDay == 9) {
1011 return "Erev Yom Kippur";
1012 } else if (jewishDay == 10) {
1013 return "Yom Kippur";
1014 } else if (jewishDay == 14) {
1015 return "Erev Sukkos";
1016 // if (ashkenaz) {
1017 // return "Erev Sukkos";
1018 // } else {
1019 // return "Erev Sukkot";
1020 // }
1021 }
1022 if (jewishDay == 15 || (jewishDay == 16 && !inIsrael)) {
1023 return "Sukkos";
1024 // if (ashkenaz) {
1025 // return "Sukkos";
1026 // } else {
1027 // return "Sukkot";
1028 // }
1029 }
1030 if (jewishDay >= 17 && jewishDay <= 20
1031 || (jewishDay == 16 && inIsrael)) {
1032 return "Chol Hamoed Sukkos";
1033 // if (ashkenaz) {
1034 // return "Chol Hamoed Sukkos";
1035 // } else {
1036 // return "Chol Hamoed Sukkot";
1037 // }
1038 }
1039 if (jewishDay == 21) {
1040 return "Hoshana Rabah";
1041 }
1042 if (jewishDay == 22) {
1043 return "Shmini Atzeres";
1044 // if (ashkenaz) {
1045 // return "Shmini Atzeres";
1046 // } else {
1047 // return "Shmini Atzeret";
1048 // }
1049 }
1050 if (jewishDay == 23 && !inIsrael) {
1051 return "Simchas Torah";
1052 // if (ashkenaz) {
1053 // return "Simchas Torah";
1054 // } else {
1055 // return "Simchat Torah";
1056 // }
1057 }
1058 break;
1059 case 9:
1060 if (jewishDay == 24) {
1061 return "Erev Chanukah";
1062 } else if (jewishDay >= 25) {
1063 return "Chanukah";
1064 }
1065 break;
1066 case 10:
1067 if (jewishDay == 1 || jewishDay == 2
1068 || (jewishDay == 3 && isKislevShort(jewishYear))) {
1069 return "Chanukah";
1070 } else if (jewishDay == 10) {
1071 return "Asarah BeTeves";
1072 // if (ashkenaz) {
1073 // return "Tzom Teves";
1074 // } else {
1075 // return "Tzom Tevet";
1076 // }
1077 }
1078 break;
1079 case 11:
1080 if (jewishDay == 15) {
1081 return "Tu B'Shvat";
1082 }
1083 break;
1084 case 12:
1085 if (!isJewishLeapYear(jewishYear)) {
1086 // if 13th Adar falls on Friday or Shabbos, push back to
1087 // Thursday
1088 if (((jewishDay == 11 || jewishDay == 12) && dayOfWeek == 5)
1089 || (jewishDay == 13 && !(dayOfWeek == 6 || dayOfWeek == 7))) {
1090 return "Ta'anis Esther";
1091 // if (ashkenaz) {
1092 // return "Ta'anis Esther";
1093 // } else {
1094 // return "Ta'anit Esther";
1095 // }
1096 }
1097 if (jewishDay == 14) {
1098 return "Purim";
1099 } else if (jewishDay == 15) {
1100 return "Shushan Purim";
1101 }
1102 }
1103 // else if a leap year //
1104 else {
1105 if (jewishDay == 14) {
1106 return "Purim Katan";
1107 }
1108 }
1109 break;
1110 case 13:
1111 // if 13th Adar falls on Friday or Shabbos, push back to Thursday
1112 if (((jewishDay == 11 || jewishDay == 12) && dayOfWeek == 5)
1113 || (jewishDay == 13 && !(dayOfWeek == 6 || dayOfWeek == 7))) {
1114 return "Ta'anis Esther";
1115 // if (ashkenaz) {
1116 // return "Ta'anis Esther";
1117 // } else {
1118 // return "Ta'anit Esther";
1119 // }
1120 }
1121 if (jewishDay == 14) {
1122 return "Purim";
1123 } else if (jewishDay == 15) {
1124 return "Shushan Purim";
1125 }
1126 break;
1127 }
1128 // if we get to this stage, then there are no holidays for the given
1129 // date
1130 // return "";
1131 return null;
1132 }
1133
1134 /**
1135 * Sets whether to use Israel parsha and holiday scheme or not. Default is
1136 * false.
1137 *
1138 * @param inIsrael
1139 * set to true for calculations for Israel
1140 */
1141 public void setInIsrael(boolean inIsrael) {
1142 this.inIsrael = inIsrael;
1143 }
1144
1145 /**
1146 * Gets whether Israel parsha and holiday scheme is used or not. The default
1147 * (if not set) is false.
1148 *
1149 * @return if the if the calendar is set to Israel
1150 */
1151 public boolean getInIsrael() {
1152 return inIsrael;
1153 }
1154
1155 // These indices were originally included in the emacs 19 distribution.
1156 // These arrays determine the correct indices into the parsha names
1157 // -1 means no parsha that week, values > 52 means it is a double parsha
1158 private static final int[] Sat_short = { -1, 52, -1, -1, 0, 1, 2, 3, 4, 5,
1159 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 53, 23, 24,
1160 -1, 25, 54, 55, 30, 56, 33, 34, 35, 36, 37, 38, 39, 40, 58, 43, 44,
1161 45, 46, 47, 48, 49, 50 };
1162
1163 private static final int[] Sat_long = { -1, 52, -1, -1, 0, 1, 2, 3, 4, 5,
1164 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 53, 23, 24,
1165 -1, 25, 54, 55, 30, 56, 33, 34, 35, 36, 37, 38, 39, 40, 58, 43, 44,
1166 45, 46, 47, 48, 49, 59 };
1167
1168 private static final int[] Mon_short = { 51, 52, -1, 0, 1, 2, 3, 4, 5, 6,
1169 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 53, 23, 24,
1170 -1, 25, 54, 55, 30, 56, 33, 34, 35, 36, 37, 38, 39, 40, 58, 43, 44,
1171 45, 46, 47, 48, 49, 59 };
1172
1173 private static final int[] Mon_long = // split
1174 { 51, 52, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
1175 18, 19, 20, 53, 23, 24, -1, 25, 54, 55, 30, 56, 33, -1, 34, 35, 36,
1176 37, 57, 40, 58, 43, 44, 45, 46, 47, 48, 49, 59 };
1177
1178 private static final int[] Thu_normal = { 52, -1, -1, 0, 1, 2, 3, 4, 5, 6,
1179 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 53, 23, 24,
1180 -1, -1, 25, 54, 55, 30, 56, 33, 34, 35, 36, 37, 38, 39, 40, 58, 43,
1181 44, 45, 46, 47, 48, 49, 50 };
1182 private static final int[] Thu_normal_Israel = { 52, -1, -1, 0, 1, 2, 3, 4,
1183 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 53, 23,
1184 24, -1, 25, 54, 55, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 58,
1185 43, 44, 45, 46, 47, 48, 49, 50 };
1186
1187 private static final int[] Thu_long = { 52, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
1188 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1189 -1, 25, 54, 55, 30, 56, 33, 34, 35, 36, 37, 38, 39, 40, 58, 43, 44,
1190 45, 46, 47, 48, 49, 50 };
1191
1192 private static final int[] Sat_short_leap = { -1, 52, -1, -1, 0, 1, 2, 3,
1193 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
1194 22, 23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
1195 38, 39, 40, 58, 43, 44, 45, 46, 47, 48, 49, 59 };
1196
1197 private static final int[] Sat_long_leap = { -1, 52, -1, -1, 0, 1, 2, 3, 4,
1198 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
1199 23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, -1, 34, 35, 36, 37,
1200 57, 40, 58, 43, 44, 45, 46, 47, 48, 49, 59 };
1201
1202 private static final int[] Mon_short_leap = { 51, 52, -1, 0, 1, 2, 3, 4, 5,
1203 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1204 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, -1, 34, 35, 36, 37, 57,
1205 40, 58, 43, 44, 45, 46, 47, 48, 49, 59 };
1206 private static final int[] Mon_short_leap_Israel = { 51, 52, -1, 0, 1, 2,
1207 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
1208 21, 22, 23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36,
1209 37, 38, 39, 40, 58, 43, 44, 45, 46, 47, 48, 49, 59 };
1210
1211 private static final int[] Mon_long_leap = { 51, 52, -1, 0, 1, 2, 3, 4, 5,
1212 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1213 24, 25, 26, 27, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
1214 39, 40, 58, 43, 44, 45, 46, 47, 48, 49, 50 };
1215 private static final int[] Mon_long_leap_Israel = { 51, 52, -1, 0, 1, 2, 3,
1216 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
1217 22, 23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
1218 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 };
1219
1220 private static final int[] Thu_short_leap = { 52, -1, -1, 0, 1, 2, 3, 4, 5,
1221 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1222 24, 25, 26, 27, 28, -1, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
1223 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 };
1224
1225 private static final int[] Thu_long_leap = { 52, -1, -1, 0, 1, 2, 3, 4, 5,
1226 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1227 24, 25, 26, 27, 28, -1, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
1228 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 59 };
1229
1230 /**
1231 * returns a string of today's parsha(ios) or an empty string if there are
1232 * none. FIXME: consider possibly return the parsha of the week for any day
1233 * during the week instead of empty. To do this the simple way, create a new
1234 * instance of the class in the mothod, roll it to the next shabbos. If the
1235 * shabbos has no parsha, keep rolling by a week till a parsha is
1236 * encountered. Possibly turn into static method that takes in a year,
1237 * month, day, roll to next shabbos (not that simple with the API for date
1238 * passed in) and if it is not a shabbos roll forwarde one week at a time to
1239 * get the parsha. I do not think it is possible to have more than 2
1240 * shabbosim in a row without a parsha, but I may be wrong.
1241 *
1242 * @return the string of the parsha. Will currently return blank for
1243 * weekdays and a shabbos on a yom tov.
1244 */
1245 public String getParsha() {
1246
1247 // if today is not Shabbos, then there is no normal parsha reading. If
1248 // commented our will return LAST week's parsha for a non shabbos
1249 if (getDayOfWeek() != 7) {
1250 return "";
1251 }
1252
1253 // kvia = whether a Jewish year is short/regular/long (0/1/2)
1254 // roshHashana = Rosh Hashana of this Jewish year
1255 // roshHashanaDay= day of week Rosh Hashana was on this year
1256 // week= current week in Jewish calendar from Rosh Hashana
1257 // array= the correct index array for this Jewish year
1258 // index= the index number of the parsha name
1259 int kvia;
1260 int roshHashanaDay;
1261 int week;
1262 int[] array = null;
1263 int index;
1264 // create a clone of this date
1265 JewishDate roshHashana = (JewishDate) this.clone();
1266 // try {
1267 // set it to Rosh Hashana of this year
1268 roshHashana.setJewishDate(jewishYear, 7, 1);
1269 // } catch (IllegalArgumentException e) {
1270 // e.printStackTrace();
1271 // }
1272
1273 // get day Rosh Hashana was on
1274 roshHashanaDay = roshHashana.getDayOfWeek();
1275
1276 // week is the week since the first Shabbos on or after Rosh Hashana
1277 week = (((gregorianAbsDate - roshHashana.getAbsDate()) - (7 - roshHashanaDay)) / 7);
1278
1279 // get kvia
1280 if (isCheshvanLong(jewishYear) && !isKislevShort(jewishYear))
1281 kvia = 2;
1282 else if (!isCheshvanLong(jewishYear) && isKislevShort(jewishYear))
1283 kvia = 0;
1284 else
1285 kvia = 1;
1286
1287 // determine appropriate array
1288 if (!isJewishLeapYear(jewishYear)) {
1289 switch (roshHashanaDay) {
1290 case 7: // RH was on a Saturday
1291 if (kvia == 0)
1292 array = Sat_short;
1293 else if (kvia == 2)
1294 array = Sat_long;
1295 break;
1296 case 2: // RH was on a Monday
1297 if (kvia == 0)
1298 array = Mon_short;
1299 else if (kvia == 2)
1300 array = inIsrael ? Mon_short : Mon_long;
1301 break;
1302 case 3: // RH was on a Tuesday
1303 if (kvia == 1)
1304 array = inIsrael ? Mon_short : Mon_long;
1305 break;
1306 case 5: // RH was on a Thursday
1307 if (kvia == 1)
1308 array = inIsrael ? Thu_normal_Israel : Thu_normal;
1309 else if (kvia == 2)
1310 array = Thu_long;
1311 break;
1312 }
1313 }
1314
1315 // if leap year //
1316 else {
1317 switch (roshHashanaDay) {
1318 case 7: // RH was on a Sat
1319 if (kvia == 0)
1320 array = Sat_short_leap;
1321 else if (kvia == 2)
1322 array = inIsrael ? Sat_short_leap : Sat_long_leap;
1323 break;
1324 case 2: // RH was on a Mon
1325 if (kvia == 0)
1326 array = inIsrael ? Mon_short_leap_Israel : Mon_short_leap;
1327 else if (kvia == 2)
1328 array = inIsrael ? Mon_long_leap_Israel : Mon_long_leap;
1329 break;
1330 case 3: // RH was on a Tue
1331 if (kvia == 1)
1332 array = inIsrael ? Mon_long_leap_Israel : Mon_long_leap;
1333 break;
1334 case 5: // RH was on a Thu
1335 if (kvia == 0)
1336 array = Thu_short_leap;
1337 else if (kvia == 2)
1338 array = Thu_long_leap;
1339 break;
1340 }
1341 }
1342 // if something goes wrong
1343 if (array == null) {
1344 throw new RuntimeException(
1345 "Unable to claculate the parsha. No index array matched any of the known types for the date: "
1346 + toString());
1347 }
1348 // get index from array
1349 index = array[week];
1350
1351 // If no Parsha this week
1352 if (index == -1) {
1353 return "";
1354 }
1355
1356 // if parsha this week
1357 // else {
1358 // if (getDayOfWeek() != 7){//in weekday return next shabbos's parsha
1359 // System.out.print(" index=" + index + " ");
1360 // return parshios[index + 1];
1361 // this code returns odd data for yom tov. See parshas kedoshim display
1362 // for 2011 for example. It will also break for Sept 25, 2011 where it
1363 // goes one beyong the index of Nitzavim-Vayelech
1364 // }
1365 return parshios[index];
1366 // }
1367 }
1368
1369 /** Create a copy of this date. */
1370 // FIXME - create deep clone
1371 public Object clone() {
1372 return new JewishDate(gregorianYear, gregorianMonth,
1373 gregorianDayOfMonth);
1374 }
1375
1376 /**
1377 * @see java.lang.Object#hashCode()
1378 */
1379 public int hashCode() {
1380 int result = 17;
1381 result = 37 * result + getClass().hashCode(); // needed or this and
1382 // subclasses will
1383 // return identical hash
1384 result += 37 * result + gregorianAbsDate;
1385 return result;
1386 }
1387 }