001/*
002 * Zmanim Java API
003 * Copyright (C) 2004-2011 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 net.sourceforge.zmanim;
017
018import java.util.Date;
019
020import net.sourceforge.zmanim.util.AstronomicalCalculator;
021import net.sourceforge.zmanim.util.GeoLocation;
022
023/**
024 * The ZmanimCalendar is a specialized calendar that can calculate sunrise and sunset and Jewish <em>zmanim</em>
025 * (religious times) for prayers and other Jewish religious duties. This class contains the main functionality of the
026 * Zmanim library. For a much more extensive list of zmanim use the {@link ComplexZmanimCalendar} that extends this
027 * class. See documentation for the {@link ComplexZmanimCalendar} and {@link AstronomicalCalendar} for simple examples
028 * on using the API. <br/>
029 * <b>Note:</b> It is important to read the technical notes on top of the {@link AstronomicalCalculator} documentation.
030 * <h2>Disclaimer:</h2> I did my best to get accurate results but please do not rely on these zmanim for
031 * <em>halacha lemaaseh</em>.
032 * 
033 * @author &copy; Eliyahu Hershfeld 2004 - 2011
034 * @version 1.2.1
035 */
036public class ZmanimCalendar extends AstronomicalCalendar {
037
038        /**
039         * The zenith of 16.1&deg; below geometric zenith (90&deg;). This calculation is used for determining <em>alos</em>
040         * (dawn) and <em>tzais</em> (nightfall) in some opinions. It is based on the calculation that the time between dawn
041         * and sunrise (and sunset to nightfall) is 72 minutes, the time that is takes to walk 4 <em>mil</em> at 18 minutes
042         * a mil (<em>Rambam</em> and others). The sun's position at 72 minutes before {@link #getSunrise sunrise} in
043         * Jerusalem on the equinox is 16.1&deg; below {@link #GEOMETRIC_ZENITH geometric zenith}.
044         * 
045         * @see #getAlosHashachar()
046         * @see ComplexZmanimCalendar#getAlos16Point1Degrees()
047         * @see ComplexZmanimCalendar#getTzais16Point1Degrees()
048         * @see ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees()
049         * @see ComplexZmanimCalendar#getSofZmanTfilaMGA16Point1Degrees()
050         * @see ComplexZmanimCalendar#getMinchaGedola16Point1Degrees()
051         * @see ComplexZmanimCalendar#getMinchaKetana16Point1Degrees()
052         * @see ComplexZmanimCalendar#getPlagHamincha16Point1Degrees()
053         * @see ComplexZmanimCalendar#getPlagAlos16Point1ToTzaisGeonim7Point083Degrees()
054         * @see ComplexZmanimCalendar#getSofZmanShmaAlos16Point1ToSunset()
055         */
056        protected static final double ZENITH_16_POINT_1 = GEOMETRIC_ZENITH + 16.1;
057
058        /**
059         * The zenith of 8.5&deg; below geometric zenith (90&deg;). This calculation is used for calculating <em>alos</em>
060         * (dawn) and <em>tzais</em> (nightfall) in some opinions. This calculation is based on the position of the sun 36
061         * minutes after {@link #getSunset sunset} in Jerusalem on March 16, about 4 days before the equinox, the day that a
062         * solar hour is 60 minutes, which is 8.5&deg; below {@link #GEOMETRIC_ZENITH geometric zenith}. The Ohr Meir
063         * considers this the time that 3 small stars are visible, which is later than the required 3 medium stars.
064         * 
065         * @see #getTzais()
066         * @see ComplexZmanimCalendar#getTzaisGeonim8Point5Degrees()
067         */
068        protected static final double ZENITH_8_POINT_5 = GEOMETRIC_ZENITH + 8.5;
069
070        /**
071         * The default Shabbos candle lighting offset is 18 minutes. This can be changed via the
072         * {@link #setCandleLightingOffset(double)} and retrieved by the {@link #getCandleLightingOffset()}.
073         */
074        private double candleLightingOffset = 18;
075
076        /**
077         * A method that returns <em>tzais</em> (nightfall) when the sun is 8.5&deg; below the western geometric horizon
078         * (90&deg;) after {@link #getSunset sunset}. For information on the source of this calculation see
079         * {@link #ZENITH_8_POINT_5}.
080         * 
081         * @return The <code>Date</code> of nightfall. If the calculation can't be computed such as northern and southern
082         *         locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may not reach
083         *         low enough below the horizon for this calculation, a null will be returned. See detailed explanation on
084         *         top of the {@link AstronomicalCalendar} documentation.
085         * @see #ZENITH_8_POINT_5
086         */
087        public Date getTzais() {
088                return this.getSunsetOffsetByDegrees(ZENITH_8_POINT_5);
089        }
090
091        /**
092         * Returns <em>alos</em> (dawn) based on the time when the sun is 16.1&deg; below the eastern
093         * {@link #GEOMETRIC_ZENITH geometric horizon} before {@link #getSunrise sunrise}. For more information the source
094         * of 16.1&deg; see {@link #ZENITH_16_POINT_1}.
095         * 
096         * @see net.sourceforge.zmanim.ZmanimCalendar#ZENITH_16_POINT_1
097         * @return The <code>Date</code> of dawn. If the calculation can't be computed such as northern and southern
098         *         locations even south of the Arctic Circle and north of the Antarctic Circle where the sun may not reach
099         *         low enough below the horizon for this calculation, a null will be returned. See detailed explanation on
100         *         top of the {@link AstronomicalCalendar} documentation.
101         */
102        public Date getAlosHashachar() {
103                return getSunriseOffsetByDegrees(ZENITH_16_POINT_1);
104        }
105
106        /**
107         * Method to return <em>alos</em> (dawn) calculated using 72 minutes before {@link #getSeaLevelSunrise() sea level
108         * sunrise} (no adjustment for elevation) based on the time to walk the distance of 4 <em>Mil</em> at 18 minutes a
109         * <em>Mil</em>. This is based on the opinion of most <em>Rishonim</em> who stated that the time of the
110         * <em>Neshef</em> (time between dawn and sunrise) does not vary by the time of year or location but purely depends
111         * on the time it takes to walk the distance of 4 <em>Mil</em>.
112         * 
113         * @return the <code>Date</code> representing the time. If the calculation can't be computed such as in the Arctic
114         *         Circle where there is at least one day a year where the sun does not rise, and one where it does not set,
115         *         a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
116         *         documentation.
117         */
118        public Date getAlos72() {
119                return getTimeOffset(getSeaLevelSunrise(), -72 * MINUTE_MILLIS);
120        }
121
122        /**
123         * This method returns <em>chatzos</em> (midday) following the opinion of the GRA that the day for Jewish halachic
124         * times start at {@link #getSunrise sunrise} and ends at {@link #getSunset sunset}. The returned value is identical
125         * to {@link #getSunTransit()}
126         * 
127         * @see AstronomicalCalendar#getSunTransit()
128         * @return the <code>Date</code> of chatzos. If the calculation can't be computed such as in the Arctic Circle where
129         *         there is at least one day where the sun does not rise, and one where it does not set, a null will be
130         *         returned. See detailed explanation on top of the {@link AstronomicalCalendar} documentation.
131         */
132        public Date getChatzos() {
133                return getSunTransit();
134        }
135
136        /**
137         * This method returns the latest <em>zman krias shema</em> (time to recite Shema in the morning). This time is 3
138         * <em>{@link #getShaahZmanisGra() shaos zmaniyos}</em> (solar hours) after {@link #getSeaLevelSunrise() sea level
139         * sunrise} based on the opinion of the <em>GRA</em> and the <em>Baal Hatanya</em> that the day is calculated from
140         * sunrise to sunset. This returns the time 3 * {@link #getShaahZmanisGra()} after {@link #getSeaLevelSunrise() sea
141         * level sunrise}.
142         * 
143         * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
144         * @return the <code>Date</code> of the latest zman shema according to the GRA and Baal Hatanya. If the calculation
145         *         can't be computed such as in the Arctic Circle where there is at least one day a year where the sun does
146         *         not rise, and one where it does not set, a null will be returned. See detailed explanation on top of the
147         *         {@link AstronomicalCalendar} documentation.
148         */
149        public Date getSofZmanShmaGRA() {
150                return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 3);
151        }
152
153        /**
154         * This method returns the latest <em>zman krias shema</em> (time to recite shema in the morning) in the opinion of
155         * the <em>MGA</em> based on <em>alos</em> being 72 minutes before {@link #getSunrise() sunrise}. This time is 3
156         * <em> shaos zmaniyos</em> (solar hours) after dawn based on the opinion of the <em>MGA</em> that the day is
157         * calculated from a dawn of 72 minutes before sunrise to nightfall of 72 minutes after sunset. This returns the
158         * time of 3 * <em>shaos zmaniyos</em> after dawn.
159         * 
160         * @return the <code>Date</code> of the latest zman shema. If the calculation can't be computed such as in the
161         *         Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
162         *         not set, a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
163         *         documentation.
164         * @see ComplexZmanimCalendar#getShaahZmanis72Minutes()
165         * @see ComplexZmanimCalendar#getAlos72()
166         * @see ComplexZmanimCalendar#getSofZmanShmaMGA72Minutes()
167         */
168        public Date getSofZmanShmaMGA() {
169                return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 3);
170        }
171
172        /**
173         * This method returns the <em>tzais</em> (nightfall) based on the opinion of the <em>Rambam</em> and
174         * <em>Rabainu Tam</em> that <em>tzais</em> is calculated as 72 minutes, the time it takes to walk 4 <em>Mil</em> at
175         * 18 minutes a <em>Mil</em>. Even for locations above sea level, this is calculated at sea level, since the
176         * darkness level is not affected by elevation.
177         * 
178         * @return the <code>Date</code> representing 72 minutes after sea level sunset. If the calculation can't be
179         *         computed such as in the Arctic Circle where there is at least one day a year where the sun does not rise,
180         *         and one where it does not set, a null will be returned See detailed explanation on top of the
181         *         {@link AstronomicalCalendar} documentation.
182         */
183        public Date getTzais72() {
184                return getTimeOffset(getSeaLevelSunset(), 72 * MINUTE_MILLIS);
185        }
186
187        /**
188         * A method to return candle lighting time. This is calculated as {@link #getCandleLightingOffset()} minutes before
189         * sunset. This will return the time for any day of the week, since it can be used to calculate candle lighting time
190         * for <em>yom tov</em> (mid-week holidays) as well.
191         * 
192         * @return candle lighting time. If the calculation can't be computed such as in the Arctic Circle where there is at
193         *         least one day a year where the sun does not rise, and one where it does not set, a null will be returned.
194         *         See detailed explanation on top of the {@link AstronomicalCalendar} documentation.
195         * @see #getCandleLightingOffset()
196         * @see #setCandleLightingOffset(double)
197         */
198        public Date getCandleLighting() {
199                return getTimeOffset(getSunset(), -getCandleLightingOffset() * MINUTE_MILLIS);
200        }
201
202        /**
203         * This method returns the latest <em>zman tefilah<em> (time to recite the morning prayers). This time is 4
204         * hours into the day based on the opinion of the <em>GRA</em> and the </em>Baal Hatanya</em> that the day is
205         * calculated from sunrise to sunset. This returns the time 4 * {@link #getShaahZmanisGra()} after
206         * {@link #getSeaLevelSunrise() sea level sunrise}.
207         * 
208         * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
209         * @return the <code>Date</code> of the latest zman tefilah. If the calculation can't be computed such as in the
210         *         Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
211         *         not set, a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
212         *         documentation.
213         */
214        public Date getSofZmanTfilaGRA() {
215                return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 4);
216        }
217
218        /**
219         * This method returns the latest <em>zman tfila</em> (time to recite the morning prayers) in the opinion of the
220         * <em>MGA</em> based on <em>alos</em> being {@link #getAlos72() 72} minutes before {@link #getSunrise() sunrise}.
221         * This time is 4 <em>{@link #getShaahZmanisMGA() shaos zmaniyos}</em> (temporal hours) after {@link #getAlos72()
222         * dawn} based on the opinion of the <em>MGA</em> that the day is calculated from a {@link #getAlos72() dawn} of 72
223         * minutes before sunrise to {@link #getTzais72() nightfall} of 72 minutes after sunset. This returns the time of 4
224         * * {@link #getShaahZmanisMGA()} after {@link #getAlos72() dawn}.
225         * 
226         * @return the <code>Date</code> of the latest zman tfila. If the calculation can't be computed such as in the
227         *         Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
228         *         not set), a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
229         *         documentation.
230         * @see #getShaahZmanisMGA()
231         * @see #getAlos72()
232         */
233        public Date getSofZmanTfilaMGA() {
234                return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 4);
235        }
236
237        /**
238         * This method returns the time of <em>mincha gedola</em>. <em>Mincha gedola</em> is the earliest time one can pray
239         * mincha. The Ramba"m is of the opinion that it is better to delay <em>mincha</em> until
240         * <em>{@link #getMinchaKetana() mincha ketana}</em> while the <em>Ra"sh,
241         * Tur, GRA</em> and others are of the opinion that <em>mincha</em> can be prayed <em>lechatchila</em> starting at
242         * <em>mincha gedola</em>. This is calculated as 6.5 {@link #getShaahZmanisGra() sea level solar hours} after
243         * {@link #getSeaLevelSunrise() sea level sunrise}. This calculation is based on the opinion of the <em>GRA</em> and
244         * the <em>Baal Hatanya</em> that the day is calculated from sunrise to sunset. This returns the time 6.5 *
245         * {@link #getShaahZmanisGra()} after {@link #getSeaLevelSunrise() sea level sunrise}.
246         * 
247         * @see #getShaahZmanisGra()
248         * @see #getMinchaKetana()
249         * @return the <code>Date</code> of the time of mincha gedola. If the calculation can't be computed such as in the
250         *         Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
251         *         not set, a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
252         *         documentation.
253         */
254        public Date getMinchaGedola() {
255                return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 6.5);
256        }
257
258        /**
259         * This method returns the time of <em>mincha ketana</em>. This is the preferred earliest time to pray
260         * <em>mincha</em> in the opinion of the Rambam and others. For more information on this see the documentation on
261         * <em>{@link #getMinchaGedola() mincha gedola}</em>. This is calculated as 9.5 {@link #getShaahZmanisGra() sea
262         * level solar hours} after {@link #getSeaLevelSunrise() sea level sunrise}. This calculation is calculated based on
263         * the opinion of the <em>GRA</em> and the <em>Baal Hatanya</em> that the day is calculated from sunrise to sunset.
264         * This returns the time 9.5 * {@link #getShaahZmanisGra()} after {@link #getSeaLevelSunrise() sea level sunrise}.
265         * 
266         * @see #getShaahZmanisGra()
267         * @see #getMinchaGedola()
268         * @return the <code>Date</code> of the time of mincha ketana. If the calculation can't be computed such as in the
269         *         Arctic Circle where there is at least one day a year where the sun does not rise, and one where it does
270         *         not set, a null will be returned. See detailed explanation on top of the {@link AstronomicalCalendar}
271         *         documentation.
272         */
273        public Date getMinchaKetana() {
274                return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 9.5);
275        }
276
277        /**
278         * This method returns the time of <em>plag hamincha</em>. This is calculated as 10.75 hours after sunrise. This
279         * calculation is based on the opinion of the <em>GRA</em> and the <em>Baal Hatanya</em> that the day is calculated
280         * from sunrise to sunset. This returns the time 10.75 * {@link #getShaahZmanisGra()} after
281         * {@link #getSeaLevelSunrise() sea level sunrise}.
282         * 
283         * @return the <code>Date</code> of the time of <em>plag hamincha</em>. If the calculation can't be computed such as
284         *         in the Arctic Circle where there is at least one day a year where the sun does not rise, and one where it
285         *         does not set, a null will be returned. See detailed explanation on top of the
286         *         {@link AstronomicalCalendar} documentation.
287         */
288        public Date getPlagHamincha() {
289                return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 10.75);
290        }
291
292        /**
293         * A method that returns a <em>shaah zmanis</em> ( {@link #getTemporalHour(Date, Date) temporal hour}) according to
294         * the opinion of the <em>GRA</em> and the <em>Baal Hatanya</em>. This calculation divides the day based on the
295         * opinion of the <em>GRA</em> and the <em>Baal Hatanya</em> that the day runs from {@link #getSeaLevelSunrise()
296         * sunrise} to {@link #getSeaLevelSunrise sunset}. The calculations are based on a day from
297         * {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunset() sea level sunset}. The day is
298         * split into 12 equal parts with each one being a <em>shaah zmanis</em>. This method is similar to
299         * {@link #getTemporalHour}, but all calculations are based on a sealevel sunrise and sunset. An explanation and
300         * detailed sources for not using elevation for anything besides sunrise and sunset can be found in <a
301         * href="http://www.worldcat.org/oclc/659793988">Zmanim Kehilchasam (second edition published in 2007)</a> by Rabbi
302         * Dovid Yehuda Bursztyn chapter 2 (pages 186-187).
303         * 
304         * @return the <code>long</code> millisecond length of a <em>shaah zmanis</em> calculated from
305         *         {@link #getSeaLevelSunrise() sea level sunrise} to {@link #getSeaLevelSunset sea level sunset}. If the
306         *         calculation can't be computed such as in the Arctic Circle where there is at least one day a year where
307         *         the sun does not rise, and one where it does not set, {@link Long#MIN_VALUE} will be returned. See
308         *         detailed explanation on top of the {@link AstronomicalCalendar} documentation.
309         * @see #getTemporalHour(Date, Date)
310         * @see #getSeaLevelSunrise()
311         * @see #getSeaLevelSunset()
312         */
313        public long getShaahZmanisGra() {
314                return getTemporalHour(getSeaLevelSunrise(), getSeaLevelSunset());
315        }
316
317        /**
318         * A method that returns a <em>shaah zmanis</em> (temporal hour) according to the opinion of the Magen Avraham. This
319         * calculation divides the day based on the opinion of the <em>MGA</em> that the day runs from dawn to dusk (for sof
320         * zman krias shema and tfila). Dawn for this calculation is 72 minutes before sunrise and dusk is 72 minutes after
321         * sunset. This day is split into 12 equal parts with each part being a <em>shaah zmanis</em>. Alternate mothods of
322         * calculating a <em>shaah zmanis</em> are available in the subclass {@link ComplexZmanimCalendar}.
323         * 
324         * @return the <code>long</code> millisecond length of a <em>shaah zmanis</em>. If the calculation can't be computed
325         *         such as in the Arctic Circle where there is at least one day a year where the sun does not rise, and one
326         *         where it does not set, {@link Long#MIN_VALUE} will be returned. See detailed explanation on top of the
327         *         {@link AstronomicalCalendar} documentation.
328         */
329        public long getShaahZmanisMGA() {
330                return getTemporalHour(getAlos72(), getTzais72());
331        }
332
333        /**
334         * Default constructor will set a default {@link GeoLocation#GeoLocation()}, a default
335         * {@link AstronomicalCalculator#getDefault() AstronomicalCalculator} and default the calendar to the current date.
336         * 
337         * @see AstronomicalCalendar#AstronomicalCalendar()
338         */
339        public ZmanimCalendar() {
340                super();
341        }
342
343        /**
344         * A constructor that takes a {@link GeoLocation} as a parameter.
345         * 
346         * @param location
347         *            the location
348         */
349        public ZmanimCalendar(GeoLocation location) {
350                super(location);
351        }
352
353        /**
354         * A method to get the offset in minutes before {@link AstronomicalCalendar#getSunset() sunset} which is used in
355         * calculating candle lighting time. The default time used is 18 minutes before sunset. Some calendars use 15
356         * minutes, while the custom in Jerusalem is to use a 40 minute offset. Please check the local custom for candle
357         * lighting time.
358         * 
359         * @return Returns the currently set candle lighting offset in minutes.
360         * @see #getCandleLighting()
361         * @see #setCandleLightingOffset(double)
362         */
363        public double getCandleLightingOffset() {
364                return this.candleLightingOffset;
365        }
366
367        /**
368         * A method to set the offset in minutes before {@link AstronomicalCalendar#getSunset() sunset} that is used in
369         * calculating candle lighting time. The default time used is 18 minutes before sunset. Some calendars use 15
370         * minutes, while the custom in Jerusalem is to use a 40 minute offset.
371         * 
372         * @param candleLightingOffset
373         *            The candle lighting offset to set in minutes.
374         * @see #getCandleLighting()
375         * @see #getCandleLightingOffset()
376         */
377        public void setCandleLightingOffset(double candleLightingOffset) {
378                this.candleLightingOffset = candleLightingOffset;
379        }
380}