日出/设定计算
我正在尝试根据下面提供的链接使用 python 计算日落/上升时间。
我通过excel和python得到的结果与实际值不符。关于我可能做错了什么有什么想法吗?
我的 Excel 工作表可以在 .. http://transpotools.com/sun_time.xls 下找到
# Created on 2010-03-28
# @author: dassouki
# @source: [http://williams.best.vwh.net/sunrise_sunset_algorithm.htm][2]
# @summary: this is based on the Nautical Almanac Office, United States Naval
# Observatory.
import math, sys
class TimeOfDay(object):
def calculate_time(self, in_day, in_month, in_year,
lat, long, is_rise, utc_time_zone):
# is_rise is a bool when it's true it indicates rise,
# and if it's false it indicates setting time
#set Zenith
zenith = 96
# offical = 90 degrees 50'
# civil = 96 degrees
# nautical = 102 degrees
# astronomical = 108 degrees
#1- calculate the day of year
n1 = math.floor( 275 * in_month / 9 )
n2 = math.floor( ( in_month + 9 ) / 12 )
n3 = ( 1 + math.floor( in_year - 4 * math.floor( in_year / 4 ) + 2 ) / 3 )
new_day = n1 - ( n2 * n3 ) + in_day - 30
print "new_day ", new_day
#2- calculate rising / setting time
if is_rise:
rise_or_set_time = new_day + ( ( 6 - ( long / 15 ) ) / 24 )
else:
rise_or_set_time = new_day + ( ( 18 - ( long/ 15 ) ) / 24 )
print "rise / set", rise_or_set_time
#3- calculate sun mean anamoly
sun_mean_anomaly = ( 0.9856 * rise_or_set_time ) - 3.289
print "sun mean anomaly", sun_mean_anomaly
#4 calculate true longitude
true_long = ( sun_mean_anomaly +
( 1.916 * math.sin( math.radians( sun_mean_anomaly ) ) ) +
( 0.020 * math.sin( 2 * math.radians( sun_mean_anomaly ) ) ) +
282.634 )
print "true long ", true_long
# make sure true_long is within 0, 360
if true_long < 0:
true_long = true_long + 360
elif true_long > 360:
true_long = true_long - 360
else:
true_long
print "true long (360 if) ", true_long
#5 calculate s_r_a (sun_right_ascenstion)
s_r_a = math.degrees( math.atan( 0.91764 * math.tan( math.radians( true_long ) ) ) )
print "s_r_a is ", s_r_a
#make sure it's between 0 and 360
if s_r_a < 0:
s_r_a = s_r_a + 360
elif true_long > 360:
s_r_a = s_r_a - 360
else:
s_r_a
print "s_r_a (modified) is ", s_r_a
# s_r_a has to be in the same Quadrant as true_long
true_long_quad = ( math.floor( true_long / 90 ) ) * 90
s_r_a_quad = ( math.floor( s_r_a / 90 ) ) * 90
s_r_a = s_r_a + ( true_long_quad - s_r_a_quad )
print "s_r_a (quadrant) is ", s_r_a
# convert s_r_a to hours
s_r_a = s_r_a / 15
print "s_r_a (to hours) is ", s_r_a
#6- calculate sun diclanation in terms of cos and sin
sin_declanation = 0.39782 * math.sin( math.radians ( true_long ) )
cos_declanation = math.cos( math.asin( sin_declanation ) )
print " sin/cos declanations ", sin_declanation, ", ", cos_declanation
# sun local hour
cos_hour = ( math.cos( math.radians( zenith ) ) -
( sin_declanation * math.sin( math.radians ( lat ) ) ) /
( cos_declanation * math.cos( math.radians ( lat ) ) ) )
print "cos_hour ", cos_hour
# extreme north / south
if cos_hour > 1:
print "Sun Never Rises at this location on this date, exiting"
# sys.exit()
elif cos_hour < -1:
print "Sun Never Sets at this location on this date, exiting"
# sys.exit()
print "cos_hour (2)", cos_hour
#7- sun/set local time calculations
if is_rise:
sun_local_hour = ( 360 - math.degrees(math.acos( cos_hour ) ) ) / 15
else:
sun_local_hour = math.degrees( math.acos( cos_hour ) ) / 15
print "sun local hour ", sun_local_hour
sun_event_time = sun_local_hour + s_r_a - ( 0.06571 *
rise_or_set_time ) - 6.622
print "sun event time ", sun_event_time
#final result
time_in_utc = sun_event_time - ( long / 15 ) + utc_time_zone
return time_in_utc
#test through main
def main():
print "Time of day App "
# test: fredericton, NB
# answer: 7:34 am
long = 66.6
lat = -45.9
utc_time = -4
d = 3
m = 3
y = 2010
is_rise = True
tod = TimeOfDay()
print "TOD is ", tod.calculate_time(d, m, y, lat, long, is_rise, utc_time)
if __name__ == "__main__":
main()
I'm trying to calculate the sunset / rise times using python based on the link provided below.
My results done through excel and python do not match the real values. Any ideas on what I could be doing wrong?
My Excel sheet can be found under .. http://transpotools.com/sun_time.xls
# Created on 2010-03-28
# @author: dassouki
# @source: [http://williams.best.vwh.net/sunrise_sunset_algorithm.htm][2]
# @summary: this is based on the Nautical Almanac Office, United States Naval
# Observatory.
import math, sys
class TimeOfDay(object):
def calculate_time(self, in_day, in_month, in_year,
lat, long, is_rise, utc_time_zone):
# is_rise is a bool when it's true it indicates rise,
# and if it's false it indicates setting time
#set Zenith
zenith = 96
# offical = 90 degrees 50'
# civil = 96 degrees
# nautical = 102 degrees
# astronomical = 108 degrees
#1- calculate the day of year
n1 = math.floor( 275 * in_month / 9 )
n2 = math.floor( ( in_month + 9 ) / 12 )
n3 = ( 1 + math.floor( in_year - 4 * math.floor( in_year / 4 ) + 2 ) / 3 )
new_day = n1 - ( n2 * n3 ) + in_day - 30
print "new_day ", new_day
#2- calculate rising / setting time
if is_rise:
rise_or_set_time = new_day + ( ( 6 - ( long / 15 ) ) / 24 )
else:
rise_or_set_time = new_day + ( ( 18 - ( long/ 15 ) ) / 24 )
print "rise / set", rise_or_set_time
#3- calculate sun mean anamoly
sun_mean_anomaly = ( 0.9856 * rise_or_set_time ) - 3.289
print "sun mean anomaly", sun_mean_anomaly
#4 calculate true longitude
true_long = ( sun_mean_anomaly +
( 1.916 * math.sin( math.radians( sun_mean_anomaly ) ) ) +
( 0.020 * math.sin( 2 * math.radians( sun_mean_anomaly ) ) ) +
282.634 )
print "true long ", true_long
# make sure true_long is within 0, 360
if true_long < 0:
true_long = true_long + 360
elif true_long > 360:
true_long = true_long - 360
else:
true_long
print "true long (360 if) ", true_long
#5 calculate s_r_a (sun_right_ascenstion)
s_r_a = math.degrees( math.atan( 0.91764 * math.tan( math.radians( true_long ) ) ) )
print "s_r_a is ", s_r_a
#make sure it's between 0 and 360
if s_r_a < 0:
s_r_a = s_r_a + 360
elif true_long > 360:
s_r_a = s_r_a - 360
else:
s_r_a
print "s_r_a (modified) is ", s_r_a
# s_r_a has to be in the same Quadrant as true_long
true_long_quad = ( math.floor( true_long / 90 ) ) * 90
s_r_a_quad = ( math.floor( s_r_a / 90 ) ) * 90
s_r_a = s_r_a + ( true_long_quad - s_r_a_quad )
print "s_r_a (quadrant) is ", s_r_a
# convert s_r_a to hours
s_r_a = s_r_a / 15
print "s_r_a (to hours) is ", s_r_a
#6- calculate sun diclanation in terms of cos and sin
sin_declanation = 0.39782 * math.sin( math.radians ( true_long ) )
cos_declanation = math.cos( math.asin( sin_declanation ) )
print " sin/cos declanations ", sin_declanation, ", ", cos_declanation
# sun local hour
cos_hour = ( math.cos( math.radians( zenith ) ) -
( sin_declanation * math.sin( math.radians ( lat ) ) ) /
( cos_declanation * math.cos( math.radians ( lat ) ) ) )
print "cos_hour ", cos_hour
# extreme north / south
if cos_hour > 1:
print "Sun Never Rises at this location on this date, exiting"
# sys.exit()
elif cos_hour < -1:
print "Sun Never Sets at this location on this date, exiting"
# sys.exit()
print "cos_hour (2)", cos_hour
#7- sun/set local time calculations
if is_rise:
sun_local_hour = ( 360 - math.degrees(math.acos( cos_hour ) ) ) / 15
else:
sun_local_hour = math.degrees( math.acos( cos_hour ) ) / 15
print "sun local hour ", sun_local_hour
sun_event_time = sun_local_hour + s_r_a - ( 0.06571 *
rise_or_set_time ) - 6.622
print "sun event time ", sun_event_time
#final result
time_in_utc = sun_event_time - ( long / 15 ) + utc_time_zone
return time_in_utc
#test through main
def main():
print "Time of day App "
# test: fredericton, NB
# answer: 7:34 am
long = 66.6
lat = -45.9
utc_time = -4
d = 3
m = 3
y = 2010
is_rise = True
tod = TimeOfDay()
print "TOD is ", tod.calculate_time(d, m, y, lat, long, is_rise, utc_time)
if __name__ == "__main__":
main()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用
ephem
python 模块:示例:
输出:
You could use
ephem
python module:Example:
Output:
为什么要调用
弧度
和度
?我认为输入数据已经是十进制度了。如果我执行以下操作,则得到上午 7:37 的结果:
45.9
和-66.6
分别编辑:
正如 JF Sebastian 指出的那样,根据问题中链接的电子表格以及使用
ephem
的 Observer 类提供的答案,该位置日出时间的答案位于 07:01 区域-07:02。一旦我得到了正确的大概数字(实现中的评论中的 07:34),我就不再寻找 dassouki 实现美国海军天文台算法的错误。
仔细研究一下,该算法进行了一些简化,并且关于“日出”的构成存在变化,其中一些内容已讨论 此处。然而,根据我最近在这件事上了解到的情况来看,这些变化应该只会导致日出时间的差异几分钟,而不是超过半个小时。
Why all the calls to
radians
anddegrees
? I thought the input data was already in decimal degrees.I get a result of 7:37am if I:
45.9
and-66.6
respectivelyEdit:
As J. F. Sebastian points out, the answer for the sunrise time at this location according to the spreadsheet linked in the question and the answer provided by using the Observer class of the
ephem
are in the region of 07:01-07:02.I stopped looking for errors in dassouki's implementation of the US Naval Observatory's algorithm once I got a figure in the right ballpark (07:34 in the comments in the implementation).
Looking into it, this algorithm makes some simplifications and there is variation about what constitutes 'sunrise', some of this is discussed here. However, in my opinion from what I've recently learnt on this matter, these variations should only lead to a difference of a few minutes in sunrise time, rather than over half an hour.
我怀疑这与没有实际执行浮点除法有关。在 python 中,如果 a 和 b 都是整数,则 a / b 也是整数:
您的选择是强制浮动您的参数之一(即,而不是 a/b 执行 float(a) / b)或确保“/”以 Python 3K 方式正常运行:
因此,如果您将该 import 语句粘贴在文件顶部,它可能会解决您的问题。现在 / 总是会产生一个浮点数,要获得旧的行为,您可以使用 // 代替。
I suspect this has something to do with not actually performing floating point division. In python if a and b are both integers, a / b is also an integer:
Your options are either to coerce to float one of your arguments (that is, instead of a/b do a float(a) / b) or to make sure the '/' behaves properly in a Python 3K way:
So if you stick that import statement at the top of your file, it may fix your problem. Now / will always produce a float, and to get the old behaviour you can use // instead.