admin管理员组

文章数量:1122832

I have the following function that for a provided date and a pair of lat/long variables is supposed to return the the list of 3 timestamps in UTC

  • one in the afternoon on that day
  • one in the late evening on that day
  • and next one shortly before sunrise next day.

Unfortunately, likely because the calculations jump from one day to another, the results are totally off. Where I got this wrong? Is there a better approach to this?

import datetime as dt
from suntime import Sun

def key_timestamps(date, latitude, longitude):  
    date = dt.datetime.strptime(date, "%Y-%m-%d")
    
    sun = Sun(latitude, longitude)
    
    sunrise = sun.get_sunrise_time(date)
    sunset = sun.get_sunset_time(date)
    
    next_day = date + dt.timedelta(days=1)
    sunrise_next_day = sun.get_sunrise_time(next_day)
    
    solar_noon = sunrise + (sunset - sunrise) / 2
    peak_heating = solar_noon + dt.timedelta(hours=2, minutes=30)
    evening_release = sunset + dt.timedelta(hours=3)
    morning_minimum = sunrise_next_day - dt.timedelta(hours=1)
    
    return [
          int(peak_heating.timestamp()), 
          int(evening_release.timestamp()),
          int(morning_minimum.timestamp())
          ] 

singapore_results = key_timestamps("2022-05-29", 1.3521, 103.8198)
print(singapore_results)

Output is [1653809526, 1653746868, 1653947784] which translates to:

  • Sunday, May 29, 2022 7:32:06 AM - probably correct
  • Saturday, May 28, 2022 2:07:48 PM - should be a few hours later than #1 so totally wrong
  • Monday, May 30, 2022 9:56:24 PM - also wrong

Another example:

la_results = key_timestamps("2022-05-29", 34.0549, 118.2426)

Output:

[1653806070, 1653747048, 1653940656] which translates to:

  • Sunday, May 29, 2022 6:34:30 AM - wrong
  • Saturday, May 28, 2022 2:10:48 PM - wrong
  • Monday, May 30, 2022 7:57:36 PM - wrong

I have the following function that for a provided date and a pair of lat/long variables is supposed to return the the list of 3 timestamps in UTC

  • one in the afternoon on that day
  • one in the late evening on that day
  • and next one shortly before sunrise next day.

Unfortunately, likely because the calculations jump from one day to another, the results are totally off. Where I got this wrong? Is there a better approach to this?

import datetime as dt
from suntime import Sun

def key_timestamps(date, latitude, longitude):  
    date = dt.datetime.strptime(date, "%Y-%m-%d")
    
    sun = Sun(latitude, longitude)
    
    sunrise = sun.get_sunrise_time(date)
    sunset = sun.get_sunset_time(date)
    
    next_day = date + dt.timedelta(days=1)
    sunrise_next_day = sun.get_sunrise_time(next_day)
    
    solar_noon = sunrise + (sunset - sunrise) / 2
    peak_heating = solar_noon + dt.timedelta(hours=2, minutes=30)
    evening_release = sunset + dt.timedelta(hours=3)
    morning_minimum = sunrise_next_day - dt.timedelta(hours=1)
    
    return [
          int(peak_heating.timestamp()), 
          int(evening_release.timestamp()),
          int(morning_minimum.timestamp())
          ] 

singapore_results = key_timestamps("2022-05-29", 1.3521, 103.8198)
print(singapore_results)

Output is [1653809526, 1653746868, 1653947784] which translates to:

  • Sunday, May 29, 2022 7:32:06 AM - probably correct
  • Saturday, May 28, 2022 2:07:48 PM - should be a few hours later than #1 so totally wrong
  • Monday, May 30, 2022 9:56:24 PM - also wrong

Another example:

la_results = key_timestamps("2022-05-29", 34.0549, 118.2426)

Output:

[1653806070, 1653747048, 1653940656] which translates to:

  • Sunday, May 29, 2022 6:34:30 AM - wrong
  • Saturday, May 28, 2022 2:10:48 PM - wrong
  • Monday, May 30, 2022 7:57:36 PM - wrong
Share Improve this question edited Nov 21, 2024 at 9:41 jonrsharpe 122k30 gold badges263 silver badges470 bronze badges asked Nov 21, 2024 at 9:30 ppp147ppp147 756 bronze badges 1
  • 2 If you print sunrise and sunset for the Singapore example, you get: sunrise = datetime.datetime(2022, 5, 29, 22, 56, 24, tzinfo=datetime.timezone.utc) sunset = datetime.datetime(2022, 5, 28, 11, 7, 48, tzinfo=datetime.timezone.utc); it's probably a tz problem; you want to convert these utcs datetimes to local ones; perhaps have a look at rhodesmill.org/pyephem/toc.html – Swifty Commented Nov 21, 2024 at 10:31
Add a comment  | 

2 Answers 2

Reset to default 1
  • Sun.get_sunset_time() appears to return the sunset time from the previous day (even if you set the time component to 23:59:59) so to get today's sunset time you need to add 1 day.
  • You also may need to pass in a time-zone aware datetime and then use Sun.get_sunrise_time(date, tzinfo) (and for sunset) to ensure that the output has the correct time zone.
from datetime import datetime, time, timedelta
from zoneinfo import ZoneInfo
from suntime import Sun

def key_timestamps(date, latitude, longitude):  
    sun = Sun(latitude, longitude)
    
    sunrise = sun.get_sunrise_time(date, date.tzinfo)
    sunset = sun.get_sunset_time(date + timedelta(days=1), date.tzinfo)
    sunrise_next_day = sun.get_sunrise_time(date + timedelta(days=1), date.tzinfo)
    
    peak_heating = sunrise + (sunset - sunrise)/2 + timedelta(hours=2, minutes=30)
    evening_release = sunset + timedelta(hours=3)
    morning_minimum = sunrise_next_day - timedelta(hours=1)
    
    return [peak_heating, evening_release, morning_minimum] 

singapore_results = key_timestamps(
    datetime(2022, 5, 29, 0, 0, 0, tzinfo=ZoneInfo("Asia/Singapore")),
    1.3521,
    103.8198,
)
print(singapore_results)
print([int(t.timestamp()) for t in singapore_results])

Outputs:

[ datetime.datetime(2022, 5, 29, 15, 32, 6, tzinfo=zoneinfo.ZoneInfo(key='Asia/Singapore')),
  datetime.datetime(2022, 5, 29, 22, 7, 48, tzinfo=zoneinfo.ZoneInfo(key='Asia/Singapore')),
  datetime.datetime(2022, 5, 30, 5, 56, 24, tzinfo=zoneinfo.ZoneInfo(key='Asia/Singapore'))]
[1653809526, 1653833268, 1653861384]
import datetime as dt
from suntime import Sun
import pytz

def key_timestamps(date, latitude, longitude):
    # Parse the date and assume it's in local time
    date = dt.datetime.strptime(date, "%Y-%m-%d")
    
    # Sun calculation object
    sun = Sun(latitude, longitude)
    
    # Get sunrise and sunset in UTC
    sunrise_utc = sun.get_sunrise_time(date)
    sunset_utc = sun.get_sunset_time(date)
    
    # Convert date to the next day for the next sunrise
    next_day = date + dt.timedelta(days=1)
    sunrise_next_day_utc = sun.get_sunrise_time(next_day)
    
    # Calculate solar noon
    solar_noon = sunrise_utc + (sunset_utc - sunrise_utc) / 2
    
    # Calculate timestamps in UTC
    peak_heating_utc = solar_noon + dt.timedelta(hours=2, minutes=30)
    evening_release_utc = sunset_utc + dt.timedelta(hours=3)
    morning_minimum_utc = sunrise_next_day_utc - dt.timedelta(hours=1)
    
    # Return timestamps in UTC
    return [
        int(peak_heating_utc.timestamp()),
        int(evening_release_utc.timestamp()),
        int(morning_minimum_utc.timestamp())
    ]

本文标签: pythonMisaligned dates for crossday calculationsStack Overflow