Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Results appear to be inaccurate during summer in northern hemisphere #144

Open
jhsware opened this issue Jun 10, 2020 · 6 comments
Open

Comments

@jhsware
Copy link

jhsware commented Jun 10, 2020

The tests do not include any variation or edge cases which allows the library to fail silently.

@jhsware
Copy link
Author

jhsware commented Jun 10, 2020

Example of failing tests (the results aren't even close)

t.test('getTimes returns sun phases in summer in Stockholm', function (t) {
  const date = Date.UTC(2020, 6, 9);
  const sthlm = {lat: 59.33538407920466, lng: 18.03007918439074};
  // https://www.timeanddate.com/sun/sweden/stockholm?month=6&year=2020
  var times = SunCalc.getTimes(date, sthlm.lat, sthlm.lng);

  // Should be aprox GMT 01:34 / 20:00
  t.equal(new Date(times.sunrise).toUTCString().substr(0, 22), 'Thu, 09 Jul 2020 01:34');
  t.equal(new Date(times.sunset).toUTCString().substr(0, 22), 'Thu, 09 Jul 2020 20:00');
  t.end();
});

t.test('getTimes returns sun phases in summer in Kiruna (midnight sun)', function (t) {
  const date = Date.UTC(2020, 7, 1);
  const kiruna = {lat: 67.8537716, lng: 20.1163502};
  // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
  var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

  // Should be up all day
  t.equal(times.sunrise, undefined);
  t.equal(times.sunset, undefined);
  t.end();
});


t.test('getTimes returns sun phases in summer in Kiruna', function (t) {
  const date = Date.UTC(2020, 7, 17);
  const kiruna = {lat: 67.8537716, lng: 20.1163502};
  // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
  var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

  // Should be aprox GMT 23:37 (day before) / 21:45
  t.equal(new Date(times.sunrise).toUTCString().substr(0, 22), 'Mon, 16 Aug 2020 23:37');
  t.equal(new Date(times.sunset).toUTCString().substr(0, 22), 'Mon, 17 Aug 2020 21:45');
  t.end();
});

@foolip
Copy link

foolip commented Jun 22, 2020

@jhsware I'm also based in Stockholm and think I'm affected by this issue as well, or at least I'm not confident that SunCalc.getPosition() is accurate after seeing this issue. Did you end up digging in to see where things go wrong?

@foolip
Copy link

foolip commented Jun 22, 2020

To shed light on the actual behavior I tweaked the tests to pass against the current implementation:

t.test('getTimes returns sun phases in summer in Stockholm', function (t) {
    const date = Date.UTC(2020, 6, 9);
    const sthlm = {lat: 59.33538407920466, lng: 18.03007918439074};
    // https://www.timeanddate.com/sun/sweden/stockholm?month=6&year=2020
    var times = SunCalc.getTimes(date, sthlm.lat, sthlm.lng);

    // Should be approx GMT 01:34 / 20:00
    t.equal(times.sunrise.toUTCString(), 'Thu, 09 Jul 2020 01:48:59 GMT');
    t.equal(times.sunriseEnd.toUTCString(), 'Thu, 09 Jul 2020 01:55:26 GMT');
    t.equal(times.sunsetStart.toUTCString(), 'Thu, 09 Jul 2020 19:53:00 GMT');
    t.equal(times.sunset.toUTCString(), 'Thu, 09 Jul 2020 19:59:26 GMT');

    t.end();
  });

t.test('getTimes returns sun phases in summer in Kiruna (midnight sun)', function (t) {
    const date = Date.UTC(2020, 7, 1);
    const kiruna = {lat: 67.8537716, lng: 20.1163502};
    // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
    var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

    // Should be up all day
    t.equal(times.sunrise.toUTCString(), 'Sat, 01 Aug 2020 01:00:24 GMT');
    t.equal(times.sunriseEnd.toUTCString(), 'Sat, 01 Aug 2020 01:10:51 GMT');
    t.equal(times.sunsetStart.toUTCString(), 'Sat, 01 Aug 2020 20:23:17 GMT');
    t.equal(times.sunset.toUTCString(), 'Sat, 01 Aug 2020 20:33:45 GMT');

    t.end();
  });

t.test('getTimes returns sun phases in summer in Kiruna', function (t) {
    const date = Date.UTC(2020, 7, 17);
    const kiruna = {lat: 67.8537716, lng: 20.1163502};
    // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
    var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

    // Should be approx GMT 23:37 (day before) / 21:45
    t.equal(times.sunrise.toUTCString(), 'Mon, 17 Aug 2020 02:11:29 GMT');
    t.equal(times.sunriseEnd.toUTCString(), 'Mon, 17 Aug 2020 02:18:48 GMT');
    t.equal(times.sunsetStart.toUTCString(), 'Mon, 17 Aug 2020 19:11:12 GMT');
    t.equal(times.sunset.toUTCString(), 'Mon, 17 Aug 2020 19:18:31 GMT');

    t.end();
});

Looking at the actual results, it's clear that at least part of the problem is the dates. Date.UTC(2020, 7, 17) is Aug 17, because months are zero-based in that method.

@foolip
Copy link

foolip commented Jun 22, 2020

Fixing that problem, here's what I end up with:

t.test('getTimes returns sun phases in summer in Stockholm', function (t) {
    const date = new Date('2020-06-09UTC');
    const sthlm = {lat: 59.33538407920466, lng: 18.03007918439074};
    // https://www.timeanddate.com/sun/sweden/stockholm?month=6&year=2020
    var times = SunCalc.getTimes(date, sthlm.lat, sthlm.lng);

    // Should be approx GMT 01:34 / 20:00
    t.equal(times.sunrise.toUTCString(), 'Tue, 09 Jun 2020 01:35:47 GMT');
    t.equal(times.sunriseEnd.toUTCString(), 'Tue, 09 Jun 2020 01:42:29 GMT');
    t.equal(times.sunsetStart.toUTCString(), 'Tue, 09 Jun 2020 19:54:41 GMT');
    t.equal(times.sunset.toUTCString(), 'Tue, 09 Jun 2020 20:01:23 GMT');

    t.end();
  });

t.test('getTimes returns sun phases in summer in Kiruna (midnight sun)', function (t) {
    const date = new Date('2020-07-01UTC');
    const kiruna = {lat: 67.8537716, lng: 20.1163502};
    // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
    var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

    // Should be up all day
    t.ok(isNaN(times.sunrise.valueOf()));
    t.ok(isNaN(times.sunriseEnd.valueOf()));
    t.ok(isNaN(times.sunsetStart.valueOf()));
    t.ok(isNaN(times.sunset.valueOf()));

    t.end();
  });

t.test('getTimes returns sun phases in summer in Kiruna', function (t) {
    const date = new Date('2020-07-17UTC');
    const kiruna = {lat: 67.8537716, lng: 20.1163502};
    // https://www.timeanddate.com/sun/sweden/kiruna?month=7&year=2020
    var times = SunCalc.getTimes(date, kiruna.lat, kiruna.lng);

    // Should be approx GMT 23:37 (day before) / 21:45
    t.equal(times.sunrise.toUTCString(), 'Thu, 16 Jul 2020 23:17:03 GMT');
    t.equal(times.sunriseEnd.toUTCString(), 'Thu, 16 Jul 2020 23:47:45 GMT');
    t.equal(times.sunsetStart.toUTCString(), 'Fri, 17 Jul 2020 21:45:49 GMT');
    t.equal(times.sunset.toUTCString(), 'Fri, 17 Jul 2020 22:16:31 GMT');

    t.end();
});

The only bit that still doesn't match the expectation from the comments is the first 01:34. @jhsware do you think suncalc is wrong in this instance?

@jhsware
Copy link
Author

jhsware commented Jun 23, 2020

@foolip Nice catch about the dates! I am wondering if the fact that Kiruna is att 530m above sea level could account for the difference compared to timeanddate.com?

@jhsware jhsware changed the title WARNING! Results appear to be wildly inaccurate during summer in northern hemisphere Results appear to be wildly inaccurate during summer in northern hemisphere Jun 23, 2020
@jhsware jhsware changed the title Results appear to be wildly inaccurate during summer in northern hemisphere Results appear to be inaccurate during summer in northern hemisphere Jun 23, 2020
@Maximilian-Jodokus
Copy link

I tried following... in my opinion improved a lot for GMT+1

var now = new Date();
now.setHours( now.getHours() -1 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants