001/*
002 * Zmanim Java API
003 * Copyright (C) 2011 - 2023 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 - 2023
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 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                transliteratedParshaMap = new EnumMap<JewishCalendar.Parsha, String>(JewishCalendar.Parsha.class);
126                transliteratedParshaMap.put(JewishCalendar.Parsha.NONE, "");
127                transliteratedParshaMap.put(JewishCalendar.Parsha.BERESHIS, "Bereshis");
128                transliteratedParshaMap.put(JewishCalendar.Parsha.NOACH, "Noach");
129                transliteratedParshaMap.put(JewishCalendar.Parsha.LECH_LECHA, "Lech Lecha");
130                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYERA, "Vayera");
131                transliteratedParshaMap.put(JewishCalendar.Parsha.CHAYEI_SARA, "Chayei Sara");
132                transliteratedParshaMap.put(JewishCalendar.Parsha.TOLDOS, "Toldos");
133                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYETZEI, "Vayetzei");
134                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYISHLACH, "Vayishlach");
135                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYESHEV, "Vayeshev");
136                transliteratedParshaMap.put(JewishCalendar.Parsha.MIKETZ, "Miketz");
137                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYIGASH, "Vayigash");
138                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYECHI, "Vayechi");
139                transliteratedParshaMap.put(JewishCalendar.Parsha.SHEMOS, "Shemos");
140                transliteratedParshaMap.put(JewishCalendar.Parsha.VAERA, "Vaera");
141                transliteratedParshaMap.put(JewishCalendar.Parsha.BO, "Bo");
142                transliteratedParshaMap.put(JewishCalendar.Parsha.BESHALACH, "Beshalach");
143                transliteratedParshaMap.put(JewishCalendar.Parsha.YISRO, "Yisro");
144                transliteratedParshaMap.put(JewishCalendar.Parsha.MISHPATIM, "Mishpatim");
145                transliteratedParshaMap.put(JewishCalendar.Parsha.TERUMAH, "Terumah");
146                transliteratedParshaMap.put(JewishCalendar.Parsha.TETZAVEH, "Tetzaveh");
147                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SISA, "Ki Sisa");
148                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYAKHEL, "Vayakhel");
149                transliteratedParshaMap.put(JewishCalendar.Parsha.PEKUDEI, "Pekudei");
150                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYIKRA, "Vayikra");
151                transliteratedParshaMap.put(JewishCalendar.Parsha.TZAV, "Tzav");
152                transliteratedParshaMap.put(JewishCalendar.Parsha.SHMINI, "Shmini");
153                transliteratedParshaMap.put(JewishCalendar.Parsha.TAZRIA, "Tazria");
154                transliteratedParshaMap.put(JewishCalendar.Parsha.METZORA, "Metzora");
155                transliteratedParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS, "Achrei Mos");
156                transliteratedParshaMap.put(JewishCalendar.Parsha.KEDOSHIM, "Kedoshim");
157                transliteratedParshaMap.put(JewishCalendar.Parsha.EMOR, "Emor");
158                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAR, "Behar");
159                transliteratedParshaMap.put(JewishCalendar.Parsha.BECHUKOSAI, "Bechukosai");
160                transliteratedParshaMap.put(JewishCalendar.Parsha.BAMIDBAR, "Bamidbar");
161                transliteratedParshaMap.put(JewishCalendar.Parsha.NASSO, "Nasso");
162                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAALOSCHA, "Beha'aloscha");
163                transliteratedParshaMap.put(JewishCalendar.Parsha.SHLACH, "Sh'lach");
164                transliteratedParshaMap.put(JewishCalendar.Parsha.KORACH, "Korach");
165                transliteratedParshaMap.put(JewishCalendar.Parsha.CHUKAS, "Chukas");
166                transliteratedParshaMap.put(JewishCalendar.Parsha.BALAK, "Balak");
167                transliteratedParshaMap.put(JewishCalendar.Parsha.PINCHAS, "Pinchas");
168                transliteratedParshaMap.put(JewishCalendar.Parsha.MATOS, "Matos");
169                transliteratedParshaMap.put(JewishCalendar.Parsha.MASEI, "Masei");
170                transliteratedParshaMap.put(JewishCalendar.Parsha.DEVARIM, "Devarim");
171                transliteratedParshaMap.put(JewishCalendar.Parsha.VAESCHANAN, "Vaeschanan");
172                transliteratedParshaMap.put(JewishCalendar.Parsha.EIKEV, "Eikev");
173                transliteratedParshaMap.put(JewishCalendar.Parsha.REEH, "Re'eh");
174                transliteratedParshaMap.put(JewishCalendar.Parsha.SHOFTIM, "Shoftim");
175                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SEITZEI, "Ki Seitzei");
176                transliteratedParshaMap.put(JewishCalendar.Parsha.KI_SAVO, "Ki Savo");
177                transliteratedParshaMap.put(JewishCalendar.Parsha.NITZAVIM, "Nitzavim");
178                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYEILECH, "Vayeilech");
179                transliteratedParshaMap.put(JewishCalendar.Parsha.HAAZINU, "Ha'Azinu");
180                transliteratedParshaMap.put(JewishCalendar.Parsha.VZOS_HABERACHA, "Vezos Habracha");
181                transliteratedParshaMap.put(JewishCalendar.Parsha.VAYAKHEL_PEKUDEI, "Vayakhel Pekudei");
182                transliteratedParshaMap.put(JewishCalendar.Parsha.TAZRIA_METZORA, "Tazria Metzora");
183                transliteratedParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS_KEDOSHIM, "Achrei Mos Kedoshim");
184                transliteratedParshaMap.put(JewishCalendar.Parsha.BEHAR_BECHUKOSAI, "Behar Bechukosai");
185                transliteratedParshaMap.put(JewishCalendar.Parsha.CHUKAS_BALAK, "Chukas Balak");
186                transliteratedParshaMap.put(JewishCalendar.Parsha.MATOS_MASEI, "Matos Masei");
187                transliteratedParshaMap.put(JewishCalendar.Parsha.NITZAVIM_VAYEILECH, "Nitzavim Vayeilech");
188                transliteratedParshaMap.put(JewishCalendar.Parsha.SHKALIM, "Shekalim");
189                transliteratedParshaMap.put(JewishCalendar.Parsha.ZACHOR, "Zachor");
190                transliteratedParshaMap.put(JewishCalendar.Parsha.PARA, "Parah");
191                transliteratedParshaMap.put(JewishCalendar.Parsha.HACHODESH, "Hachodesh");
192                transliteratedParshaMap.put(JewishCalendar.Parsha.SHUVA, "Shuva");
193                transliteratedParshaMap.put(JewishCalendar.Parsha.SHIRA, "Shira");
194                transliteratedParshaMap.put(JewishCalendar.Parsha.HAGADOL, "Hagadol");
195                transliteratedParshaMap.put(JewishCalendar.Parsha.CHAZON, "Chazon");
196                transliteratedParshaMap.put(JewishCalendar.Parsha.NACHAMU, "Nachamu");
197                
198                hebrewParshaMap = new EnumMap<JewishCalendar.Parsha, String>(JewishCalendar.Parsha.class);
199                hebrewParshaMap.put(JewishCalendar.Parsha.NONE, "");
200                hebrewParshaMap.put(JewishCalendar.Parsha.BERESHIS, "\u05D1\u05E8\u05D0\u05E9\u05D9\u05EA");
201                hebrewParshaMap.put(JewishCalendar.Parsha.NOACH, "\u05E0\u05D7");
202                hebrewParshaMap.put(JewishCalendar.Parsha.LECH_LECHA, "\u05DC\u05DA \u05DC\u05DA");
203                hebrewParshaMap.put(JewishCalendar.Parsha.VAYERA, "\u05D5\u05D9\u05E8\u05D0");
204                hebrewParshaMap.put(JewishCalendar.Parsha.CHAYEI_SARA, "\u05D7\u05D9\u05D9 \u05E9\u05E8\u05D4");
205                hebrewParshaMap.put(JewishCalendar.Parsha.TOLDOS, "\u05EA\u05D5\u05DC\u05D3\u05D5\u05EA");
206                hebrewParshaMap.put(JewishCalendar.Parsha.VAYETZEI, "\u05D5\u05D9\u05E6\u05D0");
207                hebrewParshaMap.put(JewishCalendar.Parsha.VAYISHLACH, "\u05D5\u05D9\u05E9\u05DC\u05D7");
208                hebrewParshaMap.put(JewishCalendar.Parsha.VAYESHEV, "\u05D5\u05D9\u05E9\u05D1");
209                hebrewParshaMap.put(JewishCalendar.Parsha.MIKETZ, "\u05DE\u05E7\u05E5");
210                hebrewParshaMap.put(JewishCalendar.Parsha.VAYIGASH, "\u05D5\u05D9\u05D2\u05E9");
211                hebrewParshaMap.put(JewishCalendar.Parsha.VAYECHI, "\u05D5\u05D9\u05D7\u05D9");
212                hebrewParshaMap.put(JewishCalendar.Parsha.SHEMOS, "\u05E9\u05DE\u05D5\u05EA");
213                hebrewParshaMap.put(JewishCalendar.Parsha.VAERA, "\u05D5\u05D0\u05E8\u05D0");
214                hebrewParshaMap.put(JewishCalendar.Parsha.BO, "\u05D1\u05D0");
215                hebrewParshaMap.put(JewishCalendar.Parsha.BESHALACH, "\u05D1\u05E9\u05DC\u05D7");
216                hebrewParshaMap.put(JewishCalendar.Parsha.YISRO, "\u05D9\u05EA\u05E8\u05D5");
217                hebrewParshaMap.put(JewishCalendar.Parsha.MISHPATIM, "\u05DE\u05E9\u05E4\u05D8\u05D9\u05DD");
218                hebrewParshaMap.put(JewishCalendar.Parsha.TERUMAH, "\u05EA\u05E8\u05D5\u05DE\u05D4");
219                hebrewParshaMap.put(JewishCalendar.Parsha.TETZAVEH, "\u05EA\u05E6\u05D5\u05D4");
220                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SISA, "\u05DB\u05D9 \u05EA\u05E9\u05D0");
221                hebrewParshaMap.put(JewishCalendar.Parsha.VAYAKHEL, "\u05D5\u05D9\u05E7\u05D4\u05DC");
222                hebrewParshaMap.put(JewishCalendar.Parsha.PEKUDEI, "\u05E4\u05E7\u05D5\u05D3\u05D9");
223                hebrewParshaMap.put(JewishCalendar.Parsha.VAYIKRA, "\u05D5\u05D9\u05E7\u05E8\u05D0");
224                hebrewParshaMap.put(JewishCalendar.Parsha.TZAV, "\u05E6\u05D5");
225                hebrewParshaMap.put(JewishCalendar.Parsha.SHMINI, "\u05E9\u05DE\u05D9\u05E0\u05D9");
226                hebrewParshaMap.put(JewishCalendar.Parsha.TAZRIA, "\u05EA\u05D6\u05E8\u05D9\u05E2");
227                hebrewParshaMap.put(JewishCalendar.Parsha.METZORA, "\u05DE\u05E6\u05E8\u05E2");
228                hebrewParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS, "\u05D0\u05D7\u05E8\u05D9 \u05DE\u05D5\u05EA");
229                hebrewParshaMap.put(JewishCalendar.Parsha.KEDOSHIM, "\u05E7\u05D3\u05D5\u05E9\u05D9\u05DD");
230                hebrewParshaMap.put(JewishCalendar.Parsha.EMOR, "\u05D0\u05DE\u05D5\u05E8");
231                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAR, "\u05D1\u05D4\u05E8");
232                hebrewParshaMap.put(JewishCalendar.Parsha.BECHUKOSAI, "\u05D1\u05D7\u05E7\u05EA\u05D9");
233                hebrewParshaMap.put(JewishCalendar.Parsha.BAMIDBAR, "\u05D1\u05DE\u05D3\u05D1\u05E8");
234                hebrewParshaMap.put(JewishCalendar.Parsha.NASSO, "\u05E0\u05E9\u05D0");
235                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAALOSCHA, "\u05D1\u05D4\u05E2\u05DC\u05EA\u05DA");
236                hebrewParshaMap.put(JewishCalendar.Parsha.SHLACH, "\u05E9\u05DC\u05D7 \u05DC\u05DA");
237                hebrewParshaMap.put(JewishCalendar.Parsha.KORACH, "\u05E7\u05E8\u05D7");
238                hebrewParshaMap.put(JewishCalendar.Parsha.CHUKAS, "\u05D7\u05D5\u05E7\u05EA");
239                hebrewParshaMap.put(JewishCalendar.Parsha.BALAK, "\u05D1\u05DC\u05E7");
240                hebrewParshaMap.put(JewishCalendar.Parsha.PINCHAS, "\u05E4\u05D9\u05E0\u05D7\u05E1");
241                hebrewParshaMap.put(JewishCalendar.Parsha.MATOS, "\u05DE\u05D8\u05D5\u05EA");
242                hebrewParshaMap.put(JewishCalendar.Parsha.MASEI, "\u05DE\u05E1\u05E2\u05D9");
243                hebrewParshaMap.put(JewishCalendar.Parsha.DEVARIM, "\u05D3\u05D1\u05E8\u05D9\u05DD");
244                hebrewParshaMap.put(JewishCalendar.Parsha.VAESCHANAN, "\u05D5\u05D0\u05EA\u05D7\u05E0\u05DF");
245                hebrewParshaMap.put(JewishCalendar.Parsha.EIKEV, "\u05E2\u05E7\u05D1");
246                hebrewParshaMap.put(JewishCalendar.Parsha.REEH, "\u05E8\u05D0\u05D4");
247                hebrewParshaMap.put(JewishCalendar.Parsha.SHOFTIM, "\u05E9\u05D5\u05E4\u05D8\u05D9\u05DD");
248                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SEITZEI, "\u05DB\u05D9 \u05EA\u05E6\u05D0");
249                hebrewParshaMap.put(JewishCalendar.Parsha.KI_SAVO, "\u05DB\u05D9 \u05EA\u05D1\u05D5\u05D0");
250                hebrewParshaMap.put(JewishCalendar.Parsha.NITZAVIM, "\u05E0\u05E6\u05D1\u05D9\u05DD");
251                hebrewParshaMap.put(JewishCalendar.Parsha.VAYEILECH, "\u05D5\u05D9\u05DC\u05DA");
252                hebrewParshaMap.put(JewishCalendar.Parsha.HAAZINU, "\u05D4\u05D0\u05D6\u05D9\u05E0\u05D5");
253                hebrewParshaMap.put(JewishCalendar.Parsha.VZOS_HABERACHA, "\u05D5\u05D6\u05D0\u05EA \u05D4\u05D1\u05E8\u05DB\u05D4 ");
254                hebrewParshaMap.put(JewishCalendar.Parsha.VAYAKHEL_PEKUDEI, "\u05D5\u05D9\u05E7\u05D4\u05DC \u05E4\u05E7\u05D5\u05D3\u05D9");
255                hebrewParshaMap.put(JewishCalendar.Parsha.TAZRIA_METZORA, "\u05EA\u05D6\u05E8\u05D9\u05E2 \u05DE\u05E6\u05E8\u05E2");
256                hebrewParshaMap.put(JewishCalendar.Parsha.ACHREI_MOS_KEDOSHIM, "\u05D0\u05D7\u05E8\u05D9 \u05DE\u05D5\u05EA \u05E7\u05D3\u05D5\u05E9\u05D9\u05DD");
257                hebrewParshaMap.put(JewishCalendar.Parsha.BEHAR_BECHUKOSAI, "\u05D1\u05D4\u05E8 \u05D1\u05D7\u05E7\u05EA\u05D9");
258                hebrewParshaMap.put(JewishCalendar.Parsha.CHUKAS_BALAK, "\u05D7\u05D5\u05E7\u05EA \u05D1\u05DC\u05E7");
259                hebrewParshaMap.put(JewishCalendar.Parsha.MATOS_MASEI, "\u05DE\u05D8\u05D5\u05EA \u05DE\u05E1\u05E2\u05D9");
260                hebrewParshaMap.put(JewishCalendar.Parsha.NITZAVIM_VAYEILECH, "\u05E0\u05E6\u05D1\u05D9\u05DD \u05D5\u05D9\u05DC\u05DA");
261                hebrewParshaMap.put(JewishCalendar.Parsha.SHKALIM, "\u05E9\u05E7\u05DC\u05D9\u05DD");
262                hebrewParshaMap.put(JewishCalendar.Parsha.ZACHOR, "\u05D6\u05DB\u05D5\u05E8");
263                hebrewParshaMap.put(JewishCalendar.Parsha.PARA, "\u05E4\u05E8\u05D4");
264                hebrewParshaMap.put(JewishCalendar.Parsha.HACHODESH, "\u05D4\u05D7\u05D3\u05E9");
265                hebrewParshaMap.put(JewishCalendar.Parsha.SHUVA, "\u05E9\u05D5\u05D1\u05D4");
266                hebrewParshaMap.put(JewishCalendar.Parsha.SHIRA, "\u05E9\u05D9\u05E8\u05D4");
267                hebrewParshaMap.put(JewishCalendar.Parsha.HAGADOL, "\u05D4\u05D2\u05D3\u05D5\u05DC");
268                hebrewParshaMap.put(JewishCalendar.Parsha.CHAZON, "\u05D7\u05D6\u05D5\u05DF");
269                hebrewParshaMap.put(JewishCalendar.Parsha.NACHAMU, "\u05E0\u05D7\u05DE\u05D5");
270        }
271
272        /**
273         * Returns if the {@link #formatDayOfWeek(JewishDate)} will use the long format such as
274         * &#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF; or short such as &#x05D0; when formatting the day of week in
275         * {@link #isHebrewFormat() Hebrew}.
276         * 
277         * @return the longWeekFormat
278         * @see #setLongWeekFormat(boolean)
279         * @see #formatDayOfWeek(JewishDate)
280         */
281        public boolean isLongWeekFormat() {
282                return longWeekFormat;
283        }
284
285        /**
286         * Setting to control if the {@link #formatDayOfWeek(JewishDate)} will use the long format such as
287         * &#x05E8;&#x05D0;&#x05E9;&#x05D5;&#x05DF; or short such as &#x05D0; when formatting the day of week in
288         * {@link #isHebrewFormat() Hebrew}.
289         * 
290         * @param longWeekFormat
291         *            the longWeekFormat to set
292         */
293        public void setLongWeekFormat(boolean longWeekFormat) {
294                this.longWeekFormat = longWeekFormat;
295                if(longWeekFormat) {
296                        weekFormat = new SimpleDateFormat("EEEE");
297                } else {
298                        weekFormat = new SimpleDateFormat("EEE");
299                }
300        }
301
302        /**
303         * The <a href="https://en.wikipedia.org/wiki/Geresh#Punctuation_mark">gersh</a> character is the &#x05F3; char
304         * that is similar to a single quote and is used in formatting Hebrew numbers.
305         */
306        private static final String GERESH = "\u05F3";
307        
308        /**
309         * The <a href="https://en.wikipedia.org/wiki/Gershayim#Punctuation_mark">gershyim</a> character is the &#x05F4; char
310         * that is similar to a double quote and is used in formatting Hebrew numbers.
311         */
312        private static final String GERSHAYIM = "\u05F4";
313        
314        /**
315         * Transliterated month names.&nbsp; Defaults to ["Nissan", "Iyar", "Sivan", "Tammuz", "Av", "Elul", "Tishrei", "Cheshvan",
316         * "Kislev", "Teves", "Shevat", "Adar", "Adar II", "Adar I" ].
317         * @see #getTransliteratedMonthList()
318         * @see #setTransliteratedMonthList(String[])
319         */
320        private String[] transliteratedMonths = { "Nissan", "Iyar", "Sivan", "Tammuz", "Av", "Elul", "Tishrei", "Cheshvan",
321                        "Kislev", "Teves", "Shevat", "Adar", "Adar II", "Adar I" };
322        
323        /**
324         * The Hebrew omer prefix charachter. It defaults to &#x05D1; producing &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;,
325         * but can be set to &#x05DC; to produce &#x05DC;&#x05E2;&#x05D5;&#x05DE;&#x05E8; (or any other prefix).
326         * @see #getHebrewOmerPrefix()
327         * @see #setHebrewOmerPrefix(String)
328         */
329        private String hebrewOmerPrefix = "\u05D1";
330
331        /**
332         * The default value for formatting Shabbos (Saturday).&nbsp; Defaults to Shabbos.
333         * @see #getTransliteratedShabbosDayOfWeek()
334         * @see #setTransliteratedShabbosDayOfWeek(String)
335         */
336        private String transliteratedShabbosDayOfweek = "Shabbos";
337
338        /**
339         * Returns the day of Shabbos transliterated into Latin chars. The default uses Ashkenazi pronunciation "Shabbos".
340         * This can be overwritten using the {@link #setTransliteratedShabbosDayOfWeek(String)}
341         * 
342         * @return the transliteratedShabbos. The default list of months uses Ashkenazi pronunciation "Shabbos".
343         * @see #setTransliteratedShabbosDayOfWeek(String)
344         * @see #formatDayOfWeek(JewishDate)
345         */
346        public String getTransliteratedShabbosDayOfWeek() {
347                return transliteratedShabbosDayOfweek;
348        }
349
350        /**
351         * Setter to override the default transliterated name of "Shabbos" to alternate spelling such as "Shabbat" used by
352         * the {@link #formatDayOfWeek(JewishDate)}
353         * 
354         * @param transliteratedShabbos
355         *            the transliteratedShabbos to set
356         * 
357         * @see #getTransliteratedShabbosDayOfWeek()
358         * @see #formatDayOfWeek(JewishDate)
359         */
360        public void setTransliteratedShabbosDayOfWeek(String transliteratedShabbos) {
361                this.transliteratedShabbosDayOfweek = transliteratedShabbos;
362        }
363
364        /**
365         * See {@link #getTransliteratedHolidayList()} and {@link #setTransliteratedHolidayList(String[])}.
366         */
367        private String[] transliteratedHolidays = {"Erev Pesach", "Pesach", "Chol Hamoed Pesach", "Pesach Sheni",
368                        "Erev Shavuos", "Shavuos", "Seventeenth of Tammuz", "Tishah B'Av", "Tu B'Av", "Erev Rosh Hashana",
369                        "Rosh Hashana", "Fast of Gedalyah", "Erev Yom Kippur", "Yom Kippur", "Erev Succos", "Succos",
370                        "Chol Hamoed Succos", "Hoshana Rabbah", "Shemini Atzeres", "Simchas Torah", "Erev Chanukah", "Chanukah",
371                        "Tenth of Teves", "Tu B'Shvat", "Fast of Esther", "Purim", "Shushan Purim", "Purim Katan", "Rosh Chodesh",
372                        "Yom HaShoah", "Yom Hazikaron", "Yom Ha'atzmaut", "Yom Yerushalayim", "Lag B'Omer","Shushan Purim Katan",
373                        "Isru Chag"};
374
375        /**
376         * Returns the list of holidays transliterated into Latin chars. This is used by the
377         * {@link #formatYomTov(JewishCalendar)} when formatting the Yom Tov String. The default list of months uses
378         * Ashkenazi pronunciation in typical American English spelling.
379         * 
380         * @return the list of transliterated holidays. The default list is currently ["Erev Pesach", "Pesach",
381         *         "Chol Hamoed Pesach", "Pesach Sheni", "Erev Shavuos", "Shavuos", "Seventeenth of Tammuz", "Tishah B'Av",
382         *         "Tu B'Av", "Erev Rosh Hashana", "Rosh Hashana", "Fast of Gedalyah", "Erev Yom Kippur", "Yom Kippur",
383         *         "Erev Succos", "Succos", "Chol Hamoed Succos", "Hoshana Rabbah", "Shemini Atzeres", "Simchas Torah",
384         *         "Erev Chanukah", "Chanukah", "Tenth of Teves", "Tu B'Shvat", "Fast of Esther", "Purim", "Shushan Purim",
385         *         "Purim Katan", "Rosh Chodesh", "Yom HaShoah", "Yom Hazikaron", "Yom Ha'atzmaut", "Yom Yerushalayim",
386         *         "Lag B'Omer","Shushan Purim Katan","Isru Chag"].
387         * 
388         * @see #setTransliteratedMonthList(String[])
389         * @see #formatYomTov(JewishCalendar)
390         * @see #isHebrewFormat()
391         */
392        public String[] getTransliteratedHolidayList() {
393                return transliteratedHolidays;
394        }
395
396        /**
397         * Sets the list of holidays transliterated into Latin chars. This is used by the
398         * {@link #formatYomTov(JewishCalendar)} when formatting the Yom Tov String.
399         * 
400         * @param transliteratedHolidays
401         *            the transliteratedHolidays to set. Ensure that the sequence exactly matches the list returned by the
402         *            default
403         */
404        public void setTransliteratedHolidayList(String[] transliteratedHolidays) {
405                this.transliteratedHolidays = transliteratedHolidays;
406        }
407
408        /**
409         * Hebrew holiday array in the following format.<br><code>["&#x05E2;&#x05E8;&#x05D1; &#x05E4;&#x05E1;&#x05D7;",
410         * "&#x05E4;&#x05E1;&#x05D7;", "&#x05D7;&#x05D5;&#x05DC; &#x05D4;&#x05DE;&#x05D5;&#x05E2;&#x05D3;
411         * &#x05E4;&#x05E1;&#x05D7;", "&#x05E4;&#x05E1;&#x05D7; &#x05E9;&#x05E0;&#x05D9;", "&#x05E2;&#x05E8;&#x05D1;
412         * &#x05E9;&#x05D1;&#x05D5;&#x05E2;&#x05D5;&#x05EA;", "&#x05E9;&#x05D1;&#x05D5;&#x05E2;&#x05D5;&#x05EA;",
413         * "&#x05E9;&#x05D1;&#x05E2;&#x05D4; &#x05E2;&#x05E9;&#x05E8; &#x05D1;&#x05EA;&#x05DE;&#x05D5;&#x05D6;",
414         * "&#x05EA;&#x05E9;&#x05E2;&#x05D4; &#x05D1;&#x05D0;&#x05D1;",
415         * "&#x05D8;&#x05F4;&#x05D5; &#x05D1;&#x05D0;&#x05D1;",
416         * "&#x05E2;&#x05E8;&#x05D1; &#x05E8;&#x05D0;&#x05E9; &#x05D4;&#x05E9;&#x05E0;&#x05D4;",
417         * "&#x05E8;&#x05D0;&#x05E9; &#x05D4;&#x05E9;&#x05E0;&#x05D4;",
418         * "&#x05E6;&#x05D5;&#x05DD; &#x05D2;&#x05D3;&#x05DC;&#x05D9;&#x05D4;",
419         * "&#x05E2;&#x05E8;&#x05D1; &#x05D9;&#x05D5;&#x05DD; &#x05DB;&#x05D9;&#x05E4;&#x05D5;&#x05E8;",
420         * "&#x05D9;&#x05D5;&#x05DD; &#x05DB;&#x05D9;&#x05E4;&#x05D5;&#x05E8;",
421         * "&#x05E2;&#x05E8;&#x05D1; &#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
422         * "&#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
423         * "&#x05D7;&#x05D5;&#x05DC; &#x05D4;&#x05DE;&#x05D5;&#x05E2;&#x05D3; &#x05E1;&#x05D5;&#x05DB;&#x05D5;&#x05EA;",
424         * "&#x05D4;&#x05D5;&#x05E9;&#x05E2;&#x05E0;&#x05D0; &#x05E8;&#x05D1;&#x05D4;",
425         * "&#x05E9;&#x05DE;&#x05D9;&#x05E0;&#x05D9; &#x05E2;&#x05E6;&#x05E8;&#x05EA;",
426         * "&#x05E9;&#x05DE;&#x05D7;&#x05EA; &#x05EA;&#x05D5;&#x05E8;&#x05D4;",
427         * "&#x05E2;&#x05E8;&#x05D1; &#x05D7;&#x05E0;&#x05D5;&#x05DB;&#x05D4;",
428         * "&#x05D7;&#x05E0;&#x05D5;&#x05DB;&#x05D4;", "&#x05E2;&#x05E9;&#x05E8;&#x05D4; &#x05D1;&#x05D8;&#x05D1;&#x05EA;",
429         * "&#x05D8;&#x05F4;&#x05D5; &#x05D1;&#x05E9;&#x05D1;&#x05D8;",
430         * "&#x05EA;&#x05E2;&#x05E0;&#x05D9;&#x05EA; &#x05D0;&#x05E1;&#x05EA;&#x05E8;",
431         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD;",
432         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD; &#x05E9;&#x05D5;&#x05E9;&#x05DF;",
433         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD; &#x05E7;&#x05D8;&#x05DF;",
434         * "&#x05E8;&#x05D0;&#x05E9; &#x05D7;&#x05D5;&#x05D3;&#x05E9;",
435         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05E9;&#x05D5;&#x05D0;&#x05D4;",
436         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05D6;&#x05D9;&#x05DB;&#x05E8;&#x05D5;&#x05DF;",
437         * "&#x05D9;&#x05D5;&#x05DD; &#x05D4;&#x05E2;&#x05E6;&#x05DE;&#x05D0;&#x05D5;&#x05EA;",
438         * "&#x05D9;&#x05D5;&#x05DD; &#x05D9;&#x05E8;&#x05D5;&#x05E9;&#x05DC;&#x05D9;&#x05DD;",
439         * "&#x05DC;&#x05F4;&#x05D2; &#x05D1;&#x05E2;&#x05D5;&#x05DE;&#x05E8;",
440         * "&#x05E4;&#x05D5;&#x05E8;&#x05D9;&#x05DD; &#x05E9;&#x05D5;&#x05E9;&#x05DF; &#x05E7;&#x05D8;&#x05DF;"]</code>
441         */
442        private final String[] hebrewHolidays = { "\u05E2\u05E8\u05D1 \u05E4\u05E1\u05D7", "\u05E4\u05E1\u05D7",
443                        "\u05D7\u05D5\u05DC \u05D4\u05DE\u05D5\u05E2\u05D3 \u05E4\u05E1\u05D7",
444                        "\u05E4\u05E1\u05D7 \u05E9\u05E0\u05D9", "\u05E2\u05E8\u05D1 \u05E9\u05D1\u05D5\u05E2\u05D5\u05EA",
445                        "\u05E9\u05D1\u05D5\u05E2\u05D5\u05EA",
446                        "\u05E9\u05D1\u05E2\u05D4 \u05E2\u05E9\u05E8 \u05D1\u05EA\u05DE\u05D5\u05D6",
447                        "\u05EA\u05E9\u05E2\u05D4 \u05D1\u05D0\u05D1", "\u05D8\u05F4\u05D5 \u05D1\u05D0\u05D1",
448                        "\u05E2\u05E8\u05D1 \u05E8\u05D0\u05E9 \u05D4\u05E9\u05E0\u05D4",
449                        "\u05E8\u05D0\u05E9 \u05D4\u05E9\u05E0\u05D4", "\u05E6\u05D5\u05DD \u05D2\u05D3\u05DC\u05D9\u05D4",
450                        "\u05E2\u05E8\u05D1 \u05D9\u05D5\u05DD \u05DB\u05D9\u05E4\u05D5\u05E8",
451                        "\u05D9\u05D5\u05DD \u05DB\u05D9\u05E4\u05D5\u05E8", "\u05E2\u05E8\u05D1 \u05E1\u05D5\u05DB\u05D5\u05EA",
452                        "\u05E1\u05D5\u05DB\u05D5\u05EA",
453                        "\u05D7\u05D5\u05DC \u05D4\u05DE\u05D5\u05E2\u05D3 \u05E1\u05D5\u05DB\u05D5\u05EA",
454                        "\u05D4\u05D5\u05E9\u05E2\u05E0\u05D0 \u05E8\u05D1\u05D4",
455                        "\u05E9\u05DE\u05D9\u05E0\u05D9 \u05E2\u05E6\u05E8\u05EA",
456                        "\u05E9\u05DE\u05D7\u05EA \u05EA\u05D5\u05E8\u05D4", "\u05E2\u05E8\u05D1 \u05D7\u05E0\u05D5\u05DB\u05D4",
457                        "\u05D7\u05E0\u05D5\u05DB\u05D4", "\u05E2\u05E9\u05E8\u05D4 \u05D1\u05D8\u05D1\u05EA",
458                        "\u05D8\u05F4\u05D5 \u05D1\u05E9\u05D1\u05D8", "\u05EA\u05E2\u05E0\u05D9\u05EA \u05D0\u05E1\u05EA\u05E8",
459                        "\u05E4\u05D5\u05E8\u05D9\u05DD", "\u05E4\u05D5\u05E8\u05D9\u05DD \u05E9\u05D5\u05E9\u05DF",
460                        "\u05E4\u05D5\u05E8\u05D9\u05DD \u05E7\u05D8\u05DF", "\u05E8\u05D0\u05E9 \u05D7\u05D5\u05D3\u05E9",
461                        "\u05D9\u05D5\u05DD \u05D4\u05E9\u05D5\u05D0\u05D4",
462                        "\u05D9\u05D5\u05DD \u05D4\u05D6\u05D9\u05DB\u05E8\u05D5\u05DF",
463                        "\u05D9\u05D5\u05DD \u05D4\u05E2\u05E6\u05DE\u05D0\u05D5\u05EA",
464                        "\u05D9\u05D5\u05DD \u05D9\u05E8\u05D5\u05E9\u05DC\u05D9\u05DD",
465                        "\u05DC\u05F4\u05D2 \u05D1\u05E2\u05D5\u05DE\u05E8",
466                        "\u05E4\u05D5\u05E8\u05D9\u05DD \u05E9\u05D5\u05E9\u05DF \u05E7\u05D8\u05DF",
467                        "\u05D0\u05E1\u05E8\u05D5 \u05D7\u05D2"};
468
469        /**
470         * Formats the Yom Tov (holiday) in Hebrew or transliterated Latin characters.
471         * 
472         * @param jewishCalendar the JewishCalendar
473         * @return the formatted holiday or an empty String if the day is not a holiday.
474         * @see #isHebrewFormat()
475         */
476        public String formatYomTov(JewishCalendar jewishCalendar) {
477                int index = jewishCalendar.getYomTovIndex();
478                if (index == JewishCalendar.CHANUKAH) {
479                        int dayOfChanukah = jewishCalendar.getDayOfChanukah();
480                        return hebrewFormat ? (formatHebrewNumber(dayOfChanukah) + " " + hebrewHolidays[index])
481                                        : (transliteratedHolidays[index] + " " + dayOfChanukah);
482                }
483                return index == -1 ? "" : hebrewFormat ? hebrewHolidays[index] : transliteratedHolidays[index];
484        }
485
486        /**
487         * Formats a day as Rosh Chodesh in the format of in the format of &#x05E8;&#x05D0;&#x05E9;
488         * &#x05D7;&#x05D5;&#x05D3;&#x05E9; &#x05E9;&#x05D1;&#x05D8; or Rosh Chodesh Shevat. If it
489         * is not Rosh Chodesh, an empty <code>String</code> will be returned.
490         * @param jewishCalendar the JewishCalendar
491         * @return The formatted <code>String</code> in the format of &#x05E8;&#x05D0;&#x05E9;
492         * &#x05D7;&#x05D5;&#x05D3;&#x05E9; &#x05E9;&#x05D1;&#x05D8; or Rosh Chodesh Shevat. If it
493         * is not Rosh Chodesh, an empty <code>String</code> will be returned.
494         */
495        public String formatRoshChodesh(JewishCalendar jewishCalendar) {
496                if (!jewishCalendar.isRoshChodesh()) {
497                        return "";
498                }
499                String formattedRoshChodesh = "";
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                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 list 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 list of months beginning in Nissan and ending in 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 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 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         * or &#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 - 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 word thousand (overide 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 divisable 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         * Retruns the list of transliterated parshiyos used by this formatter.
1019         * 
1020         * @return the list 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 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). If the formatter is set to format in Hebrew, returns
1040         * a string of the current parsha(ios) in Hebrew for example &#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA; or
1041         * &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA; or an empty string if there
1042         * are none. If not set to Hebrew, it returns a string of the parsha(ios) transliterated into Latin chars. The
1043         * default uses Ashkenazi pronunciation in typical American English spelling, for example Bereshis or
1044         * Nitzavim Vayeilech or an empty string if there are none.
1045         * 
1046         * @param jewishCalendar the JewishCalendar Object
1047         * @return today's parsha(ios) in Hebrew for example, if the formatter is set to format in Hebrew, returns a string
1048         *         of the current parsha(ios) in Hebrew for example &#x05D1;&#x05E8;&#x05D0;&#x05E9;&#x05D9;&#x05EA; or
1049         *         &#x05E0;&#x05E6;&#x05D1;&#x05D9;&#x05DD; &#x05D5;&#x05D9;&#x05DC;&#x05DA; or an empty string if
1050         *         there are none. If not set to Hebrew, it returns a string of the parsha(ios) transliterated into Latin
1051         *         chars. The default uses Ashkenazi pronunciation in typical American English spelling, for example
1052         *         Bereshis or Nitzavim Vayeilech or an empty string if there are none.
1053         */
1054        public String formatParsha(JewishCalendar jewishCalendar) {
1055                JewishCalendar.Parsha parsha =  jewishCalendar.getParshah();
1056                return hebrewFormat ? hebrewParshaMap.get(parsha) : transliteratedParshaMap.get(parsha);
1057        }
1058        
1059        /**
1060         * Returns a String with the name of the current special parsha of Shekalim, Zachor, Parah or Hachodesh or an
1061         * empty String for a non-special parsha. If the formatter is set to format in Hebrew, it returns a string of
1062         * the current special parsha in Hebrew, for example &#x05E9;&#x05E7;&#x05DC;&#x05D9;&#x05DD;,
1063         * &#x05D6;&#x05DB;&#x05D5;&#x05E8;, &#x05E4;&#x05E8;&#x05D4; or &#x05D4;&#x05D7;&#x05D3;&#x05E9;. An empty
1064         * string if the date is not a special parsha. If not set to Hebrew, it returns a string of the special parsha
1065         * transliterated into Latin chars. The default uses Ashkenazi pronunciation in typical American English spelling
1066         * Shekalim, Zachor, Parah or Hachodesh.
1067         * 
1068         * @param jewishCalendar the JewishCalendar Object
1069         * @return today's special parsha. If the formatter is set to format in Hebrew, returns a string
1070         *         of the current special parsha  in Hebrew for in the format of &#x05E9;&#x05E7;&#x05DC;&#x05D9;&#x05DD;,
1071         *         &#x05D6;&#x05DB;&#x05D5;&#x05E8;, &#x05E4;&#x05E8;&#x05D4; or &#x05D4;&#x05D7;&#x05D3;&#x05E9; or an empty
1072         *         string if there are none. If not set to Hebrew, it returns a string of the special parsha transliterated
1073         *         into Latin chars. The default uses Ashkenazi pronunciation in typical American English spelling of Shekalim,
1074         *         Zachor, Parah or Hachodesh. An empty string if there are none.
1075         */
1076        public String formatSpecialParsha(JewishCalendar jewishCalendar) {
1077                JewishCalendar.Parsha specialParsha =  jewishCalendar.getSpecialShabbos();
1078                return hebrewFormat ? hebrewParshaMap.get(specialParsha) : transliteratedParshaMap.get(specialParsha);
1079        }
1080}