001/*
002 * Zmanim Java API
003 * Copyright (C) 2011 - 2024 Eliyahu Hershfeld
004 *
005 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
006 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
007 * any later version.
008 *
009 * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
010 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
011 * details.
012 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
013 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA,
014 * or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
015 */
016package com.kosherjava.zmanim.hebrewcalendar;
017
018import java.text.SimpleDateFormat;
019import java.util.EnumMap;
020
021/**
022 * The HebrewDateFormatter class formats a {@link JewishDate}.
023 * 
024 * The class formats Jewish dates, numbers, <em>Daf Yomi</em> (<em>Bavli</em> and <em>Yerushalmi</em>), the <em>Omer</em>,
025 * <em>Parshas Hashavua</em> (including the special <em>parshiyos</em> of <em>Shekalim</em>, <em>Zachor</em>, <em>Parah</em>
026 * and <em>Hachodesh</em>), Yomim Tovim and the Molad (experimental) in Hebrew or Latin chars, and has various settings.
027 * Sample full date output includes (using various options):
028 * <ul>
029 * <li>21 Shevat, 5729</li>
030 * <li>&#x5DB;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DB;&#x5D8;</li>
031 * <li>&#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5D4;&#x5F3;&#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;</li>
032 * <li>&#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x05E4; or
033 * &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x05E3;</li>
034 * <li>&#x05DB;&#x05F3; &#x05E9;&#x05D1;&#x05D8; &#x05D5;&#x05F3; &#x05D0;&#x05DC;&#x05E4;&#x05D9;&#x05DD;</li>
035 * </ul>
036 * 
037 * @see JewishDate
038 * @see JewishCalendar
039 * 
040 * @author &copy; Eliyahu Hershfeld 2011 - 2024
041 */
042public class HebrewDateFormatter {
043        
044        /**
045         * See {@link #isHebrewFormat()} and {@link #setHebrewFormat(boolean)}.
046         */
047        private boolean hebrewFormat = false;
048        
049        /**
050         * See {@link #isUseLongHebrewYears()} and {@link #setUseLongHebrewYears(boolean)}.
051         */
052        private boolean useLonghebrewYears = false;
053        
054        /**
055         * See {@link #isUseGershGershayim()} and {@link #setUseGershGershayim(boolean)}.
056         */
057        private boolean useGershGershayim = true;
058        
059        /**
060         * See {@link #isLongWeekFormat()} and {@link #setLongWeekFormat(boolean)}.
061         */
062        private boolean longWeekFormat = true;
063        
064        /**
065         * See {@link #isUseFinalFormLetters()} and {@link #setUseFinalFormLetters(boolean)}.
066         */
067        private boolean useFinalFormLetters = false;
068        
069        /**
070         * The internal DateFormat.&nbsp; See {@link #isLongWeekFormat()} and {@link #setLongWeekFormat(boolean)}.
071         */
072        private SimpleDateFormat weekFormat = null;
073        
074        /**
075         * List of transliterated parshiyos using the default <em>Ashkenazi</em> pronunciation.&nbsp; The formatParsha method
076         * uses this for transliterated <em>parsha</em> formatting.&nbsp; This list can be overridden (for <em>Sephardi</em>
077         * English transliteration for example) by setting the {@link #setTransliteratedParshiosList(EnumMap)}.&nbsp; The list
078         * includes double and special <em>parshiyos</em> is set as "<em>Bereshis, Noach, Lech Lecha, Vayera, Chayei Sara,
079         * Toldos, Vayetzei, Vayishlach, Vayeshev, Miketz, Vayigash, Vayechi, Shemos, Vaera, Bo, Beshalach, Yisro, Mishpatim,
080         * Terumah, Tetzaveh, Ki Sisa, Vayakhel, Pekudei, Vayikra, Tzav, Shmini, Tazria, Metzora, Achrei Mos, Kedoshim, Emor,
081         * Behar, Bechukosai, Bamidbar, Nasso, Beha'aloscha, Sh'lach, Korach, Chukas, Balak, Pinchas, Matos, Masei, Devarim,
082         * Vaeschanan, Eikev, Re'eh, Shoftim, Ki Seitzei, Ki Savo, Nitzavim, Vayeilech, Ha'Azinu, Vezos Habracha,
083         * Vayakhel Pekudei, Tazria Metzora, Achrei Mos Kedoshim, Behar Bechukosai, Chukas Balak, Matos Masei, Nitzavim Vayeilech,
084         * Shekalim, Zachor, Parah, Hachodesh,Shuva, Shira, Hagadol, Chazon, Nachamu</em>".
085         * 
086         * @see #formatParsha(JewishCalendar)
087         */
088        private EnumMap<JewishCalendar.Parsha, String> transliteratedParshaMap;
089        
090        /**
091         * Unicode {@link EnumMap} of Hebrew <em>parshiyos</em>.&nbsp; The list includes double and special <em>parshiyos</em> and
092         * contains <code>"&#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA;, &#x05E0;&#x05D7;, &#x05DC;&#x05DA; &#x05DC;&#x05DA;,
093         *  &#x05D5;&#x05D9;&#x05E8;&#x05D0;, &#x05D7;&#x05D9;&#x05D9; &#x05E9;&#x05E8;&#x05D4;,
094         *  &#x05EA;&#x05D5;&#x05DC;&#x05D3;&#x05D5;&#x05EA;, &#x05D5;&#x05D9;&#x05E6;&#x05D0;, &#x05D5;&#x05D9;&#x05E9;&#x05DC;&#x05D7;,
095         *  &#x05D5;&#x05D9;&#x05E9;&#x05D1;, &#x05DE;&#x05E7;&#x05E5;, &#x05D5;&#x05D9;&#x05D2;&#x05E9;, &#x05D5;&#x05D9;&#x05D7;&#x05D9;,
096         *  &#x05E9;&#x05DE;&#x05D5;&#x05EA;, &#x05D5;&#x05D0;&#x05E8;&#x05D0;, &#x05D1;&#x05D0;, &#x05D1;&#x05E9;&#x05DC;&#x05D7;,
097         *  &#x05D9;&#x05EA;&#x05E8;&#x05D5;, &#x05DE;&#x05E9;&#x05E4;&#x05D8;&#x05D9;&#x05DD;, &#x05EA;&#x05E8;&#x05D5;&#x05DE;&#x05D4;,
098         *  &#x05EA;&#x05E6;&#x05D5;&#x05D4;, &#x05DB;&#x05D9; &#x05EA;&#x05E9;&#x05D0;, &#x05D5;&#x05D9;&#x05E7;&#x05D4;&#x05DC;,
099         *  &#x05E4;&#x05E7;&#x05D5;&#x05D3;&#x05D9;, &#x05D5;&#x05D9;&#x05E7;&#x05E8;&#x05D0;, &#x05E6;&#x05D5;,
100         *  &#x05E9;&#x05DE;&#x05D9;&#x05E0;&#x05D9;, &#x05EA;&#x05D6;&#x05E8;&#x05D9;&#x05E2;, &#x05DE;&#x05E6;&#x05E8;&#x05E2;,
101         *  &#x05D0;&#x05D7;&#x05E8;&#x05D9; &#x05DE;&#x05D5;&#x05EA;, &#x05E7;&#x05D3;&#x05D5;&#x05E9;&#x05D9;&#x05DD;,
102         *  &#x05D0;&#x05DE;&#x05D5;&#x05E8;, &#x05D1;&#x05D4;&#x05E8;, &#x05D1;&#x05D7;&#x05E7;&#x05EA;&#x05D9;,
103         *  &#x05D1;&#x05DE;&#x05D3;&#x05D1;&#x05E8;, &#x05E0;&#x05E9;&#x05D0;, &#x05D1;&#x05D4;&#x05E2;&#x05DC;&#x05EA;&#x05DA;,
104         *  &#x05E9;&#x05DC;&#x05D7; &#x05DC;&#x05DA;, &#x05E7;&#x05E8;&#x05D7;, &#x05D7;&#x05D5;&#x05E7;&#x05EA;, &#x05D1;&#x05DC;&#x05E7;,
105         *  &#x05E4;&#x05D9;&#x05E0;&#x05D7;&#x05E1;, &#x05DE;&#x05D8;&#x05D5;&#x05EA;, &#x05DE;&#x05E1;&#x05E2;&#x05D9;,
106         *  &#x05D3;&#x05D1;&#x05E8;&#x05D9;&#x05DD;, &#x05D5;&#x05D0;&#x05EA;&#x05D7;&#x05E0;&#x05DF;, &#x05E2;&#x05E7;&#x05D1;,
107         *  &#x05E8;&#x05D0;&#x05D4;, &#x05E9;&#x05D5;&#x05E4;&#x05D8;&#x05D9;&#x05DD;, &#x05DB;&#x05D9; &#x05EA;&#x05E6;&#x05D0;,
108         *  &#x05DB;&#x05D9; &#x05EA;&#x05D1;&#x05D5;&#x05D0;, &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD;, &#x05D5;&#x05D9;&#x05DC;&#x05DA;,
109         *  &#x05D4;&#x05D0;&#x05D6;&#x05D9;&#x05E0;&#x05D5;, &#x05D5;&#x05D6;&#x05D0;&#x05EA; &#x05D4;&#x05D1;&#x05E8;&#x05DB;&#x05D4;,
110         *  &#x05D5;&#x05D9;&#x05E7;&#x05D4;&#x05DC; &#x05E4;&#x05E7;&#x05D5;&#x05D3;&#x05D9;, &#x05EA;&#x05D6;&#x05E8;&#x05D9;&#x05E2;
111         *  &#x05DE;&#x05E6;&#x05E8;&#x05E2;, &#x05D0;&#x05D7;&#x05E8;&#x05D9; &#x05DE;&#x05D5;&#x05EA;
112         *  &#x05E7;&#x05D3;&#x05D5;&#x05E9;&#x05D9;&#x05DD;, &#x05D1;&#x05D4;&#x05E8; &#x05D1;&#x05D7;&#x05E7;&#x05EA;&#x05D9;,
113         *  &#x05D7;&#x05D5;&#x05E7;&#x05EA; &#x05D1;&#x05DC;&#x05E7;, &#x05DE;&#x05D8;&#x05D5;&#x05EA; &#x05DE;&#x05E1;&#x05E2;&#x05D9;,
114         *  &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA;, &#x05E9;&#x05E7;&#x05DC;&#x05D9;&#x05DD;,
115         *  &#x05D6;&#x05DB;&#x05D5;&#x05E8;, &#x05E4;&#x05E8;&#x05D4;, &#x05D4;&#x05D7;&#x05D3;&#x05E9;,
116         *  &#x05E9;&#x05D5;&#x05D1;&#x05D4;,&#x05E9;&#x05D9;&#x05E8;&#x05D4;,&#x05D4;&#x05D2;&#x05D3;&#x05D5;&#x05DC;,
117         *  &#x05D7;&#x05D6;&#x05D5;&#x05DF;,&#x05E0;&#x05D7;&#x05DE;&#x05D5;"</code>
118         */
119        private final EnumMap<JewishCalendar.Parsha, String> hebrewParshaMap;
120        
121        /**
122         * Default constructor sets the {@link EnumMap}s of Hebrew and default transliterated parshiyos.
123         */
124        public HebrewDateFormatter() {
125                weekFormat = new SimpleDateFormat("EEEE");
126                transliteratedParshaMap = new EnumMap<>(JewishCalendar.Parsha.class);
127                transliteratedParshaMap.put(JewishCalendar.Parsha.NONE, "");
128                transliteratedParshaMap.put(JewishCalendar.Parsha.BERESHIS, "Bereshis");
129                transliteratedParshaMap.put(JewishCalendar.Parsha.NOACH, "Noach");
130                transliteratedParshaMap.put(JewishCalendar.Parsha.LECH_LECHA, "Lech Lecha");
131                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYERA, "Vayera");
132                transliteratedParshaMap.put(JewishCalendar.Parsha.CHAYEI_SARA, "Chayei Sara");
133                transliteratedParshaMap.put(JewishCalendar.Parsha.TOLDOS, "Toldos");
134                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYETZEI, "Vayetzei");
135                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYISHLACH, "Vayishlach");
136                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYESHEV, "Vayeshev");
137                transliteratedParshaMap.put(JewishCalendar.Parsha.MIKETZ, "Miketz");
138                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYIGASH, "Vayigash");
139                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYECHI, "Vayechi");
140                transliteratedParshaMap.put(JewishCalendar.Parsha.SHEMOS, "Shemos");
141                transliteratedParshaMap.put(JewishCalendar.Parsha.VAERA, "Vaera");
142                transliteratedParshaMap.put(JewishCalendar.Parsha.BO, "Bo");
143                transliteratedParshaMap.put(JewishCalendar.Parsha.BESHALACH, "Beshalach");
144                transliteratedParshaMap.put(JewishCalendar.Parsha.YISRO, "Yisro");
145                transliteratedParshaMap.put(JewishCalendar.Parsha.MISHPATIM, "Mishpatim");
146                transliteratedParshaMap.put(JewishCalendar.Parsha.TERUMAH, "Terumah");
147                transliteratedParshaMap.put(JewishCalendar.Parsha.TETZAVEH, "Tetzaveh");
148                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SISA, "Ki Sisa");
149                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYAKHEL, "Vayakhel");
150                transliteratedParshaMap.put(JewishCalendar.Parsha.PEKUDEI, "Pekudei");
151                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYIKRA, "Vayikra");
152                transliteratedParshaMap.put(JewishCalendar.Parsha.TZAV, "Tzav");
153                transliteratedParshaMap.put(JewishCalendar.Parsha.SHMINI, "Shmini");
154                transliteratedParshaMap.put(JewishCalendar.Parsha.TAZRIA, "Tazria");
155                transliteratedParshaMap.put(JewishCalendar.Parsha.METZORA, "Metzora");
156                transliteratedParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS, "Achrei Mos");
157                transliteratedParshaMap.put(JewishCalendar.Parsha.KEDOSHIM, "Kedoshim");
158                transliteratedParshaMap.put(JewishCalendar.Parsha.EMOR, "Emor");
159                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAR, "Behar");
160                transliteratedParshaMap.put(JewishCalendar.Parsha.BECHUKOSAI, "Bechukosai");
161                transliteratedParshaMap.put(JewishCalendar.Parsha.BAMIDBAR, "Bamidbar");
162                transliteratedParshaMap.put(JewishCalendar.Parsha.NASSO, "Nasso");
163                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAALOSCHA, "Beha'aloscha");
164                transliteratedParshaMap.put(JewishCalendar.Parsha.SHLACH, "Sh'lach");
165                transliteratedParshaMap.put(JewishCalendar.Parsha.KORACH, "Korach");
166                transliteratedParshaMap.put(JewishCalendar.Parsha.CHUKAS, "Chukas");
167                transliteratedParshaMap.put(JewishCalendar.Parsha.BALAK, "Balak");
168                transliteratedParshaMap.put(JewishCalendar.Parsha.PINCHAS, "Pinchas");
169                transliteratedParshaMap.put(JewishCalendar.Parsha.MATOS, "Matos");
170                transliteratedParshaMap.put(JewishCalendar.Parsha.MASEI, "Masei");
171                transliteratedParshaMap.put(JewishCalendar.Parsha.DEVARIM, "Devarim");
172                transliteratedParshaMap.put(JewishCalendar.Parsha.VAESCHANAN, "Vaeschanan");
173                transliteratedParshaMap.put(JewishCalendar.Parsha.EIKEV, "Eikev");
174                transliteratedParshaMap.put(JewishCalendar.Parsha.REEH, "Re'eh");
175                transliteratedParshaMap.put(JewishCalendar.Parsha.SHOFTIM, "Shoftim");
176                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SEITZEI, "Ki Seitzei");
177                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SAVO, "Ki Savo");
178                transliteratedParshaMap.put(JewishCalendar.Parsha.NITZAVIM, "Nitzavim");
179                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYEILECH, "Vayeilech");
180                transliteratedParshaMap.put(JewishCalendar.Parsha.HAAZINU, "Ha'Azinu");
181                transliteratedParshaMap.put(JewishCalendar.Parsha.VZOS_HABERACHA, "Vezos Habracha");
182                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYAKHEL_PEKUDEI, "Vayakhel Pekudei");
183                transliteratedParshaMap.put(JewishCalendar.Parsha.TAZRIA_METZORA, "Tazria Metzora");
184                transliteratedParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS_KEDOSHIM, "Achrei Mos Kedoshim");
185                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAR_BECHUKOSAI, "Behar Bechukosai");
186                transliteratedParshaMap.put(JewishCalendar.Parsha.CHUKAS_BALAK, "Chukas Balak");
187                transliteratedParshaMap.put(JewishCalendar.Parsha.MATOS_MASEI, "Matos Masei");
188                transliteratedParshaMap.put(JewishCalendar.Parsha.NITZAVIM_VAYEILECH, "Nitzavim Vayeilech");
189                transliteratedParshaMap.put(JewishCalendar.Parsha.SHKALIM, "Shekalim");
190                transliteratedParshaMap.put(JewishCalendar.Parsha.ZACHOR, "Zachor");
191                transliteratedParshaMap.put(JewishCalendar.Parsha.PARA, "Parah");
192                transliteratedParshaMap.put(JewishCalendar.Parsha.HACHODESH, "Hachodesh");
193                transliteratedParshaMap.put(JewishCalendar.Parsha.SHUVA, "Shuva");
194                transliteratedParshaMap.put(JewishCalendar.Parsha.SHIRA, "Shira");
195                transliteratedParshaMap.put(JewishCalendar.Parsha.HAGADOL, "Hagadol");
196                transliteratedParshaMap.put(JewishCalendar.Parsha.CHAZON, "Chazon");
197                transliteratedParshaMap.put(JewishCalendar.Parsha.NACHAMU, "Nachamu");
198                
199                hebrewParshaMap = new EnumMap<>(JewishCalendar.Parsha.class);
200                hebrewParshaMap.put(JewishCalendar.Parsha.NONE, "");
201                hebrewParshaMap.put(JewishCalendar.Parsha.BERESHIS, "\u05D1\u05E8\u05D0\u05E9\u05D9\u05EA");
202                hebrewParshaMap.put(JewishCalendar.Parsha.NOACH, "\u05E0\u05D7");
203                hebrewParshaMap.put(JewishCalendar.Parsha.LECH_LECHA, "\u05DC\u05DA \u05DC\u05DA");
204                hebrewParshaMap.put(JewishCalendar.Parsha.VAYERA, "\u05D5\u05D9\u05E8\u05D0");
205                hebrewParshaMap.put(JewishCalendar.Parsha.CHAYEI_SARA, "\u05D7\u05D9\u05D9 \u05E9\u05E8\u05D4");
206                hebrewParshaMap.put(JewishCalendar.Parsha.TOLDOS, "\u05EA\u05D5\u05DC\u05D3\u05D5\u05EA");
207                hebrewParshaMap.put(JewishCalendar.Parsha.VAYETZEI, "\u05D5\u05D9\u05E6\u05D0");
208                hebrewParshaMap.put(JewishCalendar.Parsha.VAYISHLACH, "\u05D5\u05D9\u05E9\u05DC\u05D7");
209                hebrewParshaMap.put(JewishCalendar.Parsha.VAYESHEV, "\u05D5\u05D9\u05E9\u05D1");
210                hebrewParshaMap.put(JewishCalendar.Parsha.MIKETZ, "\u05DE\u05E7\u05E5");
211                hebrewParshaMap.put(JewishCalendar.Parsha.VAYIGASH, "\u05D5\u05D9\u05D2\u05E9");
212                hebrewParshaMap.put(JewishCalendar.Parsha.VAYECHI, "\u05D5\u05D9\u05D7\u05D9");
213                hebrewParshaMap.put(JewishCalendar.Parsha.SHEMOS, "\u05E9\u05DE\u05D5\u05EA");
214                hebrewParshaMap.put(JewishCalendar.Parsha.VAERA, "\u05D5\u05D0\u05E8\u05D0");
215                hebrewParshaMap.put(JewishCalendar.Parsha.BO, "\u05D1\u05D0");
216                hebrewParshaMap.put(JewishCalendar.Parsha.BESHALACH, "\u05D1\u05E9\u05DC\u05D7");
217                hebrewParshaMap.put(JewishCalendar.Parsha.YISRO, "\u05D9\u05EA\u05E8\u05D5");
218                hebrewParshaMap.put(JewishCalendar.Parsha.MISHPATIM, "\u05DE\u05E9\u05E4\u05D8\u05D9\u05DD");
219                hebrewParshaMap.put(JewishCalendar.Parsha.TERUMAH, "\u05EA\u05E8\u05D5\u05DE\u05D4");
220                hebrewParshaMap.put(JewishCalendar.Parsha.TETZAVEH, "\u05EA\u05E6\u05D5\u05D4");
221                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SISA, "\u05DB\u05D9 \u05EA\u05E9\u05D0");
222                hebrewParshaMap.put(JewishCalendar.Parsha.VAYAKHEL, "\u05D5\u05D9\u05E7\u05D4\u05DC");
223                hebrewParshaMap.put(JewishCalendar.Parsha.PEKUDEI, "\u05E4\u05E7\u05D5\u05D3\u05D9");
224                hebrewParshaMap.put(JewishCalendar.Parsha.VAYIKRA, "\u05D5\u05D9\u05E7\u05E8\u05D0");
225                hebrewParshaMap.put(JewishCalendar.Parsha.TZAV, "\u05E6\u05D5");
226                hebrewParshaMap.put(JewishCalendar.Parsha.SHMINI, "\u05E9\u05DE\u05D9\u05E0\u05D9");
227                hebrewParshaMap.put(JewishCalendar.Parsha.TAZRIA, "\u05EA\u05D6\u05E8\u05D9\u05E2");
228                hebrewParshaMap.put(JewishCalendar.Parsha.METZORA, "\u05DE\u05E6\u05E8\u05E2");
229                hebrewParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS, "\u05D0\u05D7\u05E8\u05D9 \u05DE\u05D5\u05EA");
230                hebrewParshaMap.put(JewishCalendar.Parsha.KEDOSHIM, "\u05E7\u05D3\u05D5\u05E9\u05D9\u05DD");
231                hebrewParshaMap.put(JewishCalendar.Parsha.EMOR, "\u05D0\u05DE\u05D5\u05E8");
232                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAR, "\u05D1\u05D4\u05E8");
233                hebrewParshaMap.put(JewishCalendar.Parsha.BECHUKOSAI, "\u05D1\u05D7\u05E7\u05EA\u05D9");
234                hebrewParshaMap.put(JewishCalendar.Parsha.BAMIDBAR, "\u05D1\u05DE\u05D3\u05D1\u05E8");
235                hebrewParshaMap.put(JewishCalendar.Parsha.NASSO, "\u05E0\u05E9\u05D0");
236                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAALOSCHA, "\u05D1\u05D4\u05E2\u05DC\u05EA\u05DA");
237                hebrewParshaMap.put(JewishCalendar.Parsha.SHLACH, "\u05E9\u05DC\u05D7 \u05DC\u05DA");
238                hebrewParshaMap.put(JewishCalendar.Parsha.KORACH, "\u05E7\u05E8\u05D7");
239                hebrewParshaMap.put(JewishCalendar.Parsha.CHUKAS, "\u05D7\u05D5\u05E7\u05EA");
240                hebrewParshaMap.put(JewishCalendar.Parsha.BALAK, "\u05D1\u05DC\u05E7");
241                hebrewParshaMap.put(JewishCalendar.Parsha.PINCHAS, "\u05E4\u05D9\u05E0\u05D7\u05E1");
242                hebrewParshaMap.put(JewishCalendar.Parsha.MATOS, "\u05DE\u05D8\u05D5\u05EA");
243                hebrewParshaMap.put(JewishCalendar.Parsha.MASEI, "\u05DE\u05E1\u05E2\u05D9");
244                hebrewParshaMap.put(JewishCalendar.Parsha.DEVARIM, "\u05D3\u05D1\u05E8\u05D9\u05DD");
245                hebrewParshaMap.put(JewishCalendar.Parsha.VAESCHANAN, "\u05D5\u05D0\u05EA\u05D7\u05E0\u05DF");
246                hebrewParshaMap.put(JewishCalendar.Parsha.EIKEV, "\u05E2\u05E7\u05D1");
247                hebrewParshaMap.put(JewishCalendar.Parsha.REEH, "\u05E8\u05D0\u05D4");
248                hebrewParshaMap.put(JewishCalendar.Parsha.SHOFTIM, "\u05E9\u05D5\u05E4\u05D8\u05D9\u05DD");
249                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SEITZEI, "\u05DB\u05D9 \u05EA\u05E6\u05D0");
250                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SAVO, "\u05DB\u05D9 \u05EA\u05D1\u05D5\u05D0");
251                hebrewParshaMap.put(JewishCalendar.Parsha.NITZAVIM, "\u05E0\u05E6\u05D1\u05D9\u05DD");
252                hebrewParshaMap.put(JewishCalendar.Parsha.VAYEILECH, "\u05D5\u05D9\u05DC\u05DA");
253                hebrewParshaMap.put(JewishCalendar.Parsha.HAAZINU, "\u05D4\u05D0\u05D6\u05D9\u05E0\u05D5");
254                hebrewParshaMap.put(JewishCalendar.Parsha.VZOS_HABERACHA, "\u05D5\u05D6\u05D0\u05EA \u05D4\u05D1\u05E8\u05DB\u05D4 ");
255                hebrewParshaMap.put(JewishCalendar.Parsha.VAYAKHEL_PEKUDEI, "\u05D5\u05D9\u05E7\u05D4\u05DC \u05E4\u05E7\u05D5\u05D3\u05D9");
256                hebrewParshaMap.put(JewishCalendar.Parsha.TAZRIA_METZORA, "\u05EA\u05D6\u05E8\u05D9\u05E2 \u05DE\u05E6\u05E8\u05E2");
257                hebrewParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS_KEDOSHIM, "\u05D0\u05D7\u05E8\u05D9 \u05DE\u05D5\u05EA \u05E7\u05D3\u05D5\u05E9\u05D9\u05DD");
258                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAR_BECHUKOSAI, "\u05D1\u05D4\u05E8 \u05D1\u05D7\u05E7\u05EA\u05D9");
259                hebrewParshaMap.put(JewishCalendar.Parsha.CHUKAS_BALAK, "\u05D7\u05D5\u05E7\u05EA \u05D1\u05DC\u05E7");
260                hebrewParshaMap.put(JewishCalendar.Parsha.MATOS_MASEI, "\u05DE\u05D8\u05D5\u05EA \u05DE\u05E1\u05E2\u05D9");
261                hebrewParshaMap.put(JewishCalendar.Parsha.NITZAVIM_VAYEILECH, "\u05E0\u05E6\u05D1\u05D9\u05DD \u05D5\u05D9\u05DC\u05DA");
262                hebrewParshaMap.put(JewishCalendar.Parsha.SHKALIM, "\u05E9\u05E7\u05DC\u05D9\u05DD");
263                hebrewParshaMap.put(JewishCalendar.Parsha.ZACHOR, "\u05D6\u05DB\u05D5\u05E8");
264                hebrewParshaMap.put(JewishCalendar.Parsha.PARA, "\u05E4\u05E8\u05D4");
265                hebrewParshaMap.put(JewishCalendar.Parsha.HACHODESH, "\u05D4\u05D7\u05D3\u05E9");
266                hebrewParshaMap.put(JewishCalendar.Parsha.SHUVA, "\u05E9\u05D5\u05D1\u05D4");
267                hebrewParshaMap.put(JewishCalendar.Parsha.SHIRA, "\u05E9\u05D9\u05E8\u05D4");
268                hebrewParshaMap.put(JewishCalendar.Parsha.HAGADOL, "\u05D4\u05D2\u05D3\u05D5\u05DC");
269                hebrewParshaMap.put(JewishCalendar.Parsha.CHAZON, "\u05D7\u05D6\u05D5\u05DF");
270                hebrewParshaMap.put(JewishCalendar.Parsha.NACHAMU, "\u05E0\u05D7\u05DE\u05D5");
271        }
272
273        /**
274         * Returns if the {@link #formatDayOfWeek(JewishDate)} will use the long format such as
275         * &#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF; or short such as &#x05D0; when formatting the day of week in
276         * {@link #isHebrewFormat() Hebrew}.
277         * 
278         * @return the longWeekFormat
279         * @see #setLongWeekFormat(boolean)
280         * @see #formatDayOfWeek(JewishDate)
281         */
282        public boolean isLongWeekFormat() {
283                return longWeekFormat;
284        }
285
286        /**
287         * Setting to control if the {@link #formatDayOfWeek(JewishDate)} will use the long format such as
288         * &#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF; or short such as &#x05D0; when formatting the day of week in
289         * {@link #isHebrewFormat() Hebrew}.
290         * 
291         * @param longWeekFormat
292         *            the longWeekFormat to set
293         */
294        public void setLongWeekFormat(boolean longWeekFormat) {
295                this.longWeekFormat = longWeekFormat;
296                if (longWeekFormat) {
297                        weekFormat = new SimpleDateFormat("EEEE");
298                } else {
299                        weekFormat = new SimpleDateFormat("EEE");
300                }
301        }
302
303        /**
304         * The <a href="https://en.wikipedia.org/wiki/Geresh#Punctuation_mark">gersh</a> character is the &#x05F3; char
305         * that is similar to a single quote and is used in formatting Hebrew numbers.
306         */
307        private static final String GERESH = "\u05F3";
308        
309        /**
310         * The <a href="https://en.wikipedia.org/wiki/Gershayim#Punctuation_mark">gershyim</a> character is the &#x05F4; char
311         * that is similar to a double quote and is used in formatting Hebrew numbers.
312         */
313        private static final String GERSHAYIM = "\u05F4";
314        
315        /**
316         * Transliterated month names.&nbsp; Defaults to ["Nissan", "Iyar", "Sivan", "Tammuz", "Av", "Elul", "Tishrei", "Cheshvan",
317         * "Kislev", "Teves", "Shevat", "Adar", "Adar II", "Adar I" ].
318         * @see #getTransliteratedMonthList()
319         * @see #setTransliteratedMonthList(String[])
320         */
321        private String[] transliteratedMonths = { "Nissan", "Iyar", "Sivan", "Tammuz", "Av", "Elul", "Tishrei", "Cheshvan",
322                        "Kislev", "Teves", "Shevat", "Adar", "Adar II", "Adar I" };
323        
324        /**
325         * The Hebrew omer prefix charachter. It defaults to &#x05D1; producing &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;,
326         * but can be set to &#x05DC; to produce &#x05DC;&#x05E2;&#x05D5;&#x05DE;&#x05E8; (or any other prefix).
327         * @see #getHebrewOmerPrefix()
328         * @see #setHebrewOmerPrefix(String)
329         */
330        private String hebrewOmerPrefix = "\u05D1";
331
332        /**
333         * The default value for formatting Shabbos (Saturday).&nbsp; Defaults to Shabbos.
334         * @see #getTransliteratedShabbosDayOfWeek()
335         * @see #setTransliteratedShabbosDayOfWeek(String)
336         */
337        private String transliteratedShabbosDayOfWeek = "Shabbos";
338
339        /**
340         * Returns the day of Shabbos transliterated into Latin chars. The default uses Ashkenazi pronunciation "Shabbos".
341         * This can be overwritten using the {@link #setTransliteratedShabbosDayOfWeek(String)}
342         * 
343         * @return the transliteratedShabbos. The default list of months uses Ashkenazi pronunciation "Shabbos".
344         * @see #setTransliteratedShabbosDayOfWeek(String)
345         * @see #formatDayOfWeek(JewishDate)
346         */
347        public String getTransliteratedShabbosDayOfWeek() {
348                return transliteratedShabbosDayOfWeek;
349        }
350
351        /**
352         * Setter to override the default transliterated name of "Shabbos" to alternate spelling such as "Shabbat" used by
353         * the {@link #formatDayOfWeek(JewishDate)}
354         * 
355         * @param transliteratedShabbos
356         *            the transliteratedShabbos to set
357         * 
358         * @see #getTransliteratedShabbosDayOfWeek()
359         * @see #formatDayOfWeek(JewishDate)
360         */
361        public void setTransliteratedShabbosDayOfWeek(String transliteratedShabbos) {
362                this.transliteratedShabbosDayOfWeek = transliteratedShabbos;
363        }
364
365        /**
366         * See {@link #getTransliteratedHolidayList()} and {@link #setTransliteratedHolidayList(String[])}.
367         */
368        private String[] transliteratedHolidays = {"Erev Pesach", "Pesach", "Chol Hamoed Pesach", "Pesach Sheni",
369                        "Erev Shavuos", "Shavuos", "Seventeenth of Tammuz", "Tishah B'Av", "Tu B'Av", "Erev Rosh Hashana",
370                        "Rosh Hashana", "Fast of Gedalyah", "Erev Yom Kippur", "Yom Kippur", "Erev Succos", "Succos",
371                        "Chol Hamoed Succos", "Hoshana Rabbah", "Shemini Atzeres", "Simchas Torah", "Erev Chanukah", "Chanukah",
372                        "Tenth of Teves", "Tu B'Shvat", "Fast of Esther", "Purim", "Shushan Purim", "Purim Katan", "Rosh Chodesh",
373                        "Yom HaShoah", "Yom Hazikaron", "Yom Ha'atzmaut", "Yom Yerushalayim", "Lag B'Omer","Shushan Purim Katan",
374                        "Isru Chag"};
375
376        /**
377         * Returns the array of holidays transliterated into Latin chars. This is used by the
378         * {@link #formatYomTov(JewishCalendar)} when formatting the Yom Tov String. The default list of months uses
379         * Ashkenazi pronunciation in typical American English spelling.
380         * 
381         * @return the array of transliterated holidays. The default list is currently ["Erev Pesach", "Pesach",
382         *         "Chol Hamoed Pesach", "Pesach Sheni", "Erev Shavuos", "Shavuos", "Seventeenth of Tammuz", "Tishah B'Av",
383         *         "Tu B'Av", "Erev Rosh Hashana", "Rosh Hashana", "Fast of Gedalyah", "Erev Yom Kippur", "Yom Kippur",
384         *         "Erev Succos", "Succos", "Chol Hamoed Succos", "Hoshana Rabbah", "Shemini Atzeres", "Simchas Torah",
385         *         "Erev Chanukah", "Chanukah", "Tenth of Teves", "Tu B'Shvat", "Fast of Esther", "Purim", "Shushan Purim",
386         *         "Purim Katan", "Rosh Chodesh", "Yom HaShoah", "Yom Hazikaron", "Yom Ha'atzmaut", "Yom Yerushalayim",
387         *         "Lag B'Omer","Shushan Purim Katan","Isru Chag"].
388         * 
389         * @see #setTransliteratedMonthList(String[])
390         * @see #formatYomTov(JewishCalendar)
391         * @see #isHebrewFormat()
392         */
393        public String[] getTransliteratedHolidayList() {
394                return transliteratedHolidays;
395        }
396
397        /**
398         * Sets the array of holidays transliterated into Latin chars. This is used by the
399         * {@link #formatYomTov(JewishCalendar)} when formatting the Yom Tov String.
400         * 
401         * @param transliteratedHolidays
402         *            the transliteratedHolidays to set. Ensure that the sequence exactly matches the list returned by the
403         *            default
404         */
405        public void setTransliteratedHolidayList(String[] transliteratedHolidays) {
406                this.transliteratedHolidays = transliteratedHolidays;
407        }
408
409        /**
410         * Hebrew holiday array in the following format.<br><code>["&#x05E2;&#x05E8;&#x05D1; &#x05E4;&#x05E1;&#x05D7;",
411         * "&#x05E4;&#x05E1;&#x05D7;", "&#x05D7;&#x05D5;&#x05DC; &#x05D4;&#x05DE;&#x05D5;&#x05E2;&#x05D3;
412         * &#x05E4;&#x05E1;&#x05D7;", "&#x05E4;&#x05E1;&#x05D7; &#x05E9;&#x05E0;&#x05D9;", "&#x05E2;&#x05E8;&#x05D1;
413         * &#x05E9;&#x05D1;&#x05D5;&#x05E2;&#x05D5;&#x05EA;", "&#x05E9;&#x05D1;&#x05D5;&#x05E2;&#x05D5;&#x05EA;",
414         * "&#x05E9;&#x05D1;&#x05E2;&#x05D4; &#x05E2;&#x05E9;&#x05E8; &#x05D1;&#x05EA;&#x05DE;&#x05D5;&#x05D6;",
415         * "&#x05EA;&#x05E9;&#x05E2;&#x05D4; &#x05D1;&#x05D0;&#x05D1;",
416         * "&#x05D8;&#x05F4;&#x05D5; &#x05D1;&#x05D0;&#x05D1;",
417         * "&#x05E2;&#x05E8;&#x05D1; &#x05E8;&#x05D0;&#x05E9; &#x05D4;&#x05E9;&#x05E0;&#x05D4;",
418         * "&#x05E8;&#x05D0;&#x05E9; &#x05D4;&#x05E9;&#x05E0;&#x05D4;",
419         * "&#x05E6;&#x05D5;&#x05DD; &#x05D2;&#x05D3;&#x05DC;&#x05D9;&#x05D4;",
420         * "&#x05E2;&#x05E8;&#x05D1; &#x05D9;&#x05D5;&#x05DD; &#x05DB;&#x05D9;&#x05E4;&#x05D5;&#x05E8;",
421         * "&#x05D9;&#x05D5;&#x05DD; &#x05DB;&#x05D9;&#x05E4;&#x05D5;&#x05E8;",
422         * "&#x05E2;&#x05E8;&#x05D1; &#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
423         * "&#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
424         * "&#x05D7;&#x05D5;&#x05DC; &#x05D4;&#x05DE;&#x05D5;&#x05E2;&#x05D3; &#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
425         * "&#x05D4;&#x05D5;&#x05E9;&#x05E2;&#x05E0;&#x05D0; &#x05E8;&#x05D1;&#x05D4;",
426         * "&#x05E9;&#x05DE;&#x05D9;&#x05E0;&#x05D9; &#x05E2;&#x05E6;&#x05E8;&#x05EA;",
427         * "&#x05E9;&#x05DE;&#x05D7;&#x05EA; &#x05EA;&#x05D5;&#x05E8;&#x05D4;",
428         * "&#x05E2;&#x05E8;&#x05D1; &#x05D7;&#x05E0;&#x05D5;&#x05DB;&#x05D4;",
429         * "&#x05D7;&#x05E0;&#x05D5;&#x05DB;&#x05D4;", "&#x05E2;&#x05E9;&#x05E8;&#x05D4; &#x05D1;&#x05D8;&#x05D1;&#x05EA;",
430         * "&#x05D8;&#x05F4;&#x05D5; &#x05D1;&#x05E9;&#x05D1;&#x05D8;",
431         * "&#x05EA;&#x05E2;&#x05E0;&#x05D9;&#x05EA; &#x05D0;&#x05E1;&#x05EA;&#x05E8;",
432         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD;",
433         * "&#x05E9;&#x05D5;&#x05E9;&#x05DF; &#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD;",
434         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD; &#x05E7;&#x05D8;&#x05DF;",
435         * "&#x05E8;&#x05D0;&#x05E9; &#x05D7;&#x05D5;&#x05D3;&#x05E9;",
436         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05E9;&#x05D5;&#x05D0;&#x05D4;",
437         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05D6;&#x05D9;&#x05DB;&#x05E8;&#x05D5;&#x05DF;",
438         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05E2;&#x05E6;&#x05DE;&#x05D0;&#x05D5;&#x05EA;",
439         * "&#x05D9;&#x05D5;&#x05DD; &#x05D9;&#x05E8;&#x05D5;&#x05E9;&#x05DC;&#x05D9;&#x05DD;",
440         * "&#x05DC;&#x05F4;&#x05D2; &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;",
441         * "&#x05E9;&#x05D5;&#x05E9;&#x05DF; &#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD; &#x05E7;&#x05D8;&#x05DF;"]</code>
442         */
443        private final String[] hebrewHolidays = { "\u05E2\u05E8\u05D1 \u05E4\u05E1\u05D7", "\u05E4\u05E1\u05D7",
444                        "\u05D7\u05D5\u05DC \u05D4\u05DE\u05D5\u05E2\u05D3 \u05E4\u05E1\u05D7",
445                        "\u05E4\u05E1\u05D7 \u05E9\u05E0\u05D9", "\u05E2\u05E8\u05D1 \u05E9\u05D1\u05D5\u05E2\u05D5\u05EA",
446                        "\u05E9\u05D1\u05D5\u05E2\u05D5\u05EA",
447                        "\u05E9\u05D1\u05E2\u05D4 \u05E2\u05E9\u05E8 \u05D1\u05EA\u05DE\u05D5\u05D6",
448                        "\u05EA\u05E9\u05E2\u05D4 \u05D1\u05D0\u05D1", "\u05D8\u05F4\u05D5 \u05D1\u05D0\u05D1",
449                        "\u05E2\u05E8\u05D1 \u05E8\u05D0\u05E9 \u05D4\u05E9\u05E0\u05D4",
450                        "\u05E8\u05D0\u05E9 \u05D4\u05E9\u05E0\u05D4", "\u05E6\u05D5\u05DD \u05D2\u05D3\u05DC\u05D9\u05D4",
451                        "\u05E2\u05E8\u05D1 \u05D9\u05D5\u05DD \u05DB\u05D9\u05E4\u05D5\u05E8",
452                        "\u05D9\u05D5\u05DD \u05DB\u05D9\u05E4\u05D5\u05E8", "\u05E2\u05E8\u05D1 \u05E1\u05D5\u05DB\u05D5\u05EA",
453                        "\u05E1\u05D5\u05DB\u05D5\u05EA",
454                        "\u05D7\u05D5\u05DC \u05D4\u05DE\u05D5\u05E2\u05D3 \u05E1\u05D5\u05DB\u05D5\u05EA",
455                        "\u05D4\u05D5\u05E9\u05E2\u05E0\u05D0 \u05E8\u05D1\u05D4",
456                        "\u05E9\u05DE\u05D9\u05E0\u05D9 \u05E2\u05E6\u05E8\u05EA",
457                        "\u05E9\u05DE\u05D7\u05EA \u05EA\u05D5\u05E8\u05D4", "\u05E2\u05E8\u05D1 \u05D7\u05E0\u05D5\u05DB\u05D4",
458                        "\u05D7\u05E0\u05D5\u05DB\u05D4", "\u05E2\u05E9\u05E8\u05D4 \u05D1\u05D8\u05D1\u05EA",
459                        "\u05D8\u05F4\u05D5 \u05D1\u05E9\u05D1\u05D8", "\u05EA\u05E2\u05E0\u05D9\u05EA \u05D0\u05E1\u05EA\u05E8",
460                        "\u05E4\u05D5\u05E8\u05D9\u05DD", "\u05E9\u05D5\u05E9\u05DF \u05E4\u05D5\u05E8\u05D9\u05DD",
461                        "\u05E4\u05D5\u05E8\u05D9\u05DD \u05E7\u05D8\u05DF", "\u05E8\u05D0\u05E9 \u05D7\u05D5\u05D3\u05E9",
462                        "\u05D9\u05D5\u05DD \u05D4\u05E9\u05D5\u05D0\u05D4",
463                        "\u05D9\u05D5\u05DD \u05D4\u05D6\u05D9\u05DB\u05E8\u05D5\u05DF",
464                        "\u05D9\u05D5\u05DD \u05D4\u05E2\u05E6\u05DE\u05D0\u05D5\u05EA",
465                        "\u05D9\u05D5\u05DD \u05D9\u05E8\u05D5\u05E9\u05DC\u05D9\u05DD",
466                        "\u05DC\u05F4\u05D2 \u05D1\u05E2\u05D5\u05DE\u05E8",
467                        "\u05E9\u05D5\u05E9\u05DF \u05E4\u05D5\u05E8\u05D9\u05DD \u05E7\u05D8\u05DF",
468                        "\u05D0\u05E1\u05E8\u05D5 \u05D7\u05D2"};
469
470        /**
471         * Formats the Yom Tov (holiday) in Hebrew or transliterated Latin characters.
472         * 
473         * @param jewishCalendar the JewishCalendar
474         * @return the formatted holiday or an empty String if the day is not a holiday.
475         * @see #isHebrewFormat()
476         */
477        public String formatYomTov(JewishCalendar jewishCalendar) {
478                int index = jewishCalendar.getYomTovIndex();
479                if (index == JewishCalendar.CHANUKAH) {
480                        int dayOfChanukah = jewishCalendar.getDayOfChanukah();
481                        return hebrewFormat ? (formatHebrewNumber(dayOfChanukah) + " " + hebrewHolidays[index])
482                                        : (transliteratedHolidays[index] + " " + dayOfChanukah);
483                }
484                return index == -1 ? "" : hebrewFormat ? hebrewHolidays[index] : transliteratedHolidays[index];
485        }
486
487        /**
488         * Formats a day as Rosh Chodesh in the format of in the format of &#x05E8;&#x05D0;&#x05E9;
489         * &#x05D7;&#x05D5;&#x05D3;&#x05E9; &#x05E9;&#x05D1;&#x05D8; or Rosh Chodesh Shevat. If it
490         * is not Rosh Chodesh, an empty <code>String</code> will be returned.
491         * @param jewishCalendar the JewishCalendar
492         * @return The formatted <code>String</code> in the format of &#x05E8;&#x05D0;&#x05E9;
493         * &#x05D7;&#x05D5;&#x05D3;&#x05E9; &#x05E9;&#x05D1;&#x05D8; or Rosh Chodesh Shevat. If it
494         * is not Rosh Chodesh, an empty <code>String</code> will be returned.
495         */
496        public String formatRoshChodesh(JewishCalendar jewishCalendar) {
497                if (!jewishCalendar.isRoshChodesh()) {
498                        return "";
499                }
500                int month = jewishCalendar.getJewishMonth();
501                if (jewishCalendar.getJewishDayOfMonth() == 30) {
502                        if (month < JewishCalendar.ADAR || (month == JewishCalendar.ADAR && jewishCalendar.isJewishLeapYear())) {
503                                month++;
504                        } else { // roll to Nissan
505                                month = JewishCalendar.NISSAN;
506                        }
507                }
508
509                // This method is only about formatting, so we shouldn't make any changes to the params passed in...
510                jewishCalendar = (JewishCalendar) jewishCalendar.clone();
511                jewishCalendar.setJewishMonth(month);
512                String formattedRoshChodesh = hebrewFormat ? hebrewHolidays[JewishCalendar.ROSH_CHODESH]
513                                : transliteratedHolidays[JewishCalendar.ROSH_CHODESH];
514                formattedRoshChodesh += " " + formatMonth(jewishCalendar);
515                return formattedRoshChodesh;
516        }
517
518        /**
519         * Returns if the formatter is set to use Hebrew formatting in the various formatting methods.
520         * 
521         * @return the hebrewFormat
522         * @see #setHebrewFormat(boolean)
523         * @see #format(JewishDate)
524         * @see #formatDayOfWeek(JewishDate)
525         * @see #formatMonth(JewishDate)
526         * @see #formatOmer(JewishCalendar)
527         * @see #formatYomTov(JewishCalendar)
528         */
529        public boolean isHebrewFormat() {
530                return hebrewFormat;
531        }
532
533        /**
534         * Sets the formatter to format in Hebrew in the various formatting methods.
535         * 
536         * @param hebrewFormat
537         *            the hebrewFormat to set
538         * @see #isHebrewFormat()
539         * @see #format(JewishDate)
540         * @see #formatDayOfWeek(JewishDate)
541         * @see #formatMonth(JewishDate)
542         * @see #formatOmer(JewishCalendar)
543         * @see #formatYomTov(JewishCalendar)
544         */
545        public void setHebrewFormat(boolean hebrewFormat) {
546                this.hebrewFormat = hebrewFormat;
547        }
548
549        /**
550         * Returns the Hebrew Omer prefix.&nbsp; By default it is the letter &#x05D1; producing
551         * &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;, but it can be set to &#x05DC; to produce
552         * &#x05DC;&#x05E2;&#x05D5;&#x05DE;&#x05E8; (or any other prefix) using the {@link #setHebrewOmerPrefix(String)}.
553         * 
554         * @return the hebrewOmerPrefix
555         * 
556         * @see #hebrewOmerPrefix
557         * @see #setHebrewOmerPrefix(String)
558         * @see #formatOmer(JewishCalendar)
559         */
560        public String getHebrewOmerPrefix() {
561                return hebrewOmerPrefix;
562        }
563
564        /**
565         * Method to set the Hebrew Omer prefix.&nbsp; By default it is the letter &#x05D1; producing
566         * &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;, but it can be set to &#x05DC; to produce
567         * &#x05DC;&#x05E2;&#x05D5;&#x05DE;&#x05E8; (or any other prefix)
568         * @param hebrewOmerPrefix
569         *            the hebrewOmerPrefix to set. You can use the Unicode &#92;u05DC to set it to &#x5DC;.
570         * @see #hebrewOmerPrefix
571         * @see #getHebrewOmerPrefix()
572         * @see #formatOmer(JewishCalendar)
573         */
574        public void setHebrewOmerPrefix(String hebrewOmerPrefix) {
575                this.hebrewOmerPrefix = hebrewOmerPrefix;
576        }
577
578        /**
579         * Returns the array of months transliterated into Latin chars. The default list of months uses Ashkenazi
580         * pronunciation in typical American English spelling. This list has a length of 14 with 3 variations for Adar -
581         * "Adar", "Adar II", "Adar I"
582         * 
583         * @return the array of months beginning in Nissan and ending in "Adar", "Adar II", "Adar I". The default list is
584         *         currently ["Nissan", "Iyar", "Sivan", "Tammuz", "Av", "Elul", "Tishrei", "Cheshvan", "Kislev", "Teves",
585         *         "Shevat", "Adar", "Adar II", "Adar I"].
586         * @see #setTransliteratedMonthList(String[])
587         */
588        public String[] getTransliteratedMonthList() {
589                return transliteratedMonths;
590        }
591
592        /**
593         * Setter method to allow overriding of the default list of months transliterated into Latin chars. The default
594         * uses Ashkenazi American English transliteration.
595         * 
596         * @param transliteratedMonths
597         *            an array of 14 month names that defaults to ["Nissan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Tishrei",
598         *            "Heshvan", "Kislev", "Tevet", "Shevat", "Adar", "Adar II", "Adar I"].
599         * @see #getTransliteratedMonthList()
600         */
601        public void setTransliteratedMonthList(String[] transliteratedMonths) {
602                this.transliteratedMonths = transliteratedMonths;
603        }
604
605        /**
606         * Unicode list of Hebrew months in the following format <code>["\u05E0\u05D9\u05E1\u05DF","\u05D0\u05D9\u05D9\u05E8",
607         * "\u05E1\u05D9\u05D5\u05DF","\u05EA\u05DE\u05D5\u05D6","\u05D0\u05D1","\u05D0\u05DC\u05D5\u05DC",
608         * "\u05EA\u05E9\u05E8\u05D9","\u05D7\u05E9\u05D5\u05DF","\u05DB\u05E1\u05DC\u05D5","\u05D8\u05D1\u05EA",
609         * "\u05E9\u05D1\u05D8","\u05D0\u05D3\u05E8","\u05D0\u05D3\u05E8 \u05D1","\u05D0\u05D3\u05E8 \u05D0"]</code>
610         * 
611         * @see #formatMonth(JewishDate)
612         */
613        private static final String[] hebrewMonths = { "\u05E0\u05D9\u05E1\u05DF", "\u05D0\u05D9\u05D9\u05E8",
614                        "\u05E1\u05D9\u05D5\u05DF", "\u05EA\u05DE\u05D5\u05D6", "\u05D0\u05D1", "\u05D0\u05DC\u05D5\u05DC",
615                        "\u05EA\u05E9\u05E8\u05D9", "\u05D7\u05E9\u05D5\u05DF", "\u05DB\u05E1\u05DC\u05D5",
616                        "\u05D8\u05D1\u05EA", "\u05E9\u05D1\u05D8", "\u05D0\u05D3\u05E8", "\u05D0\u05D3\u05E8 \u05D1",
617                        "\u05D0\u05D3\u05E8 \u05D0" };
618
619        /**
620         * Unicode list of Hebrew days of week in the format of <code>["&#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF;",
621         * "&#x05E9;&#x05E0;&#x05D9;","&#x05E9;&#x05DC;&#x05D9;&#x05E9;&#x05D9;","&#x05E8;&#x05D1;&#x05D9;&#x05E2;&#x05D9;",
622         * "&#x05D7;&#x05DE;&#x05D9;&#x05E9;&#x05D9;","&#x05E9;&#x05E9;&#x05D9;","&#x05E9;&#x05D1;&#x05EA;"]</code>
623         */
624        private static final String[] hebrewDaysOfWeek = { "\u05E8\u05D0\u05E9\u05D5\u05DF", "\u05E9\u05E0\u05D9",
625                        "\u05E9\u05DC\u05D9\u05E9\u05D9", "\u05E8\u05D1\u05D9\u05E2\u05D9", "\u05D7\u05DE\u05D9\u05E9\u05D9",
626                        "\u05E9\u05E9\u05D9", "\u05E9\u05D1\u05EA" };
627
628        /**
629         * Formats the day of week. If {@link #isHebrewFormat() Hebrew formatting} is set, it will display in the format
630         * &#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF; etc. If Hebrew formatting is not in use it will return it in the format
631         * of Sunday etc. There are various formatting options that will affect the output.
632         * 
633         * @param jewishDate the JewishDate Object
634         * @return the formatted day of week
635         * @see #isHebrewFormat()
636         * @see #isLongWeekFormat()
637         */
638        public String formatDayOfWeek(JewishDate jewishDate) {
639                if (hebrewFormat) {
640                        if (isLongWeekFormat()) {
641                                return hebrewDaysOfWeek[jewishDate.getDayOfWeek() - 1];
642                        } else {
643                                if (jewishDate.getDayOfWeek() == 7) {
644                                        return formatHebrewNumber(300);
645                                } else {
646                                        return formatHebrewNumber(jewishDate.getDayOfWeek());
647                                }
648                        }
649                } else {
650                        if (jewishDate.getDayOfWeek() == 7) {
651                                if (isLongWeekFormat()) {
652                                        return getTransliteratedShabbosDayOfWeek();
653                                } else {
654                                        return getTransliteratedShabbosDayOfWeek().substring(0,3);
655                                }
656                        } else {
657                                return weekFormat.format(jewishDate.getGregorianCalendar().getTime());
658                        }
659                }
660        }
661
662        /**
663         * Returns whether the class is set to use the Geresh &#x5F3; and Gershayim &#x5F4; in formatting Hebrew dates and
664         * numbers. When true and output would look like &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x5DB;
665         * (or &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x5DA;). When set to false, this output
666         * would display as &#x5DB;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DB;.
667         * 
668         * @return true if set to use the Geresh &#x5F3; and Gershayim &#x5F4; in formatting Hebrew dates and numbers.
669         */
670        public boolean isUseGershGershayim() {
671                return useGershGershayim;
672        }
673
674        /**
675         * Sets whether to use the Geresh &#x5F3; and Gershayim &#x5F4; in formatting Hebrew dates and numbers. The default
676         * value is true and output would look like &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x5DB;
677         * (or &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5F4;&#x5DA;). When set to false, this output would
678         * display as &#x5DB;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DB; (or
679         * &#x5DB;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DA;). Single digit days or month or years such as &#x05DB;&#x05F3;
680         * &#x05E9;&#x05D1;&#x05D8; &#x05D5;&#x05F3; &#x05D0;&#x05DC;&#x05E4;&#x05D9;&#x05DD; show the use of the Geresh.
681         * 
682         * @param useGershGershayim
683         *            set this to false to omit the Geresh &#x5F3; and Gershayim &#x5F4; in formatting
684         */
685        public void setUseGershGershayim(boolean useGershGershayim) {
686                this.useGershGershayim = useGershGershayim;
687        }
688
689        /**
690         * Returns whether the class is set to use the &#x05DE;&#x05E0;&#x05E6;&#x05E4;&#x05F4;&#x05DA; letters when
691         * formatting years ending in 20, 40, 50, 80 and 90 to produce &#x05EA;&#x05E9;&#x05F4;&#x05E4; if false or
692         * &#x05EA;&#x05E9;&#x05F4;&#x05E3; if true. Traditionally non-final form letters are used, so the year
693         * 5780 would be formatted as &#x05EA;&#x05E9;&#x05F4;&#x05E4; if the default false is used here. If this returns
694         * true, the format &#x05EA;&#x05E9;&#x05F4;&#x05E3; would be used.
695         * 
696         * @return true if set to use final form letters when formatting Hebrew years. The default value is false.
697         */
698        public boolean isUseFinalFormLetters() {
699                return useFinalFormLetters;
700        }
701
702        /**
703         * When formatting a Hebrew Year, traditionally years ending in 20, 40, 50, 80 and 90 are formatted using non-final
704         * form letters for example &#x05EA;&#x05E9;&#x05F4;&#x05E4; for the year 5780. Setting this to true (the default
705         * is false) will use the final form letters for &#x05DE;&#x05E0;&#x05E6;&#x05E4;&#x05F4;&#x05DA; and will format
706         * the year 5780 as &#x05EA;&#x05E9;&#x05F4;&#x05E3;.
707         * 
708         * @param useFinalFormLetters
709         *            Set this to true to use final form letters when formatting Hebrew years.
710         */
711        public void setUseFinalFormLetters(boolean useFinalFormLetters) {
712                this.useFinalFormLetters = useFinalFormLetters;
713        }
714
715        /**
716         * Returns whether the class is set to use the thousands digit when formatting. When formatting a Hebrew Year,
717         * traditionally the thousands digit is omitted and output for a year such as 5729 (1969 Gregorian) would be
718         * calculated for 729 and format as &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;. When set to true the long format year such
719         * as &#x5D4;&#x5F3; &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8; for 5729/1969 is returned.
720         * 
721         * @return true if set to use the thousands digit when formatting Hebrew dates and numbers.
722         */
723        public boolean isUseLongHebrewYears() {
724                return useLonghebrewYears;
725        }
726
727        /**
728         * When formatting a Hebrew Year, traditionally the thousands digit is omitted and output for a year such as 5729
729         * (1969 Gregorian) would be calculated for 729 and format as &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;. This method
730         * allows setting this to true to return the long format year such as &#x5D4;&#x5F3;
731         * &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8; for 5729/1969.
732         * 
733         * @param useLongHebrewYears
734         *            Set this to true to use the long formatting
735         */
736        public void setUseLongHebrewYears(boolean useLongHebrewYears) {
737                this.useLonghebrewYears = useLongHebrewYears;
738        }
739        /**
740         * Formats the Jewish date. If the formatter is set to Hebrew, it will format in the form, "day Month year" for
741         * example &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;, and the format
742         * "21 Shevat, 5729" if not.
743         * 
744         * @param jewishDate
745         *            the JewishDate to be formatted
746         * @return the formatted date. If the formatter is set to Hebrew, it will format in the form, "day Month year" for
747         *         example &#x5DB;&#x5F4;&#x5D0; &#x5E9;&#x5D1;&#x5D8; &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;, and the format
748         *         "21 Shevat, 5729" if not.
749         */
750        public String format(JewishDate jewishDate) {
751                if (isHebrewFormat()) {
752                        return formatHebrewNumber(jewishDate.getJewishDayOfMonth()) + " " + formatMonth(jewishDate) + " "
753                                        + formatHebrewNumber(jewishDate.getJewishYear());
754                } else {
755                        return jewishDate.getJewishDayOfMonth() + " " + formatMonth(jewishDate) + ", " + jewishDate.getJewishYear();
756                }
757        }
758
759        /**
760         * Returns a string of the current Hebrew month such as "Tishrei". Returns a string of the current Hebrew month such
761         * as "&#x5D0;&#x5D3;&#x5E8; &#x5D1;&#x5F3;".
762         * 
763         * @param jewishDate
764         *            the JewishDate to format
765         * @return the formatted month name
766         * @see #isHebrewFormat()
767         * @see #setHebrewFormat(boolean)
768         * @see #getTransliteratedMonthList()
769         * @see #setTransliteratedMonthList(String[])
770         */
771        public String formatMonth(JewishDate jewishDate) {
772                final int month = jewishDate.getJewishMonth();
773                if (isHebrewFormat()) {
774                        if (jewishDate.isJewishLeapYear() && month == JewishDate.ADAR) {
775                                return hebrewMonths[13] + (useGershGershayim ? GERESH : ""); // return Adar I, not Adar in a leap year
776                        } else if (jewishDate.isJewishLeapYear() && month == JewishDate.ADAR_II) {
777                                return hebrewMonths[12] + (useGershGershayim ? GERESH : "");
778                        } else {
779                                return hebrewMonths[month - 1];
780                        }
781                } else {
782                        if (jewishDate.isJewishLeapYear() && month == JewishDate.ADAR) {
783                                return transliteratedMonths[13]; // return Adar I, not Adar in a leap year
784                        } else {
785                                return transliteratedMonths[month - 1];
786                        }
787                }
788        }
789
790        /**
791         * Returns a String of the Omer day in the form &#x5DC;&#x5F4;&#x5D2; &#x5D1;&#x05E2;&#x05D5;&#x05DE;&#x5E8; if
792         * Hebrew Format is set, or "Omer X" or "Lag B'Omer" if not. An empty string if there is no Omer this day.
793         * 
794         * @param jewishCalendar
795         *            the JewishCalendar to be formatted
796         * 
797         * @return a String of the Omer day in the form or an empty string if there is no Omer this day. The default
798         *         formatting has a &#x5D1;&#x5F3; prefix that would output &#x5D1;&#x05E2;&#x05D5;&#x05DE;&#x5E8;, but this
799         *         can be set via the {@link #setHebrewOmerPrefix(String)} method to use a &#x5DC; and output
800         *         &#x5DC;&#x5F4;&#x5D2; &#x5DC;&#x05E2;&#x05D5;&#x05DE;&#x5E8;.
801         * @see #isHebrewFormat()
802         * @see #getHebrewOmerPrefix()
803         * @see #setHebrewOmerPrefix(String)
804         */
805        public String formatOmer(JewishCalendar jewishCalendar) {
806                int omer = jewishCalendar.getDayOfOmer();
807                if (omer == -1) {
808                        return "";
809                }
810                if (hebrewFormat) {
811                        return formatHebrewNumber(omer) + " " + hebrewOmerPrefix + "\u05E2\u05D5\u05DE\u05E8";
812                } else {
813                        if (omer == 33) { // if Lag B'Omer
814                                return transliteratedHolidays[33];
815                        } else {
816                                return "Omer " + omer;
817                        }
818                }
819        }
820
821        /**
822         * Formats a molad.
823         * @todo Experimental and incomplete.
824         * 
825         * @param moladChalakim the chalakim of the molad
826         * @return the formatted molad. FIXME: define proper format in English and Hebrew.
827         */
828        private static String formatMolad(long moladChalakim) {
829                long adjustedChalakim = moladChalakim;
830                int MINUTE_CHALAKIM = 18;
831                int HOUR_CHALAKIM = 1080;
832                int DAY_CHALAKIM = 24 * HOUR_CHALAKIM;
833
834                long days = adjustedChalakim / DAY_CHALAKIM;
835                adjustedChalakim = adjustedChalakim - (days * DAY_CHALAKIM);
836                int hours = (int) ((adjustedChalakim / HOUR_CHALAKIM));
837                if (hours >= 6) {
838                        days += 1;
839                }
840                adjustedChalakim = adjustedChalakim - (hours * (long) HOUR_CHALAKIM);
841                int minutes = (int) (adjustedChalakim / MINUTE_CHALAKIM);
842                adjustedChalakim = adjustedChalakim - minutes * (long) MINUTE_CHALAKIM;
843                return "Day: " + days % 7 + " hours: " + hours + ", minutes " + minutes + ", chalakim: " + adjustedChalakim;
844        }
845
846        /**
847         * Returns the kviah in the traditional 3 letter Hebrew format where the first letter represents the day of week of
848         * Rosh Hashana, the second letter represents the lengths of Cheshvan and Kislev ({@link JewishDate#SHELAIMIM
849         * Shelaimim} , {@link JewishDate#KESIDRAN Kesidran} or {@link JewishDate#CHASERIM Chaserim}) and the 3rd letter
850         * represents the day of week of Pesach. For example 5729 (1969) would return &#x5D1;&#x5E9;&#x5D4; (Rosh Hashana on
851         * Monday, Shelaimim, and Pesach on Thursday), while 5771 (2011) would return &#x5D4;&#x5E9;&#x5D2; (Rosh Hashana on
852         * Thursday, Shelaimim, and Pesach on Tuesday).
853         * 
854         * @param jewishYear
855         *            the Jewish year
856         * @return the Hebrew String such as &#x5D1;&#x5E9;&#x5D4; for 5729 (1969) and &#x5D4;&#x5E9;&#x5D2; for 5771
857         *         (2011).
858         */
859        public String getFormattedKviah(int jewishYear) {
860                JewishDate jewishDate = new JewishDate(jewishYear, JewishDate.TISHREI, 1); // set date to Rosh Hashana
861                int kviah = jewishDate.getCheshvanKislevKviah();
862                int roshHashanaDayOfWeek = jewishDate.getDayOfWeek();
863                String returnValue = formatHebrewNumber(roshHashanaDayOfWeek);
864                returnValue += (kviah == JewishDate.CHASERIM ? "\u05D7" : kviah == JewishDate.SHELAIMIM ? "\u05E9" : "\u05DB");
865                jewishDate.setJewishDate(jewishYear, JewishDate.NISSAN, 15); // set to Pesach of the given year
866                int pesachDayOfWeek = jewishDate.getDayOfWeek();
867                returnValue += formatHebrewNumber(pesachDayOfWeek);
868                returnValue = returnValue.replaceAll(GERESH, "");// geresh is never used in the kviah format
869                // boolean isLeapYear = JewishDate.isJewishLeapYear(jewishYear);
870                // for efficiency we can avoid the expensive recalculation of the pesach day of week by adding 1 day to Rosh
871                // Hashana for a 353-day year, 2 for a 354-day year, 3 for a 355 or 383-day year, 4 for a 384-day year and 5 for
872                // a 385-day year
873                return returnValue;
874        }
875
876        /**
877         * Formats the <a href="https://en.wikipedia.org/wiki/Daf_Yomi">Daf Yomi</a> Bavli in the format of
878         * "&#x05E2;&#x05D9;&#x05E8;&#x05D5;&#x05D1;&#x05D9;&#x05DF; &#x05E0;&#x05F4;&#x05D1;" in {@link #isHebrewFormat() Hebrew},
879         * or the transliterated format of "Eruvin 52".
880         * @param daf the Daf to be formatted.
881         * @return the formatted daf.
882         */
883        public String formatDafYomiBavli(Daf daf) {
884                if (hebrewFormat) {
885                        return daf.getMasechta() + " " + formatHebrewNumber(daf.getDaf());
886                } else {
887                        return daf.getMasechtaTransliterated() + " " + daf.getDaf();
888                }
889        }
890        
891        /**
892         * Formats the <a href="https://en.wikipedia.org/wiki/Jerusalem_Talmud#Daf_Yomi_Yerushalmi">Daf Yomi Yerushalmi</a> in the format
893         * of "&#x05E2;&#x05D9;&#x05E8;&#x05D5;&#x05D1;&#x05D9;&#x05DF; &#x05E0;&#x05F4;&#x05D1;" in {@link #isHebrewFormat() Hebrew}, or
894         * the transliterated format of "Eruvin 52".
895         * 
896         * @param daf the Daf to be formatted.
897         * @return the formatted daf.
898         */
899        public String formatDafYomiYerushalmi(Daf daf) {
900                if (daf == null) {
901                        if (hebrewFormat) {
902                                return Daf.getYerushalmiMasechtos()[39];
903                        } else {
904                                return Daf.getYerushalmiMasechtosTransliterated()[39];
905                        }
906                }
907                if (hebrewFormat) {                     
908                        return daf.getYerushalmiMasechta() + " " + formatHebrewNumber(daf.getDaf());
909                } else {
910                        return daf.getYerushalmiMasechtaTransliterated() + " " + daf.getDaf();
911                }
912        }
913
914        /**
915         * Returns a Hebrew formatted string of a number. The method can calculate from 0 to 9999.
916         * <ul>
917         * <li>Single digit numbers such as 3, 30 and 100 will be returned with a &#x5F3; (<a
918         * href="http://en.wikipedia.org/wiki/Geresh">Geresh</a>) appended as at the end. For example &#x5D2;&#x5F3;,
919         * &#x5DC;&#x5F3; and &#x5E7;&#x5F3;</li>
920         * <li>multi digit numbers such as 21 and 769 will be returned with a &#x5F4; (<a
921         * href="http://en.wikipedia.org/wiki/Gershayim">Gershayim</a>) between the second to last and last letters. For
922         * example &#x5DB;&#x5F4;&#x5D0;, &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;</li>
923         * <li>15 and 16 will be returned as &#x5D8;&#x5F4;&#x5D5; and &#x5D8;&#x5F4;&#x5D6;</li>
924         * <li>Single digit numbers (years assumed) such as 6000 (%1000=0) will be returned as &#x5D5;&#x5F3;
925         * &#x5D0;&#x5DC;&#x5E4;&#x5D9;&#x5DD;</li>
926         * <li>0 will return &#x5D0;&#x5E4;&#x05E1;</li>
927         * </ul>
928         * 
929         * @param number
930         *            the number to be formatted. It will trow an IllegalArgumentException if the number is &lt; 0 or &gt; 9999.
931         * @return the Hebrew formatted number such as &#x5EA;&#x5E9;&#x5DB;&#x5F4;&#x5D8;
932         * @see #isUseFinalFormLetters()
933         * @see #isUseGershGershayim()
934         * @see #isHebrewFormat()
935         * 
936         */
937        public String formatHebrewNumber(int number) {
938                if (number < 0) {
939                        throw new IllegalArgumentException("negative numbers can't be formatted");
940                } else if (number > 9999) {
941                        throw new IllegalArgumentException("numbers > 9999 can't be formatted");
942                }
943
944                String ALAFIM = "\u05D0\u05DC\u05E4\u05D9\u05DD";
945                String EFES = "\u05D0\u05E4\u05E1";
946
947                String[] jHundreds = new String[] { "", "\u05E7", "\u05E8", "\u05E9", "\u05EA", "\u05EA\u05E7", "\u05EA\u05E8",
948                                "\u05EA\u05E9", "\u05EA\u05EA", "\u05EA\u05EA\u05E7" };
949                String[] jTens = new String[] { "", "\u05D9", "\u05DB", "\u05DC", "\u05DE", "\u05E0", "\u05E1", "\u05E2",
950                                "\u05E4", "\u05E6" };
951                String[] jTenEnds = new String[] { "", "\u05D9", "\u05DA", "\u05DC", "\u05DD", "\u05DF", "\u05E1", "\u05E2",
952                                "\u05E3", "\u05E5" };
953                String[] tavTaz = new String[] { "\u05D8\u05D5", "\u05D8\u05D6" };
954                String[] jOnes = new String[] { "", "\u05D0", "\u05D1", "\u05D2", "\u05D3", "\u05D4", "\u05D5", "\u05D6",
955                                "\u05D7", "\u05D8" };
956
957                if (number == 0) { // do we really need this? Should it be applicable to a date?
958                        return EFES;
959                }
960                int shortNumber = number % 1000; // discard thousands
961                // next check for all possible single Hebrew digit years
962                boolean singleDigitNumber = (shortNumber < 11 || (shortNumber < 100 && shortNumber % 10 == 0) || (shortNumber <= 400 && shortNumber % 100 == 0));
963                int thousands = number / 1000; // get # thousands
964                StringBuilder sb = new StringBuilder();
965                // append thousands to String
966                if (number % 1000 == 0) { // in year is 5000, 4000 etc
967                        sb.append(jOnes[thousands]);
968                        if (isUseGershGershayim()) {
969                                sb.append(GERESH);
970                        }
971                        sb.append(" ");
972                        sb.append(ALAFIM); // add # of thousands plus the word "thousand" (override alafim boolean)
973                        return sb.toString();
974                } else if (useLonghebrewYears && number >= 1000) { // if alafim boolean display thousands
975                        sb.append(jOnes[thousands]);
976                        if (isUseGershGershayim()) {
977                                sb.append(GERESH); // append thousands quote
978                        }
979                        sb.append(" ");
980                }
981                number = number % 1000; // remove 1000s
982                int hundreds = number / 100; // # of hundreds
983                sb.append(jHundreds[hundreds]); // add hundreds to String
984                number = number % 100; // remove 100s
985                if (number == 15) { // special case 15
986                        sb.append(tavTaz[0]);
987                } else if (number == 16) { // special case 16
988                        sb.append(tavTaz[1]);
989                } else {
990                        int tens = number / 10;
991                        if (number % 10 == 0) { // if evenly divisible by 10
992                                if (!singleDigitNumber) {
993                                        if (isUseFinalFormLetters()) {
994                                                sb.append(jTenEnds[tens]); // years like 5780 will end with a final form &#x05E3;
995                                        } else {
996                                                sb.append(jTens[tens]); // years like 5780 will end with a regular &#x05E4;
997                                        }
998                                } else {
999                                        sb.append(jTens[tens]); // standard letters so years like 5050 will end with a regular nun
1000                                }
1001                        } else {
1002                                sb.append(jTens[tens]);
1003                                number = number % 10;
1004                                sb.append(jOnes[number]);
1005                        }
1006                }
1007                if (isUseGershGershayim()) {
1008                        if (singleDigitNumber) {
1009                                sb.append(GERESH); // append single quote
1010                        } else { // append double quote before last digit
1011                                sb.insert(sb.length() - 1, GERSHAYIM);
1012                        }
1013                }
1014                return sb.toString();
1015        }       
1016
1017        /**
1018         * Returns the map of transliterated parshiyos used by this formatter.
1019         * 
1020         * @return the map of transliterated Parshios
1021         */
1022        public EnumMap<JewishCalendar.Parsha, String> getTransliteratedParshiosList() {
1023                return transliteratedParshaMap;
1024        }
1025
1026        /**
1027         * Setter method to allow overriding of the default list of parshiyos transliterated into Latin chars. The
1028         * default uses Ashkenazi American English transliteration.
1029         * 
1030         * @param transliteratedParshaMap
1031         *            the transliterated Parshios as an EnumMap to set
1032         * @see #getTransliteratedParshiosList()
1033         */
1034        public void setTransliteratedParshiosList(EnumMap<JewishCalendar.Parsha, String> transliteratedParshaMap) {
1035                this.transliteratedParshaMap = transliteratedParshaMap;
1036        }
1037        
1038        /**
1039         * Returns a String with the name of the current parsha(ios). This method gets the current <em>parsha</em> by
1040         * calling {@link JewishCalendar#getParshah()} that does not return a <em>parsha</em> for any non-<em>Shabbos</em>
1041         * or a <em>Shabbos</em> that occurs on a <em>Yom Tov</em>, and will return an empty <code>String</code> in those
1042         * cases. If the class {@link #isHebrewFormat() is set to format in Hebrew} it will return a <code>String</code>
1043         * of the current parsha(ios) in Hebrew for example &#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA; or
1044         * &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA; or an empty string if there
1045         * are none. If not set to Hebrew, it returns a string of the parsha(ios) transliterated into Latin chars. The
1046         * default uses Ashkenazi pronunciation in typical American English spelling, for example Bereshis or
1047         * Nitzavim Vayeilech or an empty string if there are none.
1048         * 
1049         * @param jewishCalendar the JewishCalendar Object
1050         * @return today's parsha(ios) in Hebrew for example, if the formatter is set to format in Hebrew, returns a string
1051         *         of the current parsha(ios) in Hebrew for example &#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA; or
1052         *         &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA; or an empty string if
1053         *         there are none. If not set to Hebrew, it returns a string of the parsha(ios) transliterated into Latin
1054         *         chars. The default uses Ashkenazi pronunciation in typical American English spelling, for example
1055         *         Bereshis or Nitzavim Vayeilech or an empty string if there are none.
1056         * @see #formatParsha(JewishCalendar)
1057         * @see #isHebrewFormat()
1058         * @see JewishCalendar#getParshah()
1059         */
1060        public String formatParsha(JewishCalendar jewishCalendar) {
1061                JewishCalendar.Parsha parsha =  jewishCalendar.getParshah();
1062                return formatParsha(parsha);
1063        }
1064
1065        /**
1066         * Returns a String with the name of the current parsha(ios). This method overloads {@link
1067         * HebrewDateFormatter#formatParsha(JewishCalendar)} and unlike that method, it will format the <em>parsha</em> passed
1068         * to this method regardless of the day of week. This is the way to format a <em>parsha</em> retrieved from calling
1069         * {@link JewishCalendar#getUpcomingParshah()}.
1070         *
1071         * @param parsha a JewishCalendar.Parsha object
1072         * @return today's parsha(ios) in Hebrew for example, if the formatter is set to format in Hebrew, returns a string
1073         *         of the current parsha(ios) in Hebrew for example &#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA; or
1074         *         &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA; or an empty string if
1075         *         there are none. If not set to Hebrew, it returns a string of the parsha(ios) transliterated into Latin
1076         *         chars. The default uses Ashkenazi pronunciation in typical American English spelling, for example
1077         *         Bereshis or Nitzavim Vayeilech or an empty string if there are none.
1078         * @see #formatParsha(JewishCalendar)
1079         * @see JewishCalendar#getUpcomingParshah()
1080         */
1081        public String formatParsha(JewishCalendar.Parsha parsha) {
1082                return hebrewFormat ? hebrewParshaMap.get(parsha) : transliteratedParshaMap.get(parsha);
1083        }
1084        
1085        /**
1086         * Returns a String with the name of the current special parsha of Shekalim, Zachor, Parah or Hachodesh or an
1087         * empty String for a non-special parsha. If the formatter is set to format in Hebrew, it returns a string of
1088         * the current special parsha in Hebrew, for example &#x05E9;&#x05E7;&#x05DC;&#x05D9;&#x05DD;,
1089         * &#x05D6;&#x05DB;&#x05D5;&#x05E8;, &#x05E4;&#x05E8;&#x05D4; or &#x05D4;&#x05D7;&#x05D3;&#x05E9;. An empty
1090         * string if the date is not a special parsha. If not set to Hebrew, it returns a string of the special parsha
1091         * transliterated into Latin chars. The default uses Ashkenazi pronunciation in typical American English spelling
1092         * Shekalim, Zachor, Parah or Hachodesh.
1093         * 
1094         * @param jewishCalendar the JewishCalendar Object
1095         * @return today's special parsha. If the formatter is set to format in Hebrew, returns a string
1096         *         of the current special parsha  in Hebrew for in the format of &#x05E9;&#x05E7;&#x05DC;&#x05D9;&#x05DD;,
1097         *         &#x05D6;&#x05DB;&#x05D5;&#x05E8;, &#x05E4;&#x05E8;&#x05D4; or &#x05D4;&#x05D7;&#x05D3;&#x05E9; or an empty
1098         *         string if there are none. If not set to Hebrew, it returns a string of the special parsha transliterated
1099         *         into Latin chars. The default uses Ashkenazi pronunciation in typical American English spelling of Shekalim,
1100         *         Zachor, Parah or Hachodesh. An empty string if there are none.
1101         */
1102        public String formatSpecialParsha(JewishCalendar jewishCalendar) {
1103                JewishCalendar.Parsha specialParsha =  jewishCalendar.getSpecialShabbos();
1104                return hebrewFormat ? hebrewParshaMap.get(specialParsha) : transliteratedParshaMap.get(specialParsha);
1105        }
1106}