SatAgro / suntime

Simple sunset and sunrise time calculation python library.
GNU Lesser General Public License v3.0
108 stars 38 forks source link

Local Sunset time wrong when UTC sunset is in following day #12

Open jfbauer432 opened 4 years ago

jfbauer432 commented 4 years ago
$ pip3 show suntime | grep Version
Version: 1.2.5

$ python3
Python 3.7.5 (default, Apr 19 2020, 20:18:17) 
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> from suntime import Sun
>>> 
>>> tz = pytz.timezone('America/New_York')
>>> tz
<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
>>> 
>>> dt = datetime.datetime.now(tz=tz)
>>> dt
datetime.datetime(2020, 4, 29, 7, 35, 24, 335561, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

First, get the sunrise/set times for Washington D.C. These look correct. (www.timeanddate.com report 06:12 and 19:59 for sunrise/set today)

>>> sun = Sun(38.8895, -77.0353)
>>> sun.get_local_sunrise_time(dt)
datetime.datetime(2020, 4, 29, 6, 12, tzinfo=tzlocal())
>>> sun.get_local_sunset_time(dt)
datetime.datetime(2020, 4, 29, 19, 59, tzinfo=tzlocal())
>>> sun.get_sunrise_time(dt)
datetime.datetime(2020, 4, 29, 10, 12, tzinfo=tzutc())
>>> sun.get_sunset_time(dt)
datetime.datetime(2020, 4, 29, 23, 59, tzinfo=tzutc())

Now change the latitude 1 degree north. A small change is expected, but notice that the sunset time jumps back one day now that the sunset time goes beyond 20:00 local time (00:00 UTC)

>>> sun = Sun(39.8895, -77.0353)
>>> sun.get_local_sunrise_time(dt)
datetime.datetime(2020, 4, 29, 6, 10, tzinfo=tzlocal())
>>> sun.get_local_sunset_time(dt)
datetime.datetime(2020, 4, 28, 20, 1, tzinfo=tzlocal())   <=== Wrong, should be the 29th
>>> sun.get_sunrise_time(dt)
datetime.datetime(2020, 4, 29, 10, 10, tzinfo=tzutc())
>>> sun.get_sunset_time(dt)
datetime.datetime(2020, 4, 29, 0, 1, tzinfo=tzutc())   <==== Wrong, should be the 30th
jfbauer432 commented 4 years ago

This is the workaround I am using

def sunset(dt):
    sun = Sun(LAT, LON)
    ss = sun.get_local_sunset_time(dt)
    sr = sun.get_local_sunrise_time(dt)
    if ss < sr:
        ss = ss + datetime.timedelta(1)
    return ss
suuuehgi commented 4 years ago

Just noticed it too. It just smashed an hour of work. >.<

Even when the timezone is set in pandas (e.g. tz='America/New_York'), the resulting sunset date is back in utc.

You can force it via:

sun.get_local_sunset_time(dt).replace(tzinfo=pytz.utc).astimezone(pytz.timezone('America/New_York'))
SatAgro commented 4 years ago

I'll check it thanks for reporting!

jbeale1 commented 4 years ago

Just stumbled across this myself, thanks for the workarounds.

thinktwisted commented 4 years ago

I have a similar issue, but I don't think its related to timezone - when getting sunrise/sunset times 2020 in a single location (long = -83.09, lat = 40.18) the sunset time reverts to a day back on 4/3/2020. ...snip... Sunrise: 1585466400.0 - Sunset: 1585511640.0 - Daylight hr: 12.57 Sunrise: 1585552680.0 - Sunset: 1585598100.0 - Daylight hr: 12.62 Sunrise: 1585639020.0 - Sunset: 1585684560.0 - Daylight hr: 12.65 Sunrise: 1585725300.0 - Sunset: 1585771020.0 - Daylight hr: 12.7 Sunrise: 1585811640.0 - Sunset: 1585857480.0 - Daylight hr: 12.73 Sunrise: 1585897920.0 - Sunset: 1585943940.0 - Daylight hr: 12.78 Sunrise: 1585984200.0 - Sunset: 1585944000.0 - Daylight hr: -11.17 Sunrise: 1586070540.0 - Sunset: 1586030520.0 - Daylight hr: -11.12 Sunrise: 1586156820.0 - Sunset: 1586116980.0 - Daylight hr: -11.07 ...snip... @jfbauer432's solution worked for me.

dhowland commented 2 years ago

I just found this issue too. No fix two years later?

yasirroni commented 2 years ago

Solved in https://github.com/SatAgro/suntime/pull/19

tested using this:

import datetime
import pytz

sun = Sun(38.8895, -77.0353)
tz = pytz.timezone('America/New_York')
day = datetime.datetime(2020, 4, 29, 7, 35, 24, 335561)
day

print(sun.get_sunrise_time(day))
print(sun.get_sunset_time(day))
print("")
print(sun.get_sunrise_time(day, tz=tz))
print(sun.get_sunset_time(day, tz=tz))

sun = Sun(39.8895, -77.0353)
tz = pytz.timezone('America/New_York')
day = datetime.datetime(2020, 4, 29, 7, 35, 24, 335561)
day

print(sun.get_sunrise_time(day))
print(sun.get_sunset_time(day))
print("")
print(sun.get_sunrise_time(day, tz=tz))
print(sun.get_sunset_time(day, tz=tz))

But, it merely change the date. Can you help me confirm my solution @jfbauer432?

SylvainGa commented 2 years ago

Yeah, but the pull request hasn't been merged yet so still no fix. Testing if sunset is before sunrise is still the only valid solution, beside modifying the source on my end,