Skip to content

Commit f2157e4

Browse files
authored
Support astronomical noon in NOAACalculator
as opposed to calculating it as halfway between sunrise and sunset. This is the first part of support for #138 . Also update old links (mostly http to https).
1 parent 2c11ca9 commit f2157e4

File tree

1 file changed

+111
-57
lines changed

1 file changed

+111
-57
lines changed

src/main/java/com/kosherjava/zmanim/util/NOAACalculator.java

Lines changed: 111 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
11
/*
22
* Zmanim Java API
3-
* Copyright (C) 2004-2018 Eliyahu Hershfeld
3+
* Copyright (C) 2004-2023 Eliyahu Hershfeld
44
*
55
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
66
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
77
* any later version.
88
*
99
* This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
10-
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1111
* details.
1212
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
13-
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA,
14-
* or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
13+
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA,
14+
* or connect to: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
1515
*/
1616
package com.kosherjava.zmanim.util;
1717

1818
import java.util.Calendar;
1919

2020
/**
2121
* Implementation of sunrise and sunset methods to calculate astronomical times based on the <a
22-
* href="http://noaa.gov">NOAA</a> algorithm. This calculator uses the Java algorithm based on the implementation by <a
23-
* href="http://noaa.gov">NOAA - National Oceanic and Atmospheric Administration</a>'s <a href =
24-
* "http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html">Surface Radiation Research Branch</a>. NOAA's <a
25-
* href="http://www.srrb.noaa.gov/highlights/sunrise/solareqns.PDF">implementation</a> is based on equations from <a
26-
* href="http://www.willbell.com/math/mc1.htm">Astronomical Algorithms</a> by <a
27-
* href="http://en.wikipedia.org/wiki/Jean_Meeus">Jean Meeus</a>. Added to the algorithm is an adjustment of the zenith
22+
* href="https://noaa.gov">NOAA</a> algorithm. This calculator uses the Java algorithm based on the implementation by <a
23+
* href="https://noaa.gov">NOAA - National Oceanic and Atmospheric Administration</a>'s <a href =
24+
* "https://www.srrb.noaa.gov/highlights/sunrise/sunrise.html">Surface Radiation Research Branch</a>. NOAA's <a
25+
* href="https://www.srrb.noaa.gov/highlights/sunrise/solareqns.PDF">implementation</a> is based on equations from <a
26+
* href="https://www.amazon.com/Astronomical-Table-Sun-Moon-Planets/dp/1942675038/">Astronomical Algorithms</a> by <a
27+
* href="https://en.wikipedia.org/wiki/Jean_Meeus">Jean Meeus</a>. Added to the algorithm is an adjustment of the zenith
2828
* to account for elevation. The algorithm can be found in the <a
29-
* href="http://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation</a> article.
29+
* href="https://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation</a> article.
3030
*
31-
* @author &copy; Eliyahu Hershfeld 2011 - 2020
31+
* @author &copy; Eliyahu Hershfeld 2011 - 2023
3232
*/
3333
public class NOAACalculator extends AstronomicalCalculator {
3434
/**
35-
* The <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> of January 1, 2000
35+
* The <a href="https://en.wikipedia.org/wiki/Julian_day">Julian day</a> of January 1, 2000, known as
36+
* <a href="https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
3637
*/
3738
private static final double JULIAN_DAY_JAN_1_2000 = 2451545.0;
3839

3940
/**
40-
* Julian days per century
41+
* Julian days per century.
4142
*/
4243
private static final double JULIAN_DAYS_PER_CENTURY = 36525.0;
4344

@@ -91,7 +92,7 @@ public double getUTCSunset(Calendar calendar, GeoLocation geoLocation, double ze
9192
}
9293

9394
/**
94-
* Return the <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> from a Java Calendar
95+
* Return the <a href="https://en.wikipedia.org/wiki/Julian_day">Julian day</a> from a Java Calendar
9596
*
9697
* @param calendar
9798
* The Java Calendar
@@ -113,7 +114,8 @@ private static double getJulianDay(Calendar calendar) {
113114
}
114115

115116
/**
116-
* Convert <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a> to centuries since J2000.0.
117+
* Convert <a href="https://en.wikipedia.org/wiki/Julian_day">Julian day</a> to centuries since <a href=
118+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
117119
*
118120
* @param julianDay
119121
* the Julian Day to convert
@@ -124,21 +126,24 @@ private static double getJulianCenturiesFromJulianDay(double julianDay) {
124126
}
125127

126128
/**
127-
* Convert centuries since J2000.0 to <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a>.
129+
* Convert centuries since <a href="https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a> to
130+
* <a href="https://en.wikipedia.org/wiki/Julian_day">Julian day</a>.
128131
*
129132
* @param julianCenturies
130-
* the number of Julian centuries since J2000.0
133+
* the number of Julian centuries since <a href=
134+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
131135
* @return the Julian Day corresponding to the Julian centuries passed in
132136
*/
133137
private static double getJulianDayFromJulianCenturies(double julianCenturies) {
134138
return julianCenturies * JULIAN_DAYS_PER_CENTURY + JULIAN_DAY_JAN_1_2000;
135139
}
136140

137141
/**
138-
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_longitude">Mean Longitude</a> of the Sun.
142+
* Returns the Geometric <a href="https://en.wikipedia.org/wiki/Mean_longitude">Mean Longitude</a> of the Sun.
139143
*
140144
* @param julianCenturies
141-
* the number of Julian centuries since J2000.0
145+
* the number of Julian centuries since <a href=
146+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
142147
* @return the Geometric Mean Longitude of the Sun in degrees
143148
*/
144149
private static double getSunGeometricMeanLongitude(double julianCenturies) {
@@ -154,32 +159,35 @@ private static double getSunGeometricMeanLongitude(double julianCenturies) {
154159
}
155160

156161
/**
157-
* Returns the Geometric <a href="http://en.wikipedia.org/wiki/Mean_anomaly">Mean Anomaly</a> of the Sun.
162+
* Returns the Geometric <a href="https://en.wikipedia.org/wiki/Mean_anomaly">Mean Anomaly</a> of the Sun.
158163
*
159164
* @param julianCenturies
160-
* the number of Julian centuries since J2000.0
165+
* the number of Julian centuries since <a href=
166+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
161167
* @return the Geometric Mean Anomaly of the Sun in degrees
162168
*/
163169
private static double getSunGeometricMeanAnomaly(double julianCenturies) {
164170
return 357.52911 + julianCenturies * (35999.05029 - 0.0001537 * julianCenturies); // in degrees
165171
}
166172

167173
/**
168-
* Return the <a href="http://en.wikipedia.org/wiki/Eccentricity_%28orbit%29">eccentricity of earth's orbit</a>.
174+
* Return the <a href="https://en.wikipedia.org/wiki/Eccentricity_%28orbit%29">eccentricity of earth's orbit</a>.
169175
*
170176
* @param julianCenturies
171-
* the number of Julian centuries since J2000.0
177+
* the number of Julian centuries since <a href=
178+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
172179
* @return the unitless eccentricity
173180
*/
174181
private static double getEarthOrbitEccentricity(double julianCenturies) {
175182
return 0.016708634 - julianCenturies * (0.000042037 + 0.0000001267 * julianCenturies); // unitless
176183
}
177184

178185
/**
179-
* Returns the <a href="http://en.wikipedia.org/wiki/Equation_of_the_center">equation of center</a> for the sun.
186+
* Returns the <a href="https://en.wikipedia.org/wiki/Equation_of_the_center">equation of center</a> for the sun.
180187
*
181188
* @param julianCenturies
182-
* the number of Julian centuries since J2000.0
189+
* the number of Julian centuries since <a href=
190+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
183191
* @return the equation of center for the sun in degrees
184192
*/
185193
private static double getSunEquationOfCenter(double julianCenturies) {
@@ -195,10 +203,11 @@ private static double getSunEquationOfCenter(double julianCenturies) {
195203
}
196204

197205
/**
198-
* Return the true longitude of the sun
206+
* Return the <a href="https://en.wikipedia.org/wiki/True_longitude">true longitude</a> of the sun.
199207
*
200208
* @param julianCenturies
201-
* the number of Julian centuries since J2000.0
209+
* the number of Julian centuries since <a href=
210+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
202211
* @return the sun's true longitude in degrees
203212
*/
204213
private static double getSunTrueLongitude(double julianCenturies) {
@@ -209,7 +218,7 @@ private static double getSunTrueLongitude(double julianCenturies) {
209218
}
210219

211220
// /**
212-
// * Returns the <a href="http://en.wikipedia.org/wiki/True_anomaly">true anamoly</a> of the sun.
221+
// * Returns the <a href="https://en.wikipedia.org/wiki/True_anomaly">true anamoly</a> of the sun.
213222
// *
214223
// * @param julianCenturies
215224
// * the number of Julian centuries since J2000.0
@@ -223,10 +232,11 @@ private static double getSunTrueLongitude(double julianCenturies) {
223232
// }
224233

225234
/**
226-
* Return the apparent longitude of the sun
235+
* Return the <a href="https://en.wikipedia.org/wiki/Apparent_longitude">apparent longitude</a> of the sun.
227236
*
228237
* @param julianCenturies
229-
* the number of Julian centuries since J2000.0
238+
* the number of Julian centuries since <a href=
239+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
230240
* @return sun's apparent longitude in degrees
231241
*/
232242
private static double getSunApparentLongitude(double julianCenturies) {
@@ -238,10 +248,11 @@ private static double getSunApparentLongitude(double julianCenturies) {
238248
}
239249

240250
/**
241-
* Returns the mean <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial tilt).
251+
* Returns the mean <a href="https://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial tilt).
242252
*
243253
* @param julianCenturies
244-
* the number of Julian centuries since J2000.0
254+
* the number of Julian centuries since <a href=
255+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
245256
* @return the mean obliquity in degrees
246257
*/
247258
private static double getMeanObliquityOfEcliptic(double julianCenturies) {
@@ -251,11 +262,12 @@ private static double getMeanObliquityOfEcliptic(double julianCenturies) {
251262
}
252263

253264
/**
254-
* Returns the corrected <a href="http://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial
265+
* Returns the corrected <a href="https://en.wikipedia.org/wiki/Axial_tilt">obliquity of the ecliptic</a> (Axial
255266
* tilt).
256267
*
257268
* @param julianCenturies
258-
* the number of Julian centuries since J2000.0
269+
* the number of Julian centuries since <a href=
270+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
259271
* @return the corrected obliquity in degrees
260272
*/
261273
private static double getObliquityCorrection(double julianCenturies) {
@@ -266,10 +278,11 @@ private static double getObliquityCorrection(double julianCenturies) {
266278
}
267279

268280
/**
269-
* Return the <a href="http://en.wikipedia.org/wiki/Declination">declination</a> of the sun.
281+
* Return the <a href="https://en.wikipedia.org/wiki/Declination">declination</a> of the sun.
270282
*
271283
* @param julianCenturies
272-
* the number of Julian centuries since J2000.0
284+
* the number of Julian centuries since <a href=
285+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
273286
* @return
274287
* the sun's declination in degrees
275288
*/
@@ -283,11 +296,12 @@ private static double getSunDeclination(double julianCenturies) {
283296
}
284297

285298
/**
286-
* Return the <a href="http://en.wikipedia.org/wiki/Equation_of_time">Equation of Time</a> - the difference between
299+
* Return the <a href="https://en.wikipedia.org/wiki/Equation_of_time">Equation of Time</a> - the difference between
287300
* true solar time and mean solar time
288301
*
289302
* @param julianCenturies
290-
* the number of Julian centuries since J2000.0
303+
* the number of Julian centuries since <a href=
304+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
291305
* @return equation of time in minutes of time
292306
*/
293307
private static double getEquationOfTime(double julianCenturies) {
@@ -311,16 +325,16 @@ private static double getEquationOfTime(double julianCenturies) {
311325
}
312326

313327
/**
314-
* Return the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunrise for the
315-
* latitude.
328+
* Return the <a href="https://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun in
329+
* <a href="https://en.wikipedia.org/wiki/Radian">radians</a> at sunrise for the latitude.
316330
*
317331
* @param lat
318-
* , the latitude of observer in degrees
332+
* the latitude of observer in degrees
319333
* @param solarDec
320334
* the declination angle of sun in degrees
321335
* @param zenith
322336
* the zenith
323-
* @return hour angle of sunrise in radians
337+
* @return hour angle of sunrise in <a href="https://en.wikipedia.org/wiki/Radian">radians</a>
324338
*/
325339
private static double getSunHourAngleAtSunrise(double lat, double solarDec, double zenith) {
326340
double latRad = Math.toRadians(lat);
@@ -331,8 +345,9 @@ private static double getSunHourAngleAtSunrise(double lat, double solarDec, doub
331345
}
332346

333347
/**
334-
* Returns the <a href="http://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun at sunset for the
335-
* latitude. TODO: use - {@link #getSunHourAngleAtSunrise(double, double, double)} implementation to avoid
348+
* Returns the <a href="https://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun in <a href=
349+
* "https://en.wikipedia.org/wiki/Radian">radians</a>at sunset for the latitude.
350+
* @todo use - {@link #getSunHourAngleAtSunrise(double, double, double)} implementation to avoid
336351
* duplication of code.
337352
*
338353
* @param lat
@@ -341,7 +356,7 @@ private static double getSunHourAngleAtSunrise(double lat, double solarDec, doub
341356
* the declination angle of sun in degrees
342357
* @param zenith
343358
* the zenith
344-
* @return the hour angle of sunset in radians
359+
* @return the hour angle of sunset in <a href="https://en.wikipedia.org/wiki/Radian">radians</a>
345360
*/
346361
private static double getSunHourAngleAtSunset(double lat, double solarDec, double zenith) {
347362
double latRad = Math.toRadians(lat);
@@ -353,7 +368,7 @@ private static double getSunHourAngleAtSunset(double lat, double solarDec, doubl
353368
}
354369

355370
/**
356-
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Elevation</a> for the
371+
* Return the <a href="https://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Elevation</a> for the
357372
* horizontal coordinate system at the given location at the given time. Can be negative if the sun is below the
358373
* horizon. Not corrected for altitude.
359374
*
@@ -386,7 +401,7 @@ public static double getSolarElevation(Calendar cal, double lat, double lon) {
386401
}
387402

388403
/**
389-
* Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Azimuth</a> for the
404+
* Return the <a href="https://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Azimuth</a> for the
390405
* horizontal coordinate system at the given location at the given time. Not corrected for altitude. True south is 0
391406
* degrees.
392407
*
@@ -396,7 +411,7 @@ public static double getSolarElevation(Calendar cal, double lat, double lon) {
396411
* latitude of location for calculation
397412
* @param lon
398413
* longitude of location for calculation
399-
* @return FIXME
414+
* @return the solar azimuth
400415
*/
401416

402417
public static double getSolarAzimuth(Calendar cal, double lat, double lon) {
@@ -420,8 +435,8 @@ public static double getSolarAzimuth(Calendar cal, double lat, double lon) {
420435
}
421436

422437
/**
423-
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
424-
* of sunrise for the given day at the given location on earth
438+
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
439+
* of sunrise for the given day at the given location on earth.
425440
*
426441
* @param julianDay
427442
* the Julian day
@@ -464,20 +479,59 @@ private static double getSunriseUTC(double julianDay, double latitude, double lo
464479
timeUTC = 720 + timeDiff - eqTime; // in minutes
465480
return timeUTC;
466481
}
482+
483+
/**
484+
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
485+
* of <a href="https://en.wikipedia.org/wiki/Noon#Solar_noon">solar noon</a> for the given day at the given location
486+
* on earth. This implementation returns true solar noon as opposed to the time halfway between sunrise and sunset.
487+
* Other calculators may return a more simplified calculation of halfway between sunrise and sunset. See <a href=
488+
* "https://kosherjava.com/2020/07/02/definition-of-chatzos/">The Definition of <em>Chatzos</em></a> for details on
489+
* solar noon calculations.
490+
* @see com.kosherjava.zmanim.util.AstronomicalCalculator#getUTCNoon(Calendar, GeoLocation)
491+
* @see #getSolarNoonUTC(double, double)
492+
*
493+
* @param calendar
494+
* The Calendar representing the date to calculate solar noon for
495+
* @param geoLocation
496+
* The location information used for astronomical calculating sun times. This class uses only requires
497+
* the longitude for calculating noon since it is the same time anywhere along the longitude line.
498+
* @return the time in minutes from zero UTC
499+
*/
500+
public double getUTCNoon(Calendar calendar, GeoLocation geoLocation) {
501+
double julianDay = getJulianDay(calendar);
502+
double julianCenturies = getJulianCenturiesFromJulianDay(julianDay);
503+
504+
double noon = getSolarNoonUTC(julianCenturies, -geoLocation.getLongitude());
505+
noon = noon / 60;
506+
507+
// ensure that the time is >= 0 and < 24
508+
while (noon < 0.0) {
509+
noon += 24.0;
510+
}
511+
while (noon >= 24.0) {
512+
noon -= 24.0;
513+
}
514+
return noon;
515+
}
467516

468517
/**
469-
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
470-
* of <a href="http://en.wikipedia.org/wiki/Noon#Solar_noon">solar noon</a> for the given day at the given location
518+
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
519+
* of of <a href="http://en.wikipedia.org/wiki/Noon#Solar_noon">solar noon</a> for the given day at the given location
471520
* on earth.
472521
*
473522
* @param julianCenturies
474-
* the number of Julian centuries since J2000.0
523+
* the number of Julian centuries since <a href=
524+
* "https://en.wikipedia.org/wiki/Epoch_(astronomy)#J2000">J2000.0</a>.
475525
* @param longitude
476526
* the longitude of observer in degrees
527+
*
477528
* @return the time in minutes from zero UTC
529+
*
530+
* @see com.kosherjava.zmanim.util.AstronomicalCalculator#getUTCNoon(Calendar, GeoLocation)
531+
* @see #getUTCNoon(Calendar, GeoLocation)
478532
*/
479533
private static double getSolarNoonUTC(double julianCenturies, double longitude) {
480-
// First pass uses approximate solar noon to calculate eqtime
534+
// First pass uses approximate solar noon to calculate equation of time
481535
double tnoon = getJulianCenturiesFromJulianDay(getJulianDayFromJulianCenturies(julianCenturies) + longitude
482536
/ 360.0);
483537
double eqTime = getEquationOfTime(tnoon);
@@ -491,8 +545,8 @@ private static double getSolarNoonUTC(double julianCenturies, double longitude)
491545
}
492546

493547
/**
494-
* Return the <a href="http://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
495-
* of sunset for the given day at the given location on earth
548+
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
549+
* of sunset for the given day at the given location on earth.
496550
*
497551
* @param julianDay
498552
* the Julian day

0 commit comments

Comments
 (0)