001    /*
002     * Zmanim Java API
003     * Copyright (C) 2004-2011 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.Calendar;
020    import java.util.Date;
021    
022    import net.sourceforge.zmanim.util.AstronomicalCalculator;
023    import net.sourceforge.zmanim.util.GeoLocation;
024    
025    /**
026     * <p>
027     * Description: A Java library for calculating zmanim.
028     * </p>
029     * The zmanim library is an API is a specialized calendar that can calculate
030     * sunrise and sunset and Jewish <em>zmanim</em> (religious times) for prayers
031     * and other Jewish religious duties. For a much more extensive list of zmanim
032     * use the {@link ComplexZmanimCalendar} that extends this class. This class
033     * contains the main functionality of the Zmanim library. See documentation for
034     * the {@link ComplexZmanimCalendar} and {@link AstronomicalCalendar} for simple
035     * examples on using the API. <br/>
036     * <b>Note:</b> It is important to read the technical notes on top of the
037     * {@link AstronomicalCalculator} documentation. <h2>
038     * Disclaimer:</h2> While I did my best to get accurate results please do not
039     * rely on these zmanim for <em>halacha lemaaseh</em>.
040     * 
041     * @author &copy; Eliyahu Hershfeld 2004 - 2011
042     * @version 1.2.1
043     */
044    public class ZmanimCalendar extends AstronomicalCalendar {
045            private static final long serialVersionUID = 1;
046    
047            /**
048             * The zenith of 16.1&deg; below geometric zenith (90&deg;). This
049             * calculation is used for calculating <em>alos</em> (dawn) and
050             * <em>tzais</em> (nightfall) in some opinions. This calculation is based on
051             * the calculation that the time between dawn and sunrise (and sunset to
052             * nightfall) is the time that is takes to walk 4 <em>mil</em> at 18 minutes
053             * a mil (<em>Ramba"m</em> and others). The sun's position at 72 minutes
054             * before {@link #getSunrise sunrise} in Jerusalem on the equinox is
055             * 16.1&deg; below {@link #GEOMETRIC_ZENITH geometric zenith}.
056             * 
057             * @see #getAlosHashachar()
058             * @see ComplexZmanimCalendar#getAlos16Point1Degrees()
059             * @see ComplexZmanimCalendar#getTzais16Point1Degrees()
060             * @see ComplexZmanimCalendar#getSofZmanShmaMGA16Point1Degrees()
061             * @see ComplexZmanimCalendar#getSofZmanTfilaMGA16Point1Degrees()
062             * @see ComplexZmanimCalendar#getMinchaGedola16Point1Degrees()
063             * @see ComplexZmanimCalendar#getMinchaKetana16Point1Degrees()
064             * @see ComplexZmanimCalendar#getPlagHamincha16Point1Degrees()
065             * @see ComplexZmanimCalendar#getPlagAlos16Point1ToTzaisGeonim7Point083Degrees()
066             * @see ComplexZmanimCalendar#getSofZmanShmaAlos16Point1ToSunset()
067             */
068            protected static final double ZENITH_16_POINT_1 = GEOMETRIC_ZENITH + 16.1;
069    
070            /**
071             * The zenith of 8.5&deg; below geometric zenith (90&deg;). This calculation
072             * is used for calculating <em>alos</em> (dawn) and <em>tzais</em>
073             * (nightfall) in some opinions. This calculation is based on the position
074             * of the sun 36 minutes after {@link #getSunset sunset} in Jerusalem on
075             * March 16, about 4 days before the equinox, the day that a solar hour is
076             * one hour, which is 8.5&deg; below {@link #GEOMETRIC_ZENITH geometric
077             * zenith}. The Ohr Meir considers this the time that 3 small starts are
078             * visible, later than the required 3 medium stars.
079             * 
080             * @see #getTzais()
081             * @see ComplexZmanimCalendar#getTzaisGeonim8Point5Degrees()
082             */
083            protected static final double ZENITH_8_POINT_5 = GEOMETRIC_ZENITH + 8.5;
084    
085            /**
086             * The default Shabbos candle lighting offset is 18 minutes. This can be
087             * changed via the {@link #setCandleLightingOffset(double)} and retrieved by
088             * the {@link #getCandleLightingOffset()}.
089             */
090            private double candleLightingOffset = 18;
091    
092            /**
093             * Returns <em>tzais</em> (nightfall) when the sun is 8.5&deg; below the
094             * western geometric horizon (90&deg;) after {@link #getSunset sunset}. For
095             * information on the source of this calculation see
096             * {@link #ZENITH_8_POINT_5}.
097             * 
098             * @return The <code>Date</code> of nightfall. If the calculation can't be
099             *         computed such as northern and southern locations even south of
100             *         the Arctic Circle and north of the Antarctic Circle where the sun
101             *         may not reach low enough below the horizon for this calculation,
102             *         a null will be returned. See detailed explanation on top of the
103             *         {@link AstronomicalCalendar} documentation.
104             * @see #ZENITH_8_POINT_5
105             */
106            public Date getTzais() {
107                    return this.getSunsetOffsetByDegrees(ZENITH_8_POINT_5);
108            }
109    
110            /**
111             * Returns <em>alos</em> (dawn) based on the time when the sun is 16.1&deg;
112             * below the eastern {@link #GEOMETRIC_ZENITH geometric horizon} before
113             * {@link #getSunrise sunrise}. For more information the source of 16.1&deg;
114             * see {@link #ZENITH_16_POINT_1}.
115             * 
116             * @see net.sourceforge.zmanim.ZmanimCalendar#ZENITH_16_POINT_1
117             * @return The <code>Date</code> of dawn. If the calculation can't be
118             *         computed such as northern and southern locations even south of
119             *         the Arctic Circle and north of the Antarctic Circle where the sun
120             *         may not reach low enough below the horizon for this calculation,
121             *         a null will be returned. See detailed explanation on top of the
122             *         {@link AstronomicalCalendar} documentation.
123             */
124            public Date getAlosHashachar() {
125                    return getSunriseOffsetByDegrees(ZENITH_16_POINT_1);
126            }
127    
128            /**
129             * Method to return <em>alos</em> (dawn) calculated using 72 minutes before
130             * {@link #getSeaLevelSunrise() sea level sunrise} (no adjustment for
131             * elevation) based on the time to walk the distance of 4 <em>Mil</em> at 18
132             * minutes a <em>Mil</em>. This is based on the opinion of most
133             * <em>Rishonim</em> who stated that the time of the <em>Neshef</em> (time
134             * between dawn and sunrise) does not vary by the time of year or location
135             * but purely depends on the time it takes to walk the distance of 4
136             * <em>Mil</em>.
137             * 
138             * @return the <code>Date</code> representing the time. If the calculation
139             *         can't be computed such as in the Arctic Circle where there is at
140             *         least one day a year where the sun does not rise, and one where
141             *         it does not set, a null will be returned. See detailed
142             *         explanation on top of the {@link AstronomicalCalendar}
143             *         documentation.
144             */
145            public Date getAlos72() {
146                    return getTimeOffset(getSeaLevelSunrise(), -72 * MINUTE_MILLIS);
147            }
148    
149            /**
150             * This method returns <em>chatzos</em> (midday) following the opinion of
151             * the GRA that the day for Jewish halachic times start at
152             * {@link #getSunrise sunrise} and ends at {@link #getSunset sunset}. The
153             * returned value is identical to {@link #getSunTransit()}
154             * 
155             * @see AstronomicalCalendar#getSunTransit()
156             * @return the <code>Date</code> of chatzos. If the calculation can't be
157             *         computed such as in the Arctic Circle where there is at least one
158             *         day where the sun does not rise, and one where it does not set, a
159             *         null will be returned. See detailed explanation on top of the
160             *         {@link AstronomicalCalendar} documentation.
161             */
162            public Date getChatzos() {
163                    return getSunTransit();
164            }
165    
166            /**
167             * A method that returns "solar" midnight, or the time when the sun is at
168             * it's <a href="http://en.wikipedia.org/wiki/Nadir">nadir</a>. <br/>
169             * <br/>
170             * <b>Note:</b> this method is experimental and might be removed (or moved)
171             * 
172             * @return the <code>Date</code> of Solar Midnight (chatzos layla). If the
173             *         calculation can't be computed such as in the Arctic Circle where
174             *         there is at least one day a year where the sun does not rise, and
175             *         one where it does not set, a null will be returned. See detailed
176             *         explanation on top of the {@link AstronomicalCalendar}
177             *         documentation.
178             */
179            public Date getSolarMidnight() {
180                    ZmanimCalendar clonedCal = (ZmanimCalendar) clone();
181                    clonedCal.getCalendar().add(Calendar.DAY_OF_MONTH, 1);
182                    Date sunset = getSunset();
183                    Date sunrise = clonedCal.getSunrise();
184                    return getTimeOffset(sunset, getTemporalHour(sunset, sunrise) * 6);
185            }
186    
187            // public Date getChatzosLaylaRSZ() {
188            // ZmanimCalendar clonedCal = (ZmanimCalendar)clone();
189            // clonedCal.getCalendar().add(Calendar.DAY_OF_MONTH, 1);
190            // Date sunset = getSunset();
191            // Date sunrise = clonedCal.getAlosHashachar();
192            // return getTimeOffset(sunset, getTemporalHour(sunset, sunrise) * 6);
193            // }
194    
195            /**
196             * This method returns the latest <em>zman krias shema</em> (time to say
197             * Shema in the morning). This time is 3
198             * <em>{@link #getShaahZmanisGra() shaos zmaniyos}</em> (solar hours) after
199             * {@link #getSeaLevelSunrise() sea level sunrise} based on the opinion of
200             * the <em>GR"A</em> and the <em>Baal Hatanya</em> that the day is
201             * calculated from sunrise to sunset. This returns the time 3 *
202             * {@link #getShaahZmanisGra()} after {@link #getSeaLevelSunrise() sea level
203             * sunrise}.
204             * 
205             * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
206             * @return the <code>Date</code> of the latest zman shema. If the
207             *         calculation can't be computed such as in the Arctic Circle where
208             *         there is at least one day a year where the sun does not rise, and
209             *         one where it does not set, a null will be returned. See detailed
210             *         explanation on top of the {@link AstronomicalCalendar}
211             *         documentation.
212             */
213            public Date getSofZmanShmaGRA() {
214                    return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 3);
215            }
216    
217            /**
218             * This method returns the latest <em>zman krias shema</em> (time to say
219             * Shema in the morning) in the opinion of the <em>MG"A</em> based on
220             * <em>alos</em> being 72 minutes before {@link #getSunrise() sunrise}. This
221             * time is 3 <em> shaos zmaniyos</em> (solar hours) after dawn based on the
222             * opinion of the <em>MG"A</em> that the day is calculated from a dawn of 72
223             * minutes before sunrise to nightfall of 72 minutes after sunset. This
224             * returns the time of 3 * <em>shaos zmaniyos</em> after dawn.
225             * 
226             * @return the <code>Date</code> of the latest zman shema. If the
227             *         calculation can't be computed such as in the Arctic Circle where
228             *         there is at least one day a year where the sun does not rise, and
229             *         one where it does not set, a null will be returned. See detailed
230             *         explanation on top of the {@link AstronomicalCalendar}
231             *         documentation.
232             * @see ComplexZmanimCalendar#getShaahZmanis72Minutes()
233             * @see ComplexZmanimCalendar#getAlos72()
234             * @see ComplexZmanimCalendar#getSofZmanShmaMGA72Minutes()
235             */
236            public Date getSofZmanShmaMGA() {
237                    return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 3);
238            }
239    
240            /**
241             * This method returns the <em>tzais</em> (nightfall) based on the opinion
242             * of the <em>Ramba"m</em> and <em>Rabainu Tam</em> that <em>tzais</em> is
243             * calculated as the time it takes to walk 4 <em>Mil</em> at 18 minutes a
244             * <em>Mil</em> for a total of 72 minutes. Even for locations above sea
245             * level, this is calculated at sea level, since the darkness level is not
246             * affected by elevation.
247             * 
248             * @return the <code>Date</code> representing 72 minutes after sea level
249             *         sunset. 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
251             *         sun does not rise, and one where it does not set, a null will be
252             *         returned See detailed explanation on top of the
253             *         {@link AstronomicalCalendar} documentation.
254             */
255            public Date getTzais72() {
256                    return getTimeOffset(getSeaLevelSunset(), 72 * MINUTE_MILLIS);
257            }
258    
259            /**
260             * A method to return candle lighting time. This is calculated as
261             * {@link #getCandleLightingOffset()} minutes before sunset. This will
262             * return the time for any day of the week, since it can be used to
263             * calculate candle lighting time for <em>yom tov</em> (holidays) as well.
264             * 
265             * @return candle lighting time. If the calculation can't be computed such
266             *         as in the Arctic Circle where there is at least one day a year
267             *         where the sun does not rise, and one where it does not set, a
268             *         null will be returned. See detailed explanation on top of the
269             *         {@link AstronomicalCalendar} documentation.
270             * @see #getCandleLightingOffset()
271             * @see #setCandleLightingOffset(double)
272             */
273            public Date getCandelLighting() {
274                    return getTimeOffset(getSunset(), -getCandleLightingOffset()
275                                    * MINUTE_MILLIS);
276            }
277    
278            /**
279             * This method returns the latest
280             * <em>zman tefilah<em> (time to pray morning prayers). This time is 4
281             * hours into the day based on the opinion of the <em>GR"A</em> and the
282             * </em>Baal Hatanya</em> that the day is calculated from sunrise to sunset.
283             * This returns the time 4 * {@link #getShaahZmanisGra()} after
284             * {@link #getSeaLevelSunrise() sea level sunrise}.
285             * 
286             * @see net.sourceforge.zmanim.ZmanimCalendar#getShaahZmanisGra()
287             * @return the <code>Date</code> of the latest zman tefilah. If the
288             *         calculation can't be computed such as in the Arctic Circle where
289             *         there is at least one day a year where the sun does not rise, and
290             *         one where it does not set, a null will be returned. See detailed
291             *         explanation on top of the {@link AstronomicalCalendar}
292             *         documentation.
293             */
294            public Date getSofZmanTfilaGRA() {
295                    return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 4);
296            }
297    
298            /**
299             * This method returns the latest <em>zman tfila</em> (time to say the
300             * morning prayers) in the opinion of the <em>MG"A</em> based on
301             * <em>alos</em> being {@link #getAlos72() 72} minutes before
302             * {@link #getSunrise() sunrise}. This time is 4
303             * <em>{@link #getShaahZmanisMGA() shaos zmaniyos}</em> (temporal hours)
304             * after {@link #getAlos72() dawn} based on the opinion of the <em>MG"A</em>
305             * that the day is calculated from a {@link #getAlos72() dawn} of 72 minutes
306             * before sunrise to {@link #getTzais72() nightfall} of 72 minutes after
307             * sunset. This returns the time of 4 * {@link #getShaahZmanisMGA()} after
308             * {@link #getAlos72() dawn}.
309             * 
310             * @return the <code>Date</code> of the latest zman tfila. If the
311             *         calculation can't be computed such as in the Arctic Circle where
312             *         there is at least one day a year where the sun does not rise, and
313             *         one where it does not set), a null will be returned. See detailed
314             *         explanation on top of the {@link AstronomicalCalendar}
315             *         documentation.
316             * @see #getShaahZmanisMGA()
317             * @see #getAlos72()
318             */
319            public Date getSofZmanTfilaMGA() {
320                    return getTimeOffset(getAlos72(), getShaahZmanisMGA() * 4);
321            }
322    
323            /**
324             * This method returns the time of <em>mincha gedola</em>.
325             * <em>Mincha gedola</em> is the earliest time one can pray mincha. The
326             * Ramba"m is of the opinion that it is better to delay <em>mincha</em>
327             * until <em>{@link #getMinchaKetana() mincha ketana}</em> while the
328             * <em>Ra"sh,
329             * Tur, GR"A</em> and others are of the opinion that <em>mincha</em> can be
330             * prayed <em>lechatchila</em> starting at <em>mincha gedola</em>. This is
331             * calculated as 6.5 {@link #getShaahZmanisGra() sea level solar hours}
332             * after {@link #getSeaLevelSunrise() sea level sunrise}. This calculation
333             * is calculated based on the opinion of the <em>GR"A</em> and the
334             * <em>Baal Hatanya</em> that the day is calculated from sunrise to sunset.
335             * This returns the time 6.5 {@link #getShaahZmanisGra()} after
336             * {@link #getSeaLevelSunrise() sea level sunrise}.
337             * 
338             * @see #getShaahZmanisGra()
339             * @see #getMinchaKetana()
340             * @return the <code>Date</code> of the time of mincha gedola. If the
341             *         calculation can't be computed such as in the Arctic Circle where
342             *         there is at least one day a year where the sun does not rise, and
343             *         one where it does not set, a null will be returned. See detailed
344             *         explanation on top of the {@link AstronomicalCalendar}
345             *         documentation.
346             */
347            public Date getMinchaGedola() {
348                    return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 6.5);
349            }
350    
351            /**
352             * This method returns the time of <em>mincha ketana</em>. This is the
353             * perfered earliest time to pray <em>mincha</em> in the opinion of the
354             * Ramba"m and others. For more information on this see the documentation on
355             * <em>{@link #getMinchaGedola() mincha gedola}</em>. This is calculated as
356             * 9.5 {@link #getShaahZmanisGra() sea level solar hours} after
357             * {@link #getSeaLevelSunrise() sea level sunrise}. This calculation is
358             * calculated based on the opinion of the <em>GR"A</em> and the
359             * <em>Baal Hatanya</em> that the day is calculated from sunrise to sunset.
360             * This returns the time 9.5 * {@link #getShaahZmanisGra()} after
361             * {@link #getSeaLevelSunrise() sea level sunrise}.
362             * 
363             * @see #getShaahZmanisGra()
364             * @see #getMinchaGedola()
365             * @return the <code>Date</code> of the time of mincha gedola. If the
366             *         calculation can't be computed such as in the Arctic Circle where
367             *         there is at least one day a year where the sun does not rise, and
368             *         one where it does not set, a null will be returned. See detailed
369             *         explanation on top of the {@link AstronomicalCalendar}
370             *         documentation.
371             */
372            public Date getMinchaKetana() {
373                    return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 9.5);
374            }
375    
376            /**
377             * This method returns he time of <em>plag hamincha</em>. This is calculated
378             * as 10.75 hours after sunrise. This calculation is calculated based on the
379             * opinion of the <em>GR"A</em> and the <em>Baal Hatanya</em> that the day
380             * is calculated from sunrise to sunset. This returns the time 10.75 *
381             * {@link #getShaahZmanisGra()} after {@link #getSeaLevelSunrise() sea level
382             * sunrise}.
383             * 
384             * @return the <code>Date</code> of the time of <em>plag hamincha</em>. If
385             *         the calculation can't be computed such as in the Arctic Circle
386             *         where there is at least one day a year where the sun does not
387             *         rise, and one where it does not set, a null will be returned. See
388             *         detailed explanation on top of the {@link AstronomicalCalendar}
389             *         documentation.
390             */
391            public Date getPlagHamincha() {
392                    return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 10.75);
393            }
394    
395            /**
396             * Method to return a <em>shaah zmanis</em> (
397             * {@link #getTemporalHour(Date, Date) temporal hour}) according to the
398             * opinion of the <em>GR"A</em> and the <em>Baal Hatanya</em>. This
399             * calculation divides the day based on the opinion of the <em>GR"A</em> and
400             * the <em>Baal Hatanya</em> that the day runs from
401             * {@link #getSeaLevelSunrise() sunrise} to {@link #getSeaLevelSunrise
402             * sunset}. The calculations are based on a day from
403             * {@link #getSeaLevelSunrise() sea level sunrise} to
404             * {@link #getSeaLevelSunset() sea level sunset}. The day is split into 12
405             * equal parts each part with each one being a <em>shaah zmanis</em>. This
406             * method is similar to {@link #getTemporalHour}, but all calculations are
407             * based on a sealevel sunrise and sunset. For an explanation as to why
408             * elevation is not included in this calculation, see Zmanim Kehilchasam 2nd
409             * Edition by Rabbi Dovid Yehuda Burstein, Jerusalem, 2007. the explanation
410             * and detailed sources for not using elevation for anything besides sunrise
411             * and sunset can be found in <a
412             * href="http://www.worldcat.org/oclc/659793988">Zmanim Kehilchasam (second
413             * edition published in 2007)</a> by Rabbi Dovid Yehuda Bursztyn chapter 2
414             * (pages 186-187).
415             * 
416             * @return the <code>long</code> millisecond length of a
417             *         <em>shaah zmanis</em> calculated from
418             *         {@link #getSeaLevelSunrise() sea level sunrise} to
419             *         {@link #getSeaLevelSunset sea level sunset}. If the calculation
420             *         can't be computed such as in the Arctic Circle where there is at
421             *         least one day a year where the sun does not rise, and one where
422             *         it does not set, {@link Long#MIN_VALUE} will be returned. See
423             *         detailed explanation on top of the {@link AstronomicalCalendar}
424             *         documentation.
425             * @see #getTemporalHour(Date, Date)
426             * @see #getSeaLevelSunrise()
427             * @see #getSeaLevelSunset()
428             */
429            public long getShaahZmanisGra() {
430                    return getTemporalHour(getSeaLevelSunrise(), getSeaLevelSunset());
431            }
432    
433            /**
434             * Method to return a <em>shaah zmanis</em> (temporal hour) according to the
435             * opinion of the MGA. This calculation divides the day based on the opinion
436             * of the <em>MGA</em> that the day runs from dawn to dusk (for sof zman
437             * krias shema and tfila). Dawn for this calculation is 72 minutes before
438             * sunrise and dusk is 72 minutes after sunset. This day is split into 12
439             * equal parts with each part being a <em>shaah zmanis</em>. Alternate
440             * mothods of calculating a <em>shaah zmanis</em> are available in the
441             * subclass {@link ComplexZmanimCalendar}.
442             * 
443             * @return the <code>long</code> millisecond length of a
444             *         <em>shaah zmanis</em>. If the calculation can't be computed such
445             *         as in the Arctic Circle where there is at least one day a year
446             *         where the sun does not rise, and one where it does not set,
447             *         {@link Long#MIN_VALUE} will be returned. See detailed explanation
448             *         on top of the {@link AstronomicalCalendar} documentation.
449             */
450            public long getShaahZmanisMGA() {
451                    return getTemporalHour(getAlos72(), getTzais72());
452            }
453    
454            /**
455             * Default constructor will set a default {@link GeoLocation#GeoLocation()},
456             * a default {@link AstronomicalCalculator#getDefault()
457             * AstronomicalCalculator} and default the calendar to the current date.
458             * 
459             * @see AstronomicalCalendar#AstronomicalCalendar()
460             */
461            public ZmanimCalendar() {
462                    super();
463            }
464    
465            /**
466             * A constructor that takes a {@link GeoLocation} as a parameter.
467             * 
468             * @param location
469             *            the location
470             */
471            public ZmanimCalendar(GeoLocation location) {
472                    super(location);
473            }
474    
475            /**
476             * @see java.lang.Object#equals(Object)
477             */
478            public boolean equals(Object object) {
479                    if (this == object) {
480                            return true;
481                    }
482                    if (!(object instanceof ZmanimCalendar)) {
483                            return false;
484                    }
485                    ZmanimCalendar zCal = (ZmanimCalendar) object;
486                    // return getCalendar().getTime().equals(zCal.getCalendar().getTime())
487                    return getCalendar().equals(zCal.getCalendar())
488                                    && getGeoLocation().equals(zCal.getGeoLocation())
489                                    && getAstronomicalCalculator().equals(
490                                                    zCal.getAstronomicalCalculator());
491            }
492    
493            /**
494             * @see java.lang.Object#hashCode()
495             */
496            public int hashCode() {
497                    int result = 17;
498                    result = 37 * result + getClass().hashCode();// needed or this and
499                                                                                                                    // subclasses will
500                                                                                                                    // return identical hash
501                    result += 37 * result + getCalendar().hashCode();
502                    result += 37 * result + getGeoLocation().hashCode();
503                    result += 37 * result + getAstronomicalCalculator().hashCode();
504                    return result;
505            }
506    
507            /**
508             * A method to get the offset in minutes before
509             * {@link AstronomicalCalendar#getSunset() sunset} that is used in
510             * calculating candle lighting time. The default time used is 18 minutes
511             * before sunset. Some calendars use 15 minutes, while the custom in
512             * Jerusalem is to use a 40 minute offset. Please check the local custom for
513             * candel lighting time.
514             * 
515             * @return Returns the candle lighting offset to set in minutes..
516             * @see #getCandelLighting()
517             */
518            public double getCandleLightingOffset() {
519                    return this.candleLightingOffset;
520            }
521    
522            /**
523             * A method to set the offset in minutes before
524             * {@link AstronomicalCalendar#getSunset() sunset} that is used in
525             * calculating candle lighting time. The default time used is 18 minutes
526             * before sunset. Some calendars use 15 minutes, while the custom in
527             * Jerusalem is to use a 40 minute offset.
528             * 
529             * @param candleLightingOffset
530             *            The candle lighting offset to set in minutes.
531             * @see #getCandelLighting()
532             */
533            public void setCandleLightingOffset(double candleLightingOffset) {
534                    this.candleLightingOffset = candleLightingOffset;
535            }
536    }