SatAgro / suntime

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

Inconsistent sunrise times between neighbouring zones #17

Closed pierresegonne closed 7 months ago

pierresegonne commented 3 years ago

Hi,

The following snippet reveals an inconsistent behaviour regarding the sunrise time returned. For two points close by (Lucknow and Agra both in the same state of Uttar Pradesh in India), the sunrise time returned is completely different


import arrow
from suntime import Sun
import pytz

time = arrow.get("2020-04-30 01:00:00+05:30")
tz = pytz.timezone("Asia/Kolkata")

# Luckdown
lat = 26.848623
long = 80.8024271
sun_lockdown = Sun(lat, long)

# Agra
lat =  27.1761571
long = 77.9099726
sun_agra = Sun(lat, long)

print("Lucknow", sun_lockdown.get_sunrise_time(time).astimezone(tz)) # ==> Lucknow 2020-05-01 05:29:00+05:30
print("Agra", sun_agra.get_sunrise_time(time).astimezone(tz)) # ==> Agra 2020-04-30 05:40:00+05:30
jfbauer432 commented 3 years ago

Try the workaround I posted in issue #16

pierresegonne commented 3 years ago

Thanks for the fast answer,

Indeed

import arrow
import datetime
from suntime import Sun
import pytz

time = arrow.get("2020-04-30 01:00:00+05:30")
tz = pytz.timezone("Asia/Kolkata")

# Lucknow
lat_lucknow = 26.848623
long_lucknow = 80.8024271
sun_luckdown = Sun(lat_lucknow, long_lucknow)

# Agra
lat_agra =  27.1761571
long_agra = 77.9099726
sun_agra = Sun(lat_agra, long_agra)

print("Lucknow", sun_luckdown.get_sunrise_time(time).astimezone(tz)) # ==> Lucknow 2020-05-01 05:29:00+05:30
print("Agra", sun_agra.get_sunrise_time(time).astimezone(tz)) # ==> Agra 2020-04-30 05:40:00+05:30

def sunset(lat, lon, dt=None, tz=None):
    if dt is None:
        dt = datetime.datetime.now()

    sun = Sun(lat, lon)
    ss = sun.get_local_sunset_time(dt, local_time_zone=tz)
    sr = sun.get_local_sunrise_time(dt, local_time_zone=tz)
    if ss.utcoffset() < datetime.timedelta(0):
        if ss < sr:
            ss = ss + datetime.timedelta(1)
            print('workaround: added 1 day to sunset time')
    return ss

def sunrise(lat, lon, dt=None, tz=None):
    if dt is None:
        dt = datetime.datetime.now()

    sun = Sun(lat, lon)
    ss = sun.get_local_sunset_time(dt, local_time_zone=tz)
    sr = sun.get_local_sunrise_time(dt, local_time_zone=tz)
    if sr.utcoffset() > datetime.timedelta(0):
        if ss < sr:
            sr = sr - datetime.timedelta(1)
            print('workaround: subtracted 1 day from sunrise time')

    return sr

print("Lucknow", sunrise(lat_lucknow, long_lucknow, time, tz)) # ==> workaround: subtracted 1 day from sunrise time Lucknow 2020-04-30 05:29:00+05:30
print("Agra", sunrise(lat_agra, long_agra, time, tz)) # ==> Agra 2020-04-30 05:40:00+05:30

returns matching sunrise times, but this issue questions the consistance of the get_sunrise_time function from the package. If your workaround works well across the line, shouldn't we add it to the implementation ? I can help with writing the PR :)

jfbauer432 commented 3 years ago

Yes, it would be nice if some sort of fix would be incorporated into get_sunrise_time and get_sunset_time. My workaround, would probably need some tweaks to handle some edge cases like locations above the arctic circle. I am also not convinced it might be off a minute or so as well.

yasirroni commented 2 years ago

I also got this problem, but the workaround make us compute both sr and ss. The problem only occur on .astimezone(tz) though. I think get_local_sunrise_time should not only use .astimezone(tz) but different _calc_sun_time.

yasirroni commented 2 years ago

Solved in https://github.com/SatAgro/suntime/pull/19, just add tz as input and done.

Usage:

import datetime
import pytz
from suntime import Sun, SunTimeException

latitude = 7.7956
longitude = 110.3695
tz = pytz.timezone("Asia/Jakarta")

day = datetime.datetime(2022, 4, 24)
print(tz.utcoffset(day))

sun = Sun(latitude, longitude)
try:
    print("")
    print(datetime.datetime.now())
    print()
    print(sun.get_sunrise_time())
    print(sun.get_sunset_time())
    print("")
    print(sun.get_sunrise_time(tz=tz))
    print(sun.get_sunset_time(tz=tz))