mikereedell / sunrisesunsetlib-java

Library for computing the sunrise/sunset from GPS coordinates and a date, in Java.
http://mikereedell.github.com/sunrisesunsetlib-java/
Apache License 2.0
299 stars 69 forks source link

Invalid result for computeSunriseTime #6

Open Lagogal opened 10 years ago

Lagogal commented 10 years ago

I have problem calculation sunrise time for location N69.8888, E27.0000 for date 2014-01-16. For same date and location, sunset is calculated, but should the sunrise also be possible to calculate. 2014-01-15 sun is not either setting or rising (as expected) in that location.

Test case for testing this behaviour that I used is here:

public class SolarEventCalculatorInNorthTest extends BaseTestCase {
    private SolarEventCalculator calc;

    @Before
    public void setupCalculator() {
        super.setup(0,16, 2014, "69.8888", "27.0000", "Europe/Helsinki");
        calc = new SolarEventCalculator(location, "Europe/Helsinki");
    }

    @Test
    public void testComputeSunriseTime() {
        String localSunriseTime = "12:05";
        // should be something near 12:00, but not 99:99 because sun can't set if
        // it hasn't rised

        String actual = calc.computeSunriseTime(Zenith.OFFICIAL, eventDate);
        assertEquals(localSunriseTime, actual);
    }

    @Test
    public void testComputeSunsetTime() {
        String localSunriseTime = "12:35";
        String actual = calc.computeSunsetTime(Zenith.OFFICIAL, eventDate);
        assertEquals(localSunriseTime, actual);
    }
}
MenoData commented 6 years ago

I think this is due to a limitation of the algorithm used in this library, see also issue #12 . Originally the algorithm comes from Nautical Almanac and was popularized by Ed Williams and then overtaken here.

I have also implemented my own solution for sunrise/sunset in my library Time4J and realized four different algorithms. The following example code using two algorithms (one like the algorithm of Ed Williams and one from NOAA) shows the effect of choosing another algorithm:

SolarTime helsinkiWilliams16 = SolarTime.ofLocation(69.8888, 27.0, 0, StdSolarCalculator.SIMPLE);
System.out.println(
    PlainDate.of(2014, 1, 16).get(helsinkiWilliams16.sunshine(EUROPE.HELSINKI)));

=> Sunshine[utc=2014-01-15T22:00:00Z/2014-01-16T10:36:00Z,local=2014-01-16T00/2014-01-16T12:36,length=45360] (no sunrise, see the time T00, resulting in a length of sunshine = 45360secs which is far too much)

SolarTime helsinkiWilliams17 = SolarTime.ofLocation(69.8888, 27.0, 0, StdSolarCalculator.SIMPLE);
System.out.println(
    PlainDate.of(2014, 1, 17).get(helsinkiWilliams17.sunshine(EUROPE.HELSINKI)));

=> Sunshine[utc=2014-01-17T09:54:00Z/2014-01-17T10:59:00Z,local=2014-01-17T11:54/2014-01-17T12:59,length=3900] (imprecise sunrise on next day, should be about 11:46 instead of 11:54, this library even says: 11:55 => difference of 9 minutes)

SolarTime helsinkiNOAA16 = SolarTime.ofLocation(69.8888, 27.0, 0, StdSolarCalculator.NOAA);
System.out.println(
    PlainDate.of(2014, 1, 16).get(helsinkiNOAA16.sunshine(EUROPE.HELSINKI)));

=> Sunshine[utc=2014-01-16T10:07:09Z/2014-01-16T10:37:03Z,local=2014-01-16T12:07:09/2014-01-16T12:37:03,length=1794] (official NOAA says: no sunrise or sunset at all, difference to my NOAA-realization can be explained with small rounding differences in the algorithm and including correction for ephemeris time (delta-T), however, my result roughly matches YOUR expectations of 12:05 sunrise and 12:35 sunset, only 2 minutes difference)

SolarTime helsinkiNOAA17 = SolarTime.ofLocation(69.8888, 27.0, 0, StdSolarCalculator.NOAA);
System.out.println(
    PlainDate.of(2014, 1, 17).get(helsinkiNOAA17.sunshine(EUROPE.HELSINKI)));

=> Sunshine[utc=2014-01-17T09:45:53Z/2014-01-17T10:59:00Z,local=2014-01-17T11:45:53/2014-01-17T12:59,length=4387] (matches what the official NOAA-website says)

Conclusion:

I advise against using the algorithm of Ed Williams for circumpolar regions, however, it works quite well for "normal" latitudes.