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 }