Python中的日出和日落时间



我目前正在做一个项目,当与光相关的某些活动被触发时通知用户。我已经完成了与光相关的部分。因此,我需要找到一种在python中检索日出和日落时间的有效方法,因为整个脚本都是用python编写的。我知道有一些其他语言的库,我想知道在python中最方便的方法是什么。

我想它看起来很像这样:

if(sunrise<T<sunset) and (light<threshold):
    notifyUser()

我很感激你的帮助,祝你愉快。

查看星光。下面是他们文档中稍微修改过的例子:

>>> from astral import Astral
>>> city_name = 'London'
>>> a = Astral()
>>> a.solar_depression = 'civil'
>>> city = a[city_name]
>>> sun = city.sun(date=datetime.date(2009, 4, 22), local=True)
>>> if (sun['sunrise'] < T < sun['sunset']) and (light < threshold):
>>>    notifyUser()

如果您使用类似本示例的内容,请记住将提供的city_name和日期更改为city.sun

您也可以尝试使用suntime。下面是他们文档中的一个例子:

import datetime
from suntime import Sun, SunTimeException
latitude = 51.21
longitude = 21.01
sun = Sun(latitude, longitude)
# Get today's sunrise and sunset in UTC
today_sr = sun.get_sunrise_time()
today_ss = sun.get_sunset_time()
print('Today at Warsaw the sun raised at {} and get down at {} UTC'.
      format(today_sr.strftime('%H:%M'), today_ss.strftime('%H:%M')))
# On a special date in your machine's local time zone
abd = datetime.date(2014, 10, 3)
abd_sr = sun.get_local_sunrise_time(abd)
abd_ss = sun.get_local_sunset_time(abd)
print('On {} the sun at Warsaw raised at {} and get down at {}.'.
      format(abd, abd_sr.strftime('%H:%M'), abd_ss.strftime('%H:%M')))

我比较了几个包(suntime, suntimes, sunriset, astral)和它们返回的日出时间和日落时间。它们都返回本地时间,但你也可以很容易地获得UTC时间。结果如下:

from datetime import date, datetime, timezone, timedelta
import pytz
import time
from suntime import Sun, SunTimeException
from suntimes import SunTimes
import sunriset
import astral, astral.sun
latitude = 52.0691667
longitude = 19.4805556
altitude = 0
tz_poland = pytz.timezone('Europe/Warsaw')
tz_name = 'Europe/Warsaw'
for_date = date(2021, 4, 6)
print('====== suntime ======')
abd = for_date
sun = Sun(latitude, longitude)
today_sr = sun.get_sunrise_time()
today_ss = sun.get_sunset_time()
print(today_sr.astimezone(tz_poland))
print(today_ss.astimezone(tz_poland))
print('====== suntimes ======')
sun2 = SunTimes(longitude=longitude, latitude=latitude, altitude=altitude)
day = datetime(for_date.year, for_date.month, for_date.day)
print(sun2.risewhere(day, tz_name))
print(sun2.setwhere(day, tz_name))
print('====== sunriset ======')
local = datetime.now()
utc = datetime.utcnow()
local_tz = float(((local - utc).days * 86400 + round((local - utc).seconds, -1))/3600)
number_of_years = 1
start_date = for_date
df = sunriset.to_pandas(start_date, latitude, longitude, 2, number_of_years)
for index, row in df.iterrows():
    print(row['Sunrise'])
    print(row['Sunset'])
    break
print('====== astral ======')
l = astral.LocationInfo('Custom Name', 'My Region', tz_name, latitude, longitude)
s = astral.sun.sun(l.observer, date=for_date)
print(s['sunrise'].astimezone(tz_poland))
print(s['sunset'].astimezone(tz_poland))

返回:

====== suntime ======
2021-04-06 06:05:00+02:00
2021-04-06 19:16:00+02:00
====== suntimes ======
2021-04-06 06:04:34.000553+02:00
2021-04-06 19:17:16.000613+02:00
====== sunriset ======
0 days 06:02:52.093465
0 days 19:16:49.892350
====== astral ======
2021-04-06 06:03:39.792229+02:00
2021-04-06 19:17:01.188463+02:00

请注意只有suntimes包支持海拔

上面的Astral包示例似乎过时了。

下面是加利福尼亚州圣何塞机场位置的Astral v2.2示例。

