mourner / suncalc

A tiny JavaScript library for calculating sun/moon positions and phases.
BSD 2-Clause "Simplified" License
3.07k stars 412 forks source link

Inconsistent behavior when hour is missing #109

Open sebagr opened 6 years ago

sebagr commented 6 years ago

I think I've found a bug, but it may well be that I'm using the library incorrectly.

I'm trying to display the Moon rise/set for an entire month and I found some days were not showing the moon rise, and 14-15 days later the moon set is missing.

Note these three calls, all for the same day, but switching the datetime string:

console.log(SunCalc.getMoonTimes("2017-11-08", -34.778, -58.382));
{rise: Tue Nov 07 2017 23:10:53 GMT-0300 (-03), set: Tue Nov 07 2017 08:44:45 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes("2017-11-08 00:00:00", -34.778, -58.382));
{set: Wed Nov 08 2017 09:44:13 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes("2017-11-08 12:00:00", -34.778, -58.382));
{set: Wed Nov 08 2017 09:44:13 GMT-0300 (-03)}

For some reason I don't get the rise time in the 2nd and 3rd examples. So I figured I had to use just the date part of the datetime, but then this happens for the following day:

console.log(SunCalc.getMoonTimes("2017-11-09", -34.778, -58.382));
{set: Wed Nov 08 2017 09:44:13 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes("2017-11-09 00:00:00", -34.778, -58.382));
{rise: Thu Nov 09 2017 00:09:13 GMT-0300 (-03), set: Thu Nov 09 2017 10:48:25 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes("2017-11-09 12:00:00", -34.778, -58.382));
{rise: Thu Nov 09 2017 00:09:13 GMT-0300 (-03), set: Thu Nov 09 2017 10:48:25 GMT-0300 (-03)}

The exact opposite situation: the 2nd and 3rd options show the rise time but not the first one.

Am I doing something wrong, or did I find a bug?

services4smb commented 6 years ago

I have seen something similar, where either moon rise or moon set returns undefined in the console.

Moontime set will will fail on this:

MoonTimes date: Mon Oct 30 2017 12:00:00 GMT+0100, lat: 56.26392, lng: 9.50178500000004

Moontime rise will fail on this:

MoonTimes date: Sun Nov 12 2017 12:00:00 GMT+0100, lat: 56.26392, lng: 9.50178500000004

A solution to the above errors will be greatly appreciated.

wuqi commented 6 years ago

Maybe the moon rise and set not in the same day,so you can't get the right result.

This is the code I use in my project,maybe can help you:

    var moonTimes = SunCalc.getMoonTimes(cacldate, lat , lng);
    var moonPos = SunCalc.getMoonPosition(cacldate,lat,lng);
    var moonIllumination =SunCalc.getMoonIllumination(cacldate);
    //moon time
    if(!moonTimes.rise){
      var prevday = new Date(cacldate.getTime() - 24*60*60*1000);
      var prevmoonTimes = SunCalc.getMoonTimes(prevday, lat , lng);
      $('#moonrise').html(prevmoonTimes.rise.format("yyyy/MM/dd hh:mm"));
    }else{
      $('#moonrise').html(moonTimes.rise.format("yyyy/MM/dd hh:mm"));
    }
    if(!moonTimes.set || ((moonTimes.rise) && (moonTimes.set.getTime() < moonTimes.rise.getTime()))){
      var nextday = new Date(cacldate.getTime() + 24*60*60*1000);
      var nextmoonTimes = SunCalc.getMoonTimes(nextday, lat , lng);
      $('#moonset').html(nextmoonTimes.set.format("yyyy/MM/dd hh:mm"));
    }else{
      $('#moonset').html(moonTimes.set.format("yyyy/MM/dd hh:mm"));
    }
    //moon ill
    $('#light').html(moonIllumination.fraction.toPrecision(6));
MenoData commented 6 years ago

Please see the USNO-data for the location and date specified by you (UTC-offset = -03:00):

http://aa.usno.navy.mil/cgi-bin/aa_rstablew.pl?ID=AA&year=2017&task=1&place=&lon_sign=-1&lon_deg=58&lon_min=23&lat_sign=-1&lat_deg=34&lat_min=47&tz=3&tz_sign=-1

It clearly shows that not every calendar date has both moonrise and moonset. This is understandable because the moon shifts its rising and setting time every day by roughly 50 minutes so sometimes the event is postponed to next day. This is an effect of the fact that - while the earth is rotating along its own axis - the moon is also rotating (around the earth) so the observer on the earth needs extra time to see the moon again next day.

Another topic is the accuracy of the times for moonrise/set. USNO says for 2017-11-07: 23:23 while this library says 23:10:53 It is obvious here that the underlying algorithms used in suncalc-library are overly simple hence constraining the accurary to about 5 minutes (here even about 12 minutes difference). I have also written an implementation (Time4J in Java not JavaScript) which does much more computation efforts and therefore matches USNO-data well which is known to yield more or less accurate results.

sebagr commented 6 years ago

@MenoData that's not in question here. The problem is that the behavior is different when passing these different strings as the date argument:

console.log(SunCalc.getMoonTimes(**"2017-11-08"**, -34.778, -58.382));
{rise: Tue Nov 07 2017 23:10:53 GMT-0300 (-03), set: Tue Nov 07 2017 08:44:45 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes(**"2017-11-08 00:00:00"**, -34.778, -58.382));
{set: Wed Nov 08 2017 09:44:13 GMT-0300 (-03)}

console.log(SunCalc.getMoonTimes(**"2017-11-08 12:00:00"**, -34.778, -58.382));
{set: Wed Nov 08 2017 09:44:13 GMT-0300 (-03)}

I'm suspecting that when we don't pass the hour, SunCalc is assuming one, some kind of hour shift happens and the resulting day is one day before or after the one we pass.

It's confusing that not passing an hour returns the rise time, but passing 00:00:00 or 12:00:00 as hours it doesn't return the rise time. This is the inconsistency I'm talking about.

MenoData commented 6 years ago

Well, I see now in your published output that the suncalc-library seems to produce moon times for the previous day if the hour information is left out (equal if set to 00:00:00 or to 12:00:00). In short:

input "2017-11-08" => moontimes for "2017-11-07" input "2017-11-08 00:00:00" => moontimes for "2017-11-08"

This indeed indicates a serious bug.


But else:

There is no moonrise on 2017-11-08 (see USNO-data and the link given above). So suncalc-lib is correct here (although really imprecise but that is another topic).

And about the day before (2017-11-07): It has first moonset and then moonrise. After the day when there is only one event (moonset), namely on 2017-11-09, we observe (and suncalc also shows that) the right order of events again, that is first moonrise and then moonset.

So we still have the proper order of settings and risings for consecutive days.

sebagr commented 6 years ago

Thanks for clarifying that, MenoData. I've updated the issue title to reflect the problem properly - it's no longer about moonrise missing but inconsistent behavior when the time is missing.