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

Different results for getTimes depending on time of date passed in #161

Open Jorundur opened 2 years ago

Jorundur commented 2 years ago

An example given in the docs is the following:

// get today's sunlight times for London
var times = SunCalc.getTimes(new Date(), 51.5, -0.1);

To me this suggests that it doesn't matter what time of day it is in the Date object passed in - i.e. passing in new Date('2020-01-01T00:00:00) or new Date('2020-01-01T23:59:59') should give me the same results: the sunlight phases for the date 2020-01-01.

I was doing some testing and I always got the same results return if I passed in any time from 00:00:00 to 22:45:12, but somehow if I passed in time at 22:45:13 or after for the same date I got different results. I assume that specific timestamp 22:45:12 depends on the lat/long I pass in so it's different for other coordinates.

To replicate:

import SunCalc from "suncalc";

const date = new Date("2020-01-01T22:45:12"); // and any time before with the same date

const reyLatitude = 64.9631;
const reyLongitude = 19.0208;
const times = SunCalc.getTimes(date, reyLatitude, reyLongitude);

console.log(times);

/*
Gives
{ solarNoon: Wed Jan 01 2020 10:48:17 GMT+0000 (Greenwich Mean Time),
  nadir: Tue Dec 31 2019 22:48:17 GMT+0000 (Greenwich Mean Time),
  sunrise: Wed Jan 01 2020 08:51:53 GMT+0000 (Greenwich Mean Time),
  sunset: Wed Jan 01 2020 12:44:42 GMT+0000 (Greenwich Mean Time),
  sunriseEnd: Wed Jan 01 2020 09:03:41 GMT+0000 (Greenwich Mean Time),
  sunsetStart: Wed Jan 01 2020 12:32:53 GMT+0000 (Greenwich Mean Time),
  dawn: Wed Jan 01 2020 07:28:15 GMT+0000 (Greenwich Mean Time),
  dusk: Wed Jan 01 2020 14:08:19 GMT+0000 (Greenwich Mean Time),
  nauticalDawn: Wed Jan 01 2020 06:16:55 GMT+0000 (Greenwich Mean Time),
  nauticalDusk: Wed Jan 01 2020 15:19:39 GMT+0000 (Greenwich Mean Time),
  nightEnd: Wed Jan 01 2020 05:15:17 GMT+0000 (Greenwich Mean Time),
  night: Wed Jan 01 2020 16:21:17 GMT+0000 (Greenwich Mean Time),
  goldenHourEnd: Invalid Date,
  goldenHour: Invalid Date }
*/

and

...
const date = new Date("2020-01-01T22:45:13"); // and any time after with the same date
...

/*
Gives
{ solarNoon: Thu Jan 02 2020 10:48:45 GMT+0000 (Greenwich Mean Time),
  nadir: Wed Jan 01 2020 22:48:45 GMT+0000 (Greenwich Mean Time),
  sunrise: Thu Jan 02 2020 08:50:40 GMT+0000 (Greenwich Mean Time),
  sunset: Thu Jan 02 2020 12:46:49 GMT+0000 (Greenwich Mean Time),
  sunriseEnd: Thu Jan 02 2020 09:02:18 GMT+0000 (Greenwich Mean Time),
  sunsetStart: Thu Jan 02 2020 12:35:11 GMT+0000 (Greenwich Mean Time),
  dawn: Thu Jan 02 2020 07:27:41 GMT+0000 (Greenwich Mean Time),
  dusk: Thu Jan 02 2020 14:09:48 GMT+0000 (Greenwich Mean Time),
  nauticalDawn: Thu Jan 02 2020 06:16:34 GMT+0000 (Greenwich Mean Time),
  nauticalDusk: Thu Jan 02 2020 15:20:55 GMT+0000 (Greenwich Mean Time),
  nightEnd: Thu Jan 02 2020 05:15:02 GMT+0000 (Greenwich Mean Time),
  night: Thu Jan 02 2020 16:22:28 GMT+0000 (Greenwich Mean Time),
  goldenHourEnd: Invalid Date,
  goldenHour: Invalid Date }
*/

The results in the latter example are all for 1 day later than the former example.

I'm in GMT +0 so I don't think timezones are affecting this.

Is this behaviour expected?

jumpjack commented 1 year ago

This issue is not just around 31/dec - 1/jan, look at these these results:

Feb 04:

For feb 05:

jmbldwn commented 5 months ago

I don't mind working around whatever causes this strange behavior, but I'd like to know what the expectation is for specifying the date at the target coordinates. I'm writing some silly code to hunt around that would be unnecessary if this was clear.

I would expect that specifying 00:00:00 for H:M:S (start of day) would give me the events for today, but I get yesterday instead. If I advance the request time to 02:00:00, I get today.

So would it be reliable to choose 12:00:00 (noon) as the request time? Will that work worldwide?

jumpjack commented 5 months ago

I swithced to meeusJs and added an easier interface: https://github.com/jumpjack/MeeusJsEasy

jmbldwn commented 5 months ago

Not sure that would make it easier in my case. The results from suncalc are pretty much exactly what I'm looking for; I just have to figure out what to expect.

My current workaround is to gather events from yesterday/today/tomorrow, sort them by time, and take the window I need out of that. It's more work than necessary but it doesn't need to get run very often so it's not really a performance issue.