001    /*
002     * Zmanim Java API
003     * Copyright (C) 2004-2005 Eliyahu Hershfeld
004     * 
005     * This program is free software; you can redistribute it and/or modify it under the terms of the
006     * GNU General Public License as published by the Free Software Foundation; either version 2 of the
007     * License, or (at your option) any later version.
008     * 
009     * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
010     * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011     * General Public License for more details.
012     * 
013     * You should have received a copy of the GNU General Public License along with this program; if
014     * not, write to the Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA
015     * 02111-1307, USA or connect to: http://www.fsf.org/copyleft/gpl.html
016     */
017    package net.sourceforge.zmanim;
018    
019    import java.util.Date;
020    
021    import net.sourceforge.zmanim.util.GeoLocation;
022    
023    /**
024     * <p>
025     * Description: A Java library for calculating zmanim.
026     * </p>
027     * The zmanim library is an API is a specialized calendar that can calculate
028     * sunrise and sunset and Jewish <em>zmanim</em> (religious times) for prayers
029     * and other Jewish religious duties. For a much more extensive list of zmanim
030     * use the {@link ComplexZmanimCalendar} that extends this class. This class
031     * contains the main functionality of the Zmanim library.
032     * <h2>Disclaimer:</h2>
033     * While I did my best to get accurate results please do not rely on these
034     * zmanim for <em>halacha lemaaseh</em>
035     * 
036     * @author © Eliyahu Hershfeld 2004 - 2007
037     * @version 1.1
038     */
039    public class ZmanimCalendar extends AstronomicalCalendar {
040            private static final long serialVersionUID = 1;
041    
042            /**
043             * The zenith of 16.1° below geometric zenith (90°). This calculation is
044             * used for calculating <em>alos</em> (dawn) and <em>tzais</em>
045             * (nightfall) in some opinions. This calculation is based on the
046             * calculation that the time between dawn and sunrise (and sunset to
047             * nightfall) is the time that is takes to walk 4 <em>mil</em> at 18
048             * minutes a mil (<em>Ramba"m</em> and others). The sun's position at 72
049             * minutes before {@link #getSunrise sunrise} in Jerusalem on the equinox is
050             * 16.1° below {@link #GEOMETRIC_ZENITH geometric zenith}.
051             * 
052             * @see #getAlosHashachar()
053             * @see ComplexZmanimCalendar#getAlos16Point1Degrees()
054             * @see ComplexZmanimCalendar#getTzais16Point1Degrees()
055             * @see ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees()
056             * @see ComplexZmanimCalendar#getSofZmanTfilaMGA16Point1Degrees()
057             * @see ComplexZmanimCalendar#getMinchaGedola16Point1Degrees()
058             * @see ComplexZmanimCalendar#getMinchaKetana16Point1Degrees()
059             * @see ComplexZmanimCalendar#getPlagHamincha16Point1Degrees()
060             * @see ComplexZmanimCalendar#getPlagAlos16Point1ToTzaisGeonim7Point083Degrees()
061             * @see ComplexZmanimCalendar#getSofZmanShmaAlos16Point1ToSunset()
062             */
063            protected static final double ZENITH_16_POINT_1 = GEOMETRIC_ZENITH + 16.1;
064    
065            /**
066             * The zenith of 8.5° below geometric zenith (90°). This calculation is used
067             * for calculating <em>alos</em> (dawn) and <em>tzais</em> (nightfall)
068             * in some opinions. This calculation is based on the position of the sun 36
069             * minutes after {@link #getSunset sunset} in Jerusalem in the equinox which
070             * is 8.5° below {@link #GEOMETRIC_ZENITH geometric zenith}
071             * 
072             * @see #getTzais()
073             * @see ComplexZmanimCalendar#getTzaisGeonim8Point5Degrees()
074             */
075            protected static final double ZENITH_8_POINT_5 = GEOMETRIC_ZENITH + 8.5;
076    
077            // private AstronomicalCalculator astronomicalGeometryCalculator;
078    
079            private double candleLightingOffset = 18;
080    
081            /**
082             * Returns <em>tzais</em> (nightfall) when the sun is 8.5° below the
083             * western geometric horizon (90°) after {@link #getSunset sunset}. For
084             * information on the source of this calculation see
085             * {@link #ZENITH_8_POINT_5}.
086             * 
087             * @return The <code>Date</code> of nightfall.
088             * @see #ZENITH_8_POINT_5
089             */
090            public Date getTzais() {
091                    return this.getSunsetOffsetByDegrees(ZENITH_8_POINT_5);
092            }
093    
094            /**
095             * Returns <em>alos</em> (dawn) based on the time when the sun is 16.1°
096             * below the eastern {@link #GEOMETRIC_ZENITH geometric horizon} before
097             * {@link #getSunrise sunrise}. For more information the source of 16.1°
098             * see {@link #ZENITH_16_POINT_1}.
099             * 
100             * @see net.sourceforge.zmanim.ZmanimCalendar#ZENITH_16_POINT_1
101             * @return The <code>Date</code> of dawn.
102             */
103            public Date getAlosHashachar() {
104                    return getSunriseOffsetByDegrees(ZENITH_16_POINT_1);
105            }
106    
107            /**
108             * Method to return <em>alos</em> (dawn) calculated using 72 minutes
109             * before {@link #getSeaLevelSunrise() sea level sunrise} (no adjustment for
110             * elevation) based on the time to walk the distance of 4 <em>Mil</em> at
111             * 18 minutes a <em>Mil</em>. This is based on the opinion of most
112             * <em>Rishonim</em> who stated that the time of the <em>Neshef</em>
113             * (time between dawn and sunrise) does not vary by the time of year or
114             * location but purely depends on the time it takes to walk the distance of
115             * 4 <em>Mil</em>.
116             * 
117             * @return the <code>Date</code> representing the time.
118             */
119            public Date getAlos72() {
120                    return getTimeOffset(getSeaLevelSunrise(), -72 * MINUTE_MILLIS);
121            }
122    
123            /**
124             * This method returns <em>chatzos</em> (midday) following the opinion of
125             * the GRA that the day for Jewish halachic times start at
126             * {@link #getSunrise sunrise} and ends at {@link #getSunset sunset}. The
127             * returned value is identical to {@link #getSunTransit()}
128             * 
129             * @see AstronomicalCalendar#getSunTransit()
130             * @return the <code>Date</code> of chatzos.
131             */
132            public Date getChatzos() {
133                    return getSunTransit();
134            }
135    
136            /**
137             * This method returns the latest <em>zman krias shema</em> (time to say
138             * Shema in the morning). This time is 3
139             * <em>{@link #getShaahZmanisGra() shaos zmaniyos}</em> (solar hours)
140             * after {@link #getSunrise() sunrise} based on the opinion of the
141             * <em>GR"A</em> and the <em>Baal Hatanya</em> that the day is
142             * calculated from sunrise to sunset. This returns the time 3 *{@link #getShaahZmanisGra()}
143             * after {@link #getSunrise() sunrise}.
144             * 
145             * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
146             * @return the <code>Date</code> of the latest zman shema.
147             */
148            public Date getSofZmanShmaGRA() {
149                    return getTimeOffset(getSunrise(), getShaahZmanisGra() * 3);
150            }
151    
152            /**
153             * This method returns the latest <em>zman krias shema</em> (time to say
154             * Shema in the morning) in the opinion of the <em>MG"A</em> based on
155             * <em>alos</em> being 72 minutes before {@link #getSunrise() sunrise}.
156             * This time is 3 <em> shaos zmaniyos</em> (solar hours) after dawn based
157             * on the opinion of the <em>MG"A</em> that the day is calculated from a
158             * dawn of 72 minutes before sunrise to nightfall of 72 minutes after
159             * sunset. This returns the time of 3 * <em>shaos zmaniyos</em> after
160             * dawn.
161             * 
162             * @return the <code>Date</code> of the latest zman shema.
163             * @see ComplexZmanimCalendar#getShaahZmanis72Minutes()
164             * @see ComplexZmanimCalendar#getAlos72()
165             * @see ComplexZmanimCalendar#getSofZmanShmaMGA72Minutes()
166             */
167            public Date getSofZmanShmaMGA() {
168                    return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 3);
169            }
170    
171            /**
172             * This method returns the <em>tzais</em> (nightfall) based on the opinion
173             * of the <em>Ramba"m</em> and <em>Rabainu Tam</em> that <em>tzais</em>
174             * is calculated as the time it takes to walk 4 <em>Mil</em> at 18 minutes
175             * a <em>Mil</em> for a total of 72 minutes. Even for locations above sea
176             * level, this is calculated at sea level, since the darkness level is not
177             * affected by elevation.
178             * 
179             * @return the <code>Date</code> representing 72 minutes after sea level
180             *         sunset.
181             */
182            public Date getTzais72() {
183                    return getTimeOffset(getSeaLevelSunset(), 72 * MINUTE_MILLIS);
184            }
185    
186            /**
187             * A method to return candle lighting time. This is calculated as
188             * {@link #getCandleLightingOffset()} minutes before sunset. This will
189             * return the time for any day of the week, since it can be used to
190             * calculate candle lighting time for <em>yom tov</em> (holidays) as well.
191             * 
192             * @return candle lighting time.
193             * @see #getCandleLightingOffset()
194             * @see #setCandleLightingOffset(double)
195             */
196            public Date getCandelLighting() {
197                    return getTimeOffset(getSunset(), -getCandleLightingOffset()
198                                    * MINUTE_MILLIS);
199            }
200    
201            /**
202             * This method returns the latest
203             * <em>zman tefilah<em> (time to pray morning prayers). This time is 4
204             * hours into the day based on the opinion of the <em>GR"A</em> and the </em>Baal Hatanya</em>
205             * that the day is calculated from sunrise to sunset. This returns the time
206             * 4 * {@link #getShaahZmanisGra()} after {@link #getSunrise() sunrise}.
207             * 
208             * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
209             * @return the <code>Date</code> of the latest zman tefilah.
210             */
211            public Date getSofZmanTfilaGRA() {
212                    return getTimeOffset(getSunrise(), getShaahZmanisGra() * 4);
213            }
214    
215            /**
216             * This method returns the latest <em>zman tfila</em> (time to say the
217             * morning prayers) in the opinion of the <em>MG"A</em> based on
218             * <em>alos</em> being {@link #getAlos72() 72} minutes before
219             * {@link #getSunrise() sunrise}. This time is 4
220             * <em>{@link #getShaahZmanisMGA() shaos zmaniyos}</em> (temporal hours)
221             * after {@link #getAlos72() dawn} based on the opinion of the <em>MG"A</em>
222             * that the day is calculated from a {@link #getAlos72() dawn} of 72 minutes
223             * before sunrise to {@link #getTzais72() nightfall} of 72 minutes after
224             * sunset. This returns the time of 4 * {@link #getShaahZmanisMGA()} after
225             * {@link #getAlos72() dawn}.
226             * 
227             * @return the <code>Date</code> of the latest zman tfila.
228             * @see #getShaahZmanisMGA()
229             * @see #getAlos72()
230             */
231            public Date getSofZmanTfilaMGA() {
232                    return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 4);
233            }
234    
235            /**
236             * This method returns the time of <em>mincha gedola</em>.<em>Mincha gedola</em>
237             * is the earliest time one can pray mincha. The Ramba"m is of the opinion
238             * that it is better to delay <em>mincha</em> until
239             * <em>{@link #getMinchaKetana() mincha ketana}</em> while the <em>Ra"sh,
240             * Tur, GR"A</em>
241             * and others are of the opinion that <em>mincha</em> can be prayed
242             * <em>lechatchila</em> starting at <em>mincha gedola</em>. This is
243             * calculated as 6.5 {@link #getTemporalHour() solar hours} after sunrise.
244             * This calculation is calculated based on the opinion of the <em>GR"A</em>
245             * and the <em>Baal Hatanya</em> that the day is calculated from sunrise
246             * to sunset. This returns the time 6.5 *{@link #getShaahZmanisGra()} after
247             * {@link #getSunrise() sunrise}.
248             * 
249             * @see #getShaahZmanisGra()
250             * @see #getMinchaKetana()
251             * @return the <code>Date</code> of the time of mincha gedola.
252             */
253            public Date getMinchaGedola() {
254                    return getTimeOffset(getSunrise(), getShaahZmanisGra() * 6.5);
255            }
256    
257            /**
258             * This method returns the time of <em>mincha ketana</em>. This is the
259             * perfered earliest time to pray <em>mincha</em> in the opinion of the
260             * Ramba"m and others. For more information on this see the documentation on
261             * <em>{@link #getMinchaGedola() mincha gedola}</em>. This is calculated
262             * as 9.5 {@link #getTemporalHour() solar hours}after sunrise. This
263             * calculation is calculated based on the opinion of the <em>GR"A</em> and
264             * the <em>Baal Hatanya</em> that the day is calculated from sunrise to
265             * sunset. This returns the time 9.5 * {@link #getShaahZmanisGra()} after
266             * {@link #getSunrise() sunrise}.
267             * 
268             * @see #getShaahZmanisGra()
269             * @see #getMinchaGedola()
270             * @return the <code>Date</code> of the time of mincha gedola.
271             */
272            public Date getMinchaKetana() {
273                    return getTimeOffset(getSunrise(), getShaahZmanisGra() * 9.5);
274            }
275    
276            /**
277             * This method returns he time of <em>plag hamincha</em>. This is
278             * calculated as 10.75 hours after sunrise. This calculation is calculated
279             * based on the opinion of the <em>GR"A</em> and the <em>Baal Hatanya</em>
280             * that the day is calculated from sunrise to sunset. This returns the time
281             * 10.75 *{@link #getShaahZmanisGra()} after {@link #getSunrise() sunrise}.
282             * 
283             * @return the <code>Date</code> of the time of <em>plag hamincha</em>.
284             */
285            public Date getPlagHamincha() {
286                    return getTimeOffset(getSunrise(), getShaahZmanisGra() * 10.75);
287            }
288    
289            /**
290             * Method to return a <em>shaah zmanis</em> ({@link #getTemporalHour temporal hour})
291             * according to the opinion of the <em>GR"A</em> and the
292             * <em>Baal Hatanya</em>. This calculation divides the day based on the
293             * opinion of the <em>GR"A</em> and the <em>Baal Hatanya</em> that the
294             * day runs from {@link #getSunrise() sunrise} to {@link #getSunset sunset}.
295             * The day is split into 12 equal parts each part with each one being a
296             * <em>shaah zmanis</em>. This method is identical to
297             * {@link #getTemporalHour} (it is actually a wrapper that calls that
298             * method) and is provided for clarity.
299             * 
300             * @return the <code>long</code> millisecond length of a
301             *         <em>shaah zmanis</em>.
302             * @see #getTemporalHour()
303             */
304            public long getShaahZmanisGra() {
305                    return getTemporalHour();
306            }
307    
308            /**
309             * Method to return a <em>shaah zmanis</em> (temporal hour) according to
310             * the opinion of the MGA. This calculation divides the day based on the
311             * opinion of the <em>MGA</em> that the day runs from dawn to dusk (for
312             * sof zman krias shema and tfila). Dawn for this calculation is 72 minutes
313             * before sunrise and dusk is 72 minutes after sunset. This day is split
314             * into 12 equal parts with each part being a <em>shaah zmanis</em>.
315             * Alternate mothods of calculating a <em>shaah zmanis</em> are available
316             * in the subclass {@link ComplexZmanimCalendar}.
317             * 
318             * @return the <code>long</code> millisecond length of a
319             *         <em>shaah zmanis</em>.
320             */
321            public long getShaahZmanisMGA() {
322                    return getTemporalHour(getAlos72(), getTzais72());
323            }
324    
325            /**
326             * Constructor for ZmanimCalendar that can use values from the command line
327             * or {@link java.util.Properties} file since all parameters are
328             * {@link java.lang.String String}s.
329             * 
330             * @param locationName
331             *            String the Name of the location
332             * @param latitude
333             *            double The latitude of the geoLocation
334             * @param longitude
335             *            double The longitude of the geoLocation
336             * @param timeZone
337             *            String The timezone for the calculation. Offset to GMT and
338             *            dailight savings time are calculated from the timezone. The
339             *            time zone name has to be a valid Java TimeZone name.
340             * @throws Exception
341             *             thrown when matematical problems arise. Should never happen
342             */
343            /*
344             * public ZmanimCalendar(String locationName, String latitude, String
345             * longitude, String timeZone) throws Exception { super(locationName,
346             * latitude, longitude, timeZone); }
347             */
348    
349            /**
350             * A constructor that takes a {@link GeoLocation} as a parameter.
351             * 
352             * @param location
353             *            the location
354             */
355            public ZmanimCalendar(GeoLocation location) {
356                    super(location);
357            }
358    
359            /**
360             * @see java.lang.Object#equals(Object)
361             */
362            public boolean equals(Object object) {
363                    if (this == object) {
364                            return true;
365                    }
366                    if (!(object instanceof ZmanimCalendar)) {
367                            return false;
368                    }
369                    ZmanimCalendar zCal = (ZmanimCalendar) object;
370                    //return getCalendar().getTime().equals(zCal.getCalendar().getTime())
371                    return getCalendar().equals(zCal.getCalendar())
372                                    && getGeoLocation().equals(zCal.getGeoLocation())
373                                    && getAstronomicalCalculator().equals(
374                                                    zCal.getAstronomicalCalculator());
375            }
376    
377            /**
378             * @see java.lang.Object#hashCode()
379             */
380            public int hashCode() {
381                    int result = 17;
382                    // needed or this and subclasses will return identical hash
383                    result = 37 * result + getClass().hashCode();
384                    result += 37 * result + getCalendar().hashCode();
385                    result += 37 * result + getGeoLocation().hashCode();
386                    result += 37 * result + getAstronomicalCalculator().hashCode();
387                    return result;
388            }
389    
390            /**
391             * A method to get the offset in minutes before
392             * {@link AstronomicalCalendar#getSunset() sunset} that is used in
393             * calculating candle lighting time. The default time used is 18 minutes
394             * before sunset. Some calendars use 15 minutes, while the custom in
395             * Jerusalem is to use a 40 minute offset. Please check the local custom
396             * for candel lighting time.
397             * 
398             * @return Returns the candle lighting offset to set in minutes..
399             * @see #getCandelLighting()
400             */
401            public double getCandleLightingOffset() {
402                    return candleLightingOffset;
403            }
404    
405            /**
406             * A method to set the offset in minutes before
407             * {@link AstronomicalCalendar#getSunset() sunset} that is used in
408             * calculating candle lighting time. The default time used is 18 minutes
409             * before sunset. Some calendars use 15 minutes, while the custom in
410             * Jerusalem is to use a 40 minute offset.
411             * 
412             * @param candleLightingOffset
413             *            The candle lighting offset to set in minutes.
414             * @see #getCandelLighting()
415             */
416            public void setCandleLightingOffset(double candleLightingOffset) {
417                    this.candleLightingOffset = candleLightingOffset;
418            }
419    }