Search code examples
pythonpyephem

Why is the sunrise and sunset time returned by pyephem incorrect for a given location?


I am using the ephem module in Python to calculate the next sunrise and sunset time for a given location (Boston). However, the results returned by the next_rising and next_setting methods are incorrect.

Here is the code I am using:

import ephem
import datetime

Boston=ephem.Observer()
Boston.lat='42.3462'
Boston.lon='-71.0978'
Boston.date = datetime.datetime.now()
Boston.elevation = 3 # meters
Boston.pressure = 1010 # millibar
Boston.temp = 25 # deg. Celcius
Boston.horizon = 0

sun = ephem.Sun()

print("Next sunrise in Boston will be: ",ephem.localtime(Boston.next_rising(sun)))
print("Next sunset in Boston will be: ",ephem.localtime(Boston.next_setting(sun)))

The output I get is:

Next sunrise in Boston will be:  2023-04-27 10:45:21.307728
Next sunset in Boston will be:  2023-04-27 00:38:21.498500

However, these times are not correct!

Is there an error in my code, or is there something else I need to consider when using the ephem module to calculate sunrise and sunset times for a given location?


Solution

  • The above code gets the sunrise/sunset times in the local time. To get these in the observer's timezone, we can use a library like timezonefinder.

    import ephem
    import datetime
    import pytz
    from timezonefinder import TimezoneFinder
    
    # set observer coordinates
    lat = '42.3462'
    lon = '-71.0978'
    
    # create observer
    observer = ephem.Observer()
    observer.lat = lat
    observer.lon = lon
    observer.date = datetime.datetime.utcnow()
    
    # define observer parameters
    observer.elevation = 3  # meters
    observer.pressure = 1010  # millibar
    observer.temp = 25  # deg. Celcius
    observer.horizon = 0
    
    # define sun
    sun = ephem.Sun()
    
    # get sunrise and sunset times in UTC
    next_rising = observer.next_rising(sun)
    next_setting = observer.next_setting(sun)
    
    # get observer timezone
    tf = TimezoneFinder()
    timezone_str = tf.timezone_at(lat=float(lat), lng=float(lon))
    tz = pytz.timezone(timezone_str)
    
    # convert UTC times to local time
    next_rising_local = pytz.utc.localize(next_rising.datetime()).astimezone(tz)
    next_setting_local = pytz.utc.localize(next_setting.datetime()).astimezone(tz)
    
    # print results
    print("Next sunrise will be at: ", next_rising_local)
    print("Next sunset will be at: ", next_setting_local)