1
1
/*
2
2
* Zmanim Java API
3
- * Copyright (C) 2004-2018 Eliyahu Hershfeld
3
+ * Copyright (C) 2004-2023 Eliyahu Hershfeld
4
4
*
5
5
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
6
6
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
7
7
* any later version.
8
8
*
9
9
* 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
11
11
* details.
12
12
* 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
15
15
*/
16
16
package com .kosherjava .zmanim .util ;
17
17
18
18
import java .util .Calendar ;
19
19
20
20
/**
21
21
* 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
28
28
* 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.
30
30
*
31
- * @author © Eliyahu Hershfeld 2011 - 2020
31
+ * @author © Eliyahu Hershfeld 2011 - 2023
32
32
*/
33
33
public class NOAACalculator extends AstronomicalCalculator {
34
34
/**
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>.
36
37
*/
37
38
private static final double JULIAN_DAY_JAN_1_2000 = 2451545.0 ;
38
39
39
40
/**
40
- * Julian days per century
41
+ * Julian days per century.
41
42
*/
42
43
private static final double JULIAN_DAYS_PER_CENTURY = 36525.0 ;
43
44
@@ -91,7 +92,7 @@ public double getUTCSunset(Calendar calendar, GeoLocation geoLocation, double ze
91
92
}
92
93
93
94
/**
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
95
96
*
96
97
* @param calendar
97
98
* The Java Calendar
@@ -113,7 +114,8 @@ private static double getJulianDay(Calendar calendar) {
113
114
}
114
115
115
116
/**
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>.
117
119
*
118
120
* @param julianDay
119
121
* the Julian Day to convert
@@ -124,21 +126,24 @@ private static double getJulianCenturiesFromJulianDay(double julianDay) {
124
126
}
125
127
126
128
/**
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>.
128
131
*
129
132
* @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>.
131
135
* @return the Julian Day corresponding to the Julian centuries passed in
132
136
*/
133
137
private static double getJulianDayFromJulianCenturies (double julianCenturies ) {
134
138
return julianCenturies * JULIAN_DAYS_PER_CENTURY + JULIAN_DAY_JAN_1_2000 ;
135
139
}
136
140
137
141
/**
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.
139
143
*
140
144
* @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>.
142
147
* @return the Geometric Mean Longitude of the Sun in degrees
143
148
*/
144
149
private static double getSunGeometricMeanLongitude (double julianCenturies ) {
@@ -154,32 +159,35 @@ private static double getSunGeometricMeanLongitude(double julianCenturies) {
154
159
}
155
160
156
161
/**
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.
158
163
*
159
164
* @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>.
161
167
* @return the Geometric Mean Anomaly of the Sun in degrees
162
168
*/
163
169
private static double getSunGeometricMeanAnomaly (double julianCenturies ) {
164
170
return 357.52911 + julianCenturies * (35999.05029 - 0.0001537 * julianCenturies ); // in degrees
165
171
}
166
172
167
173
/**
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>.
169
175
*
170
176
* @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>.
172
179
* @return the unitless eccentricity
173
180
*/
174
181
private static double getEarthOrbitEccentricity (double julianCenturies ) {
175
182
return 0.016708634 - julianCenturies * (0.000042037 + 0.0000001267 * julianCenturies ); // unitless
176
183
}
177
184
178
185
/**
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.
180
187
*
181
188
* @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>.
183
191
* @return the equation of center for the sun in degrees
184
192
*/
185
193
private static double getSunEquationOfCenter (double julianCenturies ) {
@@ -195,10 +203,11 @@ private static double getSunEquationOfCenter(double julianCenturies) {
195
203
}
196
204
197
205
/**
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.
199
207
*
200
208
* @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>.
202
211
* @return the sun's true longitude in degrees
203
212
*/
204
213
private static double getSunTrueLongitude (double julianCenturies ) {
@@ -209,7 +218,7 @@ private static double getSunTrueLongitude(double julianCenturies) {
209
218
}
210
219
211
220
// /**
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.
213
222
// *
214
223
// * @param julianCenturies
215
224
// * the number of Julian centuries since J2000.0
@@ -223,10 +232,11 @@ private static double getSunTrueLongitude(double julianCenturies) {
223
232
// }
224
233
225
234
/**
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.
227
236
*
228
237
* @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>.
230
240
* @return sun's apparent longitude in degrees
231
241
*/
232
242
private static double getSunApparentLongitude (double julianCenturies ) {
@@ -238,10 +248,11 @@ private static double getSunApparentLongitude(double julianCenturies) {
238
248
}
239
249
240
250
/**
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).
242
252
*
243
253
* @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>.
245
256
* @return the mean obliquity in degrees
246
257
*/
247
258
private static double getMeanObliquityOfEcliptic (double julianCenturies ) {
@@ -251,11 +262,12 @@ private static double getMeanObliquityOfEcliptic(double julianCenturies) {
251
262
}
252
263
253
264
/**
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
255
266
* tilt).
256
267
*
257
268
* @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>.
259
271
* @return the corrected obliquity in degrees
260
272
*/
261
273
private static double getObliquityCorrection (double julianCenturies ) {
@@ -266,10 +278,11 @@ private static double getObliquityCorrection(double julianCenturies) {
266
278
}
267
279
268
280
/**
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.
270
282
*
271
283
* @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>.
273
286
* @return
274
287
* the sun's declination in degrees
275
288
*/
@@ -283,11 +296,12 @@ private static double getSunDeclination(double julianCenturies) {
283
296
}
284
297
285
298
/**
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
287
300
* true solar time and mean solar time
288
301
*
289
302
* @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>.
291
305
* @return equation of time in minutes of time
292
306
*/
293
307
private static double getEquationOfTime (double julianCenturies ) {
@@ -311,16 +325,16 @@ private static double getEquationOfTime(double julianCenturies) {
311
325
}
312
326
313
327
/**
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.
316
330
*
317
331
* @param lat
318
- * , the latitude of observer in degrees
332
+ * the latitude of observer in degrees
319
333
* @param solarDec
320
334
* the declination angle of sun in degrees
321
335
* @param zenith
322
336
* 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>
324
338
*/
325
339
private static double getSunHourAngleAtSunrise (double lat , double solarDec , double zenith ) {
326
340
double latRad = Math .toRadians (lat );
@@ -331,8 +345,9 @@ private static double getSunHourAngleAtSunrise(double lat, double solarDec, doub
331
345
}
332
346
333
347
/**
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
336
351
* duplication of code.
337
352
*
338
353
* @param lat
@@ -341,7 +356,7 @@ private static double getSunHourAngleAtSunrise(double lat, double solarDec, doub
341
356
* the declination angle of sun in degrees
342
357
* @param zenith
343
358
* 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>
345
360
*/
346
361
private static double getSunHourAngleAtSunset (double lat , double solarDec , double zenith ) {
347
362
double latRad = Math .toRadians (lat );
@@ -353,7 +368,7 @@ private static double getSunHourAngleAtSunset(double lat, double solarDec, doubl
353
368
}
354
369
355
370
/**
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
357
372
* horizontal coordinate system at the given location at the given time. Can be negative if the sun is below the
358
373
* horizon. Not corrected for altitude.
359
374
*
@@ -386,7 +401,7 @@ public static double getSolarElevation(Calendar cal, double lat, double lon) {
386
401
}
387
402
388
403
/**
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
390
405
* horizontal coordinate system at the given location at the given time. Not corrected for altitude. True south is 0
391
406
* degrees.
392
407
*
@@ -396,7 +411,7 @@ public static double getSolarElevation(Calendar cal, double lat, double lon) {
396
411
* latitude of location for calculation
397
412
* @param lon
398
413
* longitude of location for calculation
399
- * @return FIXME
414
+ * @return the solar azimuth
400
415
*/
401
416
402
417
public static double getSolarAzimuth (Calendar cal , double lat , double lon ) {
@@ -420,8 +435,8 @@ public static double getSolarAzimuth(Calendar cal, double lat, double lon) {
420
435
}
421
436
422
437
/**
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.
425
440
*
426
441
* @param julianDay
427
442
* the Julian day
@@ -464,20 +479,59 @@ private static double getSunriseUTC(double julianDay, double latitude, double lo
464
479
timeUTC = 720 + timeDiff - eqTime ; // in minutes
465
480
return timeUTC ;
466
481
}
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
+ }
467
516
468
517
/**
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
471
520
* on earth.
472
521
*
473
522
* @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>.
475
525
* @param longitude
476
526
* the longitude of observer in degrees
527
+ *
477
528
* @return the time in minutes from zero UTC
529
+ *
530
+ * @see com.kosherjava.zmanim.util.AstronomicalCalculator#getUTCNoon(Calendar, GeoLocation)
531
+ * @see #getUTCNoon(Calendar, GeoLocation)
478
532
*/
479
533
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
481
535
double tnoon = getJulianCenturiesFromJulianDay (getJulianDayFromJulianCenturies (julianCenturies ) + longitude
482
536
/ 360.0 );
483
537
double eqTime = getEquationOfTime (tnoon );
@@ -491,8 +545,8 @@ private static double getSolarNoonUTC(double julianCenturies, double longitude)
491
545
}
492
546
493
547
/**
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.
496
550
*
497
551
* @param julianDay
498
552
* the Julian day
0 commit comments