首先,设置观察者的位置:

from astral import LocationInfo
loc = LocationInfo(name='SJC', region='CA, USA', timezone='America/Los_Angeles',
                   latitude=37.3713439, longitude=-121.944675)
print(loc)
# LocationInfo(name='SJC', region='CA, USA', timezone='America/Los_Angeles',
#   latitude=37.3713439, longitude=-121.944675)
print(loc.observer)
# Observer(latitude=37.3713439, longitude=-121.944675, elevation=0.0)

注意:

  • 只有纬度、经度和时区重要
  • 名称和地区只是标签。

接下来,计算该观测者在期望日期(例如,下面的20121-01-15)的太阳信息:

import datetime
from astral.sun import sun
s = sun(loc.observer, date=datetime.date(2021, 1, 15), tzinfo=loc.timezone)
for key in ['dawn', 'dusk', 'noon', 'sunrise', 'sunset']:
    print(f'{key:10s}:', s[key])
输出:

dawn      : 2021-01-15 06:52:04.342105-08:00
dusk      : 2021-01-15 17:42:59.471441-08:00
noon      : 2021-01-15 12:17:05-08:00
sunrise   : 2021-01-15 07:21:04.877697-08:00
sunset    : 2021-01-15 17:13:58.467348-08:00

指出:

  • 如果没有指定时区,默认为UTC。
  • 正午是太阳正午——太阳在观测者所在位置穿过子午线的时间。
  • Astral是NOAA发布的Excel表格的实现。

进一步改进@Wojciech Jakubas的答案,这是基准测试(省略时区):

# boilerplate
from datetime import date, datetime, timezone, timedelta
import pytz
import time
from suntime import Sun, SunTimeException
from suntimes import SunTimes
import sunriset
import astral, astral.sun
latitude = 6.2088
longitude = 106.8456
altitude = 0
tz_name = 'Asia/Jakarta'
for_date = date(2021, 4, 6)
%%timeit
# print('====== suntime ======')
sun = Sun(latitude, longitude)
today_sr = sun.get_sunrise_time(for_date)
today_ss = sun.get_sunset_time(for_date)
# 20.3 µs ± 90.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
# print('====== suntimes ======')
sun2 = SunTimes(longitude=longitude, latitude=latitude, altitude=altitude)
today_sr = sun2.riseutc(for_date)
today_ss = sun2.setutc(for_date)
# 83 µs ± 261 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
# print('====== sunriset ======')
df = sunriset.to_pandas(for_date, latitude, longitude, 0, 1)
for index, row in df.iterrows():
    today_sr = row['Sunrise']
    today_ss = row['Sunset']
    break
# 28.7 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
# print('====== astral ======')
l = astral.LocationInfo('Custom Name', 'My Region', tz_name, latitude, longitude)
today_sr = astral.sun.sunrise(l.observer, date=for_date)
today_ss = astral.sun.sunset(l.observer, date=for_date)
# 64.3 µs ± 292 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

转换为本地time zone (UTC+X),使用:

# with known region name
tz_name = 'Asia/Jakarta'
tz = pytz.timezone(tz_name)
today_sr.astimezone(tz)
# with known time different
time_different = 7
tz = datetime.timezone(datetime.timedelta(hours=time_different))
today_sr.astimezone(tz)

结论:

  1. 使用suntime(注意它使用LGPL许可证)。
  2. 如果你真的需要一年的数据,不关心速度,试试sunriset,因为它喷出一年的周期。
  3. sunriset需要从源代码手动编辑,以解决只有一次
  4. sunriset输出在timedelta中,因此不能直接使用.astimezone转换。

这也可以使用skyfield库完成。下面是一个使用当前版本(1.39)的简短示例,改编自文档:

from skyfield import almanac, api
ts = api.load.timescale()
eph = api.load('de421.bsp')
# Location
bluffton = api.wgs84.latlon(+40.8939, -83.8917)
# Times between which to look for sunrises and sunsets
t0 = ts.utc(2018, 9, 12, 4)
t1 = ts.utc(2018, 9, 13, 4)
times, is_sunrise = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, bluffton))

time将包含t0t1之间日出/日落的次数,如果是日出,is_sunrise中的对应值为1,如果是日落,则为0。

相关内容

  • 没有找到相关文章

最新更新