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