Python:用Ephem/Astral/PvLib非迭代获取太阳特定仰角时刻
问题解答
一、各库直接获取特定太阳高度角时刻的方法
1. ephem库
ephem支持通过自定义观察者的horizon参数,直接计算太阳到达指定高度角的时刻,无需逐分钟迭代。只需将horizon设为目标高度角(负数表示地平线以下),再调用next_rising/next_setting即可得到对应时间。
2. astral库(推荐astral4版本)
astral专门处理太阳与暮光时间计算,可通过sun()方法的depression参数指定地平线以下的角度,直接获取对应时刻,无需手动迭代。
3. pvlib库
pvlib的sun_rise_set_transit_spa函数基于高精度SPA算法,支持自定义太阳高度角阈值,能快速返回目标时刻,效率远高于逐分钟计算。
二、替代库推荐
- astral4:API简洁直观,专注太阳与暮光时间计算,内置多种暮光类型,也支持自定义高度角。
- skyfield:高精度天文计算库,基于SPICE数据,可精准计算任意太阳高度角对应的时刻。
三、可运行示例
示例1:用ephem获取太阳-6°(航海暮光)的时刻
import ephem from datetime import datetime import zoneinfo # 配置墨尔本观测点 melbourne = ephem.Observer() melbourne.lat = "-37.8136" melbourne.lon = "144.9631" melbourne.elev = 0 # 设置目标太阳高度角(地平线以下6°) target_alt = -6 melbourne.horizon = str(target_alt) # 指定日期 target_date = datetime(2023, 1, 1) melbourne.date = ephem.Date(target_date) # 获取UTC时刻并转换为墨尔本本地时间 sun_rise_utc = melbourne.next_rising(ephem.Sun()) sun_set_utc = melbourne.next_setting(ephem.Sun()) tz_mel = zoneinfo.ZoneInfo("Australia/Melbourne") rise_local = ephem.localtime(sun_rise_utc).astimezone(tz_mel) set_local = ephem.localtime(sun_set_utc).astimezone(tz_mel) print(f"太阳高度{target_alt}°升起时刻(墨尔本时间):{rise_local.strftime('%Y-%m-%d %H:%M:%S')}") print(f"太阳高度{target_alt}°落下时刻(墨尔本时间):{set_local.strftime('%Y-%m-%d %H:%M:%S')}")
示例2:用astral4获取自定义高度角时刻
from astral import LocationInfo from astral.sun import sun from datetime import date import zoneinfo # 定义墨尔本位置 city = LocationInfo( name="Melbourne", region="Australia", timezone="Australia/Melbourne", latitude=-37.8136, longitude=144.9631 ) target_date = date(2023, 1, 1) tz_mel = zoneinfo.ZoneInfo(city.timezone) # 获取太阳-6°(航海暮光)的时刻 sun_data_nautical = sun(city.observer, date=target_date, depression=6) print(f"航海暮光开始:{sun_data_nautical['dawn'].astimezone(tz_mel)}") print(f"航海暮光结束:{sun_data_nautical['dusk'].astimezone(tz_mel)}") # 获取太阳-12°(天文暮光)的时刻 sun_data_astro = sun(city.observer, date=target_date, depression=12) print(f"天文暮光开始:{sun_data_astro['dawn'].astimezone(tz_mel)}") print(f"天文暮光结束:{sun_data_astro['dusk'].astimezone(tz_mel)}")
示例3:用pvlib获取自定义高度角时刻
import pvlib from datetime import date import zoneinfo # 墨尔本参数 lat, lon = -37.8136, 144.9631 tz = "Australia/Melbourne" target_date = date(2023, 1, 1) # 计算太阳高度角为-6°的时刻 sun_times = pvlib.solarposition.sun_rise_set_transit_spa( latitude=lat, longitude=lon, date=target_date, altitude=-6, # 负数表示地平线以下 tz=tz ) print(f"太阳-6°升起时刻:{sun_times['sun_rise']}") print(f"太阳-6°落下时刻:{sun_times['sun_set']}")
四、优化原始代码的思路
你的逐分钟迭代效率极低,可改为:
- 对每一天,用上述库直接获取所有关键高度角(-1°、-6°、-12°、-18°)对应的时刻
- 根据这些时刻计算对应时间段的Y轴像素范围(对应24小时的比例)
- 直接绘制对应颜色的线段/矩形,无需逐像素计算高度角
这样每天仅需几次计算,效率会大幅提升。
内容的提问来源于stack exchange,提问作者Mutley Eugenius
相关产品推荐
相关产品推荐

