suncalc
suncalc copied to clipboard
It doesn't calculate correctly for other timezones relative to my own
If I live in GMT-7 (DST), and look up New York coordinates, the times are all messed up.
I made a date variable that is specific for New York (or the location given by user) but the suncalc still screws up the timing...is there any fix for this?
Thanks!
It seems like SunCalc will always calculate sun times in the local time zone. I managed to work around this issue with the following approach.
Where,
Given,
- Location A is where the user is located (in time zone A)
- Location B is where you want to calculate the sun times for in time zone B
const tzB = tzLookup(B.lat, b.lng)
const currentTimeAtB = DateTime.fromISO(new Date().toISOString(), { zone: tzB })
const suntimesAtB_in_tzA = SunCalc.getTimes(new Date(currentTimeAtB), B.lat, B.lng)
const sunriseAtB_in_tzB = DateTime.fromISO(suntimesAtB_in_tzA.sunrise.toISOString(), { zone: tzB })
thanks men is working 👌
Also would like a fix for this. AWS machines are always set to UTC.
@SrGrieves Does the workaround I posted work for you? I also blogged about it at https://tech.beyondtracks.com/posts/sun-times/
@andrewharvey I'm working on an embedded system. Adding two additional external libraries is something I'd like to avoid. I like that SunCalc is small and self-sufficient.
@andrewharvey I have tried your script and it seems to works but only if I edit "toJulian" function (with this ) isn't it?
@ottopic I didn't do that, though my times could be a day off without it. I haven't done that detailed testing. If that's the case, good catch.
It seems like SunCalc will always calculate sun times in the local time zone. I managed to work around this issue with the following approach.
Where,
Given,
- Location A is where the user is located (in time zone A)
- Location B is where you want to calculate the sun times for in time zone B
const tzB = tzLookup(B.lat, b.lng) const currentTimeAtB = DateTime.fromISO(new Date().toISOString(), { zone: tzB }) const suntimesAtB_in_tzA = SunCalc.getTimes(new Date(currentTimeAtB), B.lat, B.lng) const sunriseAtB_in_tzB = DateTime.fromISO(suntimesAtB_in_tzA.sunrise.toISOString(), { zone: tzB })
This saved me hours of figuring out how to do the transformation. Such a nice little library but in so many applications you have to operate with UTC times.
For a personal project I ended up creating an NPM package of a modified suncalc
to do this. It's called suncalc-tz, if anyone comes across this and is looking for something quick and dirty, might be worth a try. I wouldn't recommend it for production though, I haven't thoroughly tested it.
Similar to the code above, the package basically just pulls in a minified tzlookup to get the timezone and combines that with the Intl
standard library:
// Convert dates to the time at lat/lng
for (let time in result) {
const options = {timeZone: tz, year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'};
result[time] = new Date(Date.parse(new Intl.DateTimeFormat('default', options).format(result[time])));
}
For a personal project I ended up creating an NPM package of a modified
suncalc
to do this. It's called suncalc-tz, if anyone comes across this and is looking for something quick and dirty, might be worth a try. I wouldn't recommend it for production though, I haven't thoroughly tested it.Similar to the code above, the package basically just pulls in a minified tzlookup to get the timezone and combines that with the
Intl
standard library:// Convert dates to the time at lat/lng for (let time in result) { const options = {timeZone: tz, year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'}; result[time] = new Date(Date.parse(new Intl.DateTimeFormat('default', options).format(result[time]))); }
Found a minor issue - it crashes for high latitudes where some of the values are not available (for example, in summer there is no nautical dusk / dawn or night in Iceland). I think that the fix should be as easy as adding if ( !isNaN(result[time]) ) { ... }
around the conversion, so I didn't bother with a pull request.
This will probably not work for regions that implement day light saving?
const { sunrise } = getTimes(new Date(), lat, lon);
const tzOffset = sunrise.getTimezoneOffset();
console.log('Corrected time', new Date(sunrise.getTime() - tzOffset * 60000));
If you're only calling getPosition
, you can pass in a UTC epoch int in milliseconds for the time, rather than a Date
object, as the function only calls valueOf
on that parameter